On 14/01/2013 at 06:15, xxxxxxxx wrote:
Originally posted by xxxxxxxx
But I can't find anything even loosely resembling this in any form in the SDK:
MSG_RETRIEVE_MY_BITMAPBUTTON_IMAGE
There are hundreds of messages in the SDK.
Maybe I'm just not seeing it due to the sheer volume of them?
Hello Scott,
MSG_RETRIEVE_MY_BITMAPBUTTON_IMAGE is not defined in any of the Cinema 4D headers. It is your own message type. You need to retrieve an id from the plugincafe for it to make sure it does not clash with any other message type and some NodeData recieving that message thinks it should work with it because it thinks the message you've sent is some other message (the message type it clashes with). The name is, btw, really awkward, I'm giving it another name in the code below..
So, here's again the theory I was thinking of, but more expanded (including partial implementation of what the TagData subclass should do).
#include <c4d.h>
enum {
// Registered at plugincafe.com !
PMSG_GETSAMPLEIMAGE = 1029665,
};
class PMSG_GetSampleImageData {
public:
BaseBitmap* bmp;
Bool supported;
PMSG_GetSampleImageData()
: bmp(NULL), supported(FALSE) {};
};
class MyDialog : public GeDialog {
// {static}
private:
static BaseBitmap* defaultImage;
public:
static Bool InitStatic() {
defaultImage = BaseBitmap::Alloc();
if (!defaultImage) {
return FALSE;
}
// Load the default image, from wherever..
return TRUE;
}
// {instance}
private:
BitmapButtonCustomGui* bmpButton;
public:
// {GeDialog} Overrides
Bool CreateLayout() {
// Create layout and `bmpButton`.
return TRUE;
}
Bool CoreMessage(LONG msgType, const BaseContainer& msg) {
Bool result = GeDialog::Message(msgType, msg);
switch (msgType) {
case EVMSG_CHANGE: {
BaseDocument* doc = GetActiveDocument();
BaseTag* tag = doc->GetActiveTag();
if (!tag) return TRUE;
// As we use the message channels of Cinema 4D, we can
// preform this action on any tag.
PMSG_GetSampleImageData data;
tag->Message(PMSG_GETSAMPLEIMAGE, (void* ) &data);
Bool isSet = FALSE;
if (data.supported) {
if (data.bmp) {
Bool copyImage = TRUE;
bmpButton->setImage(data.bmp, copyImage);
isSet = TRUE;
}
}
if (!isSet) {
bmpButton->setImage(GeDialog::defaultImage);
}
break;
}
default:
break;
}
return result;
}
};
class MyTag : public TagData {
// {instance}
private:
BaseBitmap* image;
public:
Bool Message(LONG msgType, void* msgData) {
Bool result = TagData::Message(msgType, msgData);
switch (msgType) {
// Handle our custom message here !
case PMSG_GETSAMPLEIMAGE: {
// C++11 Feature!
auto data = (PMSG_GetSampleImageData* ) msgData;
data->supported = TRUE;
data->bmp = image;
}
default:
break;
}
return result;
}
};
/* ... */
Bool PluginStart() {
Bool success;
success = MyDialog::InitStatic();
if (!success) {
MessageDialog("MyDialog class could not initialize internals.");
return FALSE;
}
// Register Command and Tag and stuff you need..
}
Note: I hope there are no syntax errors or typos in it, I didn't have the time to actually compile it, that is also why this is just a snippet.
General notes about your code
The following is based on the code you shared in [this post.
](https://plugincafe.maxon.net/topic/6851/7642_allowing-plugins-to-talk-to-eachother&PID=31691#31691)
- Line 33:
myDialog *dlg;
I wonder why you would want to store a reference to another dialog in the dialog itself? - Line 52:
myDialog::~myDialog(void)
{
GeFree(dlg);
}
You are freeing an uninitialized variable here. I really wonder why Cinema doesn't crash when this destructor is called. - Line 230:
Bool SimpleTag::Write(GeListNode *node, HyperFile *hf)
{
hf->WriteImage(bmp,FILTER_JPG,NULL,SAVEBIT_0);
return TRUE;
}
The SDK does not state anything about passing a nullpointer for bmp. I would not assume it to be safe, therefore you should find another way than just passing the bitmap-pointer to this method. (E.g. first something like this hf->WriteBool(bmp != NULL); ) - Line 255:
void SimpleTag::createImage(void)
{
BaseDocument *doc = GetActiveDocument();
bmp = BaseBitmap::Alloc();
/* ... */
You do not free the bitmap that might have been allocated before (i.e. when createImage() is called twice, are an image has already been loaded from the HyperFile). You should add the following lines:
// Check if we already have a bitmap stored on this tag. If not,
// we need to allocate a new bitmap.
if (bmp) {
bmp->FlushAll();
}
else {
bmp = BaseBitmap::Alloc();
}
if (!bmp) {
// Handle memory error here..
}
Best,
Niklas