About

NodeData based classic plugin classes can implement NodeData::Message() to receive various messages that are sent for several reasons. This page shows how to handle the most important messages.

Note
Messages sent to C4DAtom::Message() and received by NodeData::Message() are synchronous messages.

NodeData::Message() corresponds to C4DAtom::Message() and C4DAtom::MultiMessage().

Usage

Basics

NodeData::Message() is called by Cinema 4D to inform the plugin class about an event or to request some information from it. Additional data is handed over in form of a void pointer that has to be cast into the correct type depending on the message.

// This example shows a primitive implementation of Message().
virtual Bool Message(GeListNode* node, Int32 type, void* data)
{
switch (type)
{
case (MSG_UPDATE):
{
break;
}
// more cases
Represents a C4DAtom that resides in a 4D list.
Definition: c4d_baselist.h:1976
maxon::Bool Bool
Definition: ge_sys_math.h:51
maxon::Int32 Int32
Definition: ge_sys_math.h:56
#define MSG_UPDATE
Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
Definition: c4d_baselist.h:359
PyObject ** type
Definition: pycore_pyerrors.h:34
Definition: node.h:10
Note
If the plugin class hosts a subshader, HandleShaderMessage() must be used to relay certain messages to this subshader. Especially MSG_GETALLASSETS, MSG_RENAMETEXTURES and MSG_MULTI_CLEARSUGGESTEDFOLDER should be handled.

Filter

With C4DAtom::MultiMessage() it is possible to send messages to the complete object hierarchy or branches (see also Heads and Branches). In this case it is possible to filter certain messages so they are not sent to the child elements of the given element.

Return true to let the message pass and false to block it.

The data of this message is MessageFilter:

Data

Messages can be used to retrieve data from an entity. For generic purposes this message exists:

The data of this message is RetrievePrivateData:

// This example sends MSG_RETRIEVEPRIVATEDATA to the generator to get its internal data.
data.flags = 0;
data.data = nullptr;
// send message to retrieve private data
if (object->Message(MSG_RETRIEVEPRIVATEDATA, &data))
{
// got data
if (data.data != nullptr)
{
Int32* const value = static_cast<Int32*>(data.data);
ApplicationOutput("Got value: @"_s, *value);
}
}
PyObject * value
Definition: abstract.h:715
#define MSG_RETRIEVEPRIVATEDATA
A generic private message to retrieve data from an object. Specific for every type of object so no pu...
Definition: c4d_baselist.h:405
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204
Definition: object.h:105
Definition: c4d_baselist.h:881
Int32 flags
The flags for the retrieval.
Definition: c4d_baselist.h:887
void * data
The address returned.
Definition: c4d_baselist.h:888
// This example receives a MSG_RETRIEVEPRIVATEDATA message
// and sets the pointer to the internal data.
{
RetrievePrivateData* const pdata = static_cast<RetrievePrivateData*>(data);
if (pdata)
{
pdata->data = &(this->_value);
return true;
}
break;
}

Assets

Plugins use external assets typically by referencing the asset file in a Filename parameter. When the document is saved with "Save Project with Assets" or is rendered via Team Render these assets have to be collected. To collect these assets Cinema 4D sends these messages to all scene elements:

Warning
MSG_GETALLASSETS is not sent to MaterialData plugins.
// This example adds the file path stored in a parameter to the asset list.
{
AssetData* const assetData = static_cast<AssetData*>(data);
if (assetData == nullptr)
return true;
// checks if only texture assets should be added
return true;
BaseList2D* const baseList2D = static_cast<BaseList2D*>(node);
if (baseList2D)
{
// get the file name
const Filename path = baseList2D->GetDataInstanceRef().GetFilename(EXAMPLE_GENERATOR_PARAMETER_FILE);
// check if the file name is set
if (path.IsPopulated())
{
// add the file name
assetData->Add(path, nullptr);
}
}
break;
}
// This example removes the folder part of the file path of the object's parameter.
{
BaseContainer& bc = (static_cast<BaseList2D*>(node))->GetDataInstanceRef();
const Filename path = bc.GetFilename(EXAMPLE_GENERATOR_PARAMETER_FILE);
// check if the directory part of the path contains anything
if (path.GetDirectory().IsPopulated())
{
bc.SetFilename(EXAMPLE_GENERATOR_PARAMETER_FILE, path.GetFile());
}
break;
}
Definition: c4d_basecontainer.h:48
Filename GetFilename(Int32 id, const Filename &preset=Filename()) const
Definition: c4d_basecontainer.h:448
void SetFilename(Int32 id, const Filename &f)
Definition: c4d_basecontainer.h:665
Definition: c4d_baselist.h:2377
const BaseContainer & GetDataInstanceRef() const
Definition: c4d_baselist.h:2518
Manages file and path names.
Definition: c4d_file.h:94
const Filename GetDirectory() const
const Filename GetFile() const
Bool IsPopulated() const
@ TEXTURESONLY
Only return texture assets.
#define MSG_MULTI_CLEARSUGGESTEDFOLDER
Definition: c4d_baselist.h:557
#define MSG_GETALLASSETS
Definition: c4d_shader.h:1210
struct _node node
Definition: c4d_baselist.h:1211
ASSETDATA_FLAG _flags
The asset data flags: ASSETDATA_FLAG.
Definition: c4d_baselist.h:1222
Bool Add(const Filename &fn, BaseList2D *bl, Int32 parameterId=-1, Bool netRequestOnDemand=false, Int32 channelIndex=-1, const maxon::CString &nodePath=maxon::GetZeroRef< maxon::CString >(), const maxon::Id &nodeSpace=maxon::GetZeroRef< maxon::Id >())

Further asset related messages are:

  • MSG_MULTI_MARKMATERIALS: When the given data is nullptr this is sent to scene elements to let them mark the materials they use (with BIT_MATMARK). Otherwise the message is sent to get material links translated, for example when a material is replaced. In this case the corresponding data is MarkMaterials. This is needed for example when an object that is using a material is copied.
  • MSG_RENAMETEXTURES: This message is sent to all scene elements when a bitmap image was renamed (e.g. by "Save Project" or by BodyPaint 3D) and all shaders etc. need to adjust the name. The message data is RenameTextureMessage.

See also BaseDocument Convert and Export and Disc I/O.

Icon

Cinema 4D sends a message to ObjectData and TagData based plugins so they can change their icon dynamically.

The data of this message is GetCustomIconData:

// This example simply sets a standard icon as the object's icon.
{
// get data
GetCustomIconData* const iconData = static_cast<GetCustomIconData*>(data);
if (iconData == nullptr)
return true;
// set as filled
iconData->filled = true;
// load a standard Cinema icon
return GetIcon(RESOURCEIMAGE_OK, iconData->dat);
}
#define MSG_GETCUSTOMICON
Every atom can return a custom icon with this message. The corresponding data is GetCustomIconData.
Definition: c4d_baselist.h:459
#define RESOURCEIMAGE_OK
Definition: ge_prepass.h:3701
Bool GetIcon(Int32 lIconID, IconData *pData)
Message struct for the MSG_GETCUSTOMICON message.
Definition: c4d_baselist.h:1279
IconData * dat
Definition: c4d_baselist.h:1285
Bool filled
Set this to true if the icon data dat was changed or set.
Definition: c4d_baselist.h:1287

An object or tag can include the ID_BASELIST_ICON_SETTINGS_GROUP parameter group. It is possible to add a custom color mode to that group and to define that custom color when reacting to MSG_GETCUSTOMICON.

// This example adds a new color mode to the object's "Icon Settings" in the Init() function.
BaseObject* const op = static_cast<BaseObject*>(node);
BaseContainer* const bc = op->GetDataInstance();
// add custom color mode
BaseContainer iconSettings, iconSpecialModes;
iconSpecialModes.SetString(0, "Custom Color Mode"_s);
iconSettings.SetContainer(ID_ICONCHOOSER_SETTINGS_SPECIALCASES, iconSpecialModes);
// set icon settings container into baselist2d data container
// default color mode: custom mode
void SetContainer(Int32 id, const BaseContainer &s)
Definition: c4d_basecontainer.h:679
void SetString(Int32 id, const maxon::String &s)
Definition: c4d_basecontainer.h:651
void SetInt32(Int32 id, Int32 l)
Definition: c4d_basecontainer.h:587
Definition: c4d_baseobject.h:248
@ ID_ICONCHOOSER_SETTINGS_SPECIALCASES
Definition: customgui_iconchooser.h:33
#define ID_ICONCHOOSER_SETTINGS
Id to store icon settings data into BaseList2D basecontainer.
Definition: customgui_iconchooser.h:29
@ ID_BASELIST_ICON_COLORIZE_MODE
Definition: obaselist.h:10
@ ID_BASELIST_ICON_COLORIZE_MODE_CUSTOM
Definition: obaselist.h:12
PyObject * op
Definition: object.h:520
// This example defines the color of the custom color mode as well as the ID of the used icon.
{
GetCustomIconData* const cid = static_cast<GetCustomIconData*>(data);
if (cid == nullptr)
return false;
BaseObject* const baseObject = static_cast<BaseObject*>(node);
const BaseContainer& bc = baseObject->GetDataInstanceRef();
// define color for custom color mode
FillCustomIconSettingsFromBaseList2D(settings, bc, node->GetType(), true);
settings._specialColors.Resize(1) iferr_ignore("Can't do anything about it here."_s);
// get some float value from the object itself
GeData parameterData;
node->GetParameter(ConstDescID(DescLevel(ICONTEST_OBJECT_VALUE)), parameterData, DESCFLAGS_GET::NONE);
// create RGB value for custom color mode
const maxon::Float value = parameterData.GetFloat() / 360.0;
const maxon::Color hsv { value, 1.0, 1.0 };
const maxon::Color rgb = maxon::HsvToRgb(hsv);
// set custom color
settings._specialColors[0] = rgb;
// callback defining the icon ID
CustomIconGetIdDelegate getIdCallback = [node]() -> Int32
{
// read a parameter from the object
GeData data;
node->GetParameter(ConstDescID(DescLevel(ICONTEST_OBJECT_ID)), data, DESCFLAGS_GET::NONE);
const Int32 id = data.GetInt32();
// set the icon ID based on that parameter value
if (id > 0)
return Ocube;
return Osphere;
};
// define custom ID
GetCustomIcon(*cid, settings, false, &getIdCallback);
break;
}
Definition: c4d_gedata.h:83
Int32 GetInt32() const
Definition: c4d_gedata.h:456
Float GetFloat() const
Definition: c4d_gedata.h:468
Definition: delegate.h:240
Bool GetCustomIcon(GetCustomIconData &cid, const CustomIconSettings &settings, Bool drawBeforeColoring=false, CustomIconGetIdDelegate *getIdCallback=nullptr, CustomIconDrawDelegate *drawCallback=nullptr)
void FillCustomIconSettingsFromBaseList2D(CustomIconSettings &settings, const BaseContainer &data, Int32 defaultIconId, Bool fillDefault)
Private.
Float64 Float
Definition: apibase.h:211
#define Ocube
Cube.
Definition: ge_prepass.h:1119
#define Osphere
Sphere.
Definition: ge_prepass.h:1120
#define ConstDescID(...)
Definition: lib_description.h:594
MAXON_ATTRIBUTE_FORCE_INLINE COLORTYPE HsvToRgb(const COLORTYPE &hsv)
Definition: gfx_image_functions_color_conversions.h:51
#define iferr_ignore(...)
Definition: resultbase.h:1489
Definition: c4d_baselist.h:1426
maxon::BaseArray< maxon::Color > _specialColors
Special colors (e.g. Light Color for light object)
Definition: c4d_baselist.h:1430
Represents a level within a DescID.
Definition: lib_description.h:298

Interaction

It is possible to drag and drop something onto objects and tags in the Object Manager. These elements are informed about this event with this message:

  • MSG_DRAGANDDROP: Received by an element in the Object Manager when something is dropped on it. The corresponding data is DragAndDrop.
// This example checks if the file dropped onto an object is neither image nor scene file.
// If so, the file path will be stored in one of the object's parameters.
{
// get data
DragAndDrop* const dnd = static_cast<DragAndDrop*>(data);
if (dnd == nullptr)
return false;
// ignore this when the object itself is dragged
return true;
// check if a file (scene or image) is dragged onto the object
const Bool typeIsNotFilename = dnd->type != DRAGTYPE_FILENAME_OTHER;
const Bool dataNotSet = dnd->data == nullptr;
if (typeIsNotFilename || dataNotSet)
return false;
// drop
{
// get filename
Filename* const file = static_cast<Filename*>(dnd->data);
// set parameter
node->SetParameter(ConstDescID(DescLevel(EXAMPLE_GENERATOR_PARAMETER_FILE)), *file, DESCFLAGS_SET::NONE);
}
return true;
}
@ DRAGTYPE_FILENAME_OTHER
Other filename.
Definition: gui.h:788
#define DRAGANDDROP_FLAG_SOURCE
Drag and drop message is send to the source objects (objects that were dragged).
Definition: c4d_baselist.h:951
#define DRAGANDDROP_FLAG_ACCEPT
Accept.
Definition: c4d_baselist.h:947
#define DRAGANDDROP_FLAG_DROP
Drop.
Definition: c4d_baselist.h:946
#define MSG_DRAGANDDROP
Received by an element in the Object manager when something is dropped on it. The corresponding data ...
Definition: c4d_baselist.h:464
const char const char const char * file
Definition: object.h:439
Message struct for the MSG_DRAGANDDROP message.
Definition: c4d_baselist.h:968
UInt32 flags
Definition: c4d_baselist.h:976
void * data
The pointer to the dragged elements. Depends on the drag type.
Definition: c4d_baselist.h:979
Int32 type
The drag type: DRAGTYPE.
Definition: c4d_baselist.h:978

When the user double clicks on an icon in the Object Manger this message is sent to the corresponding element.

// This example simply opens a message dialog when one
// double-clicks on the icon in the Object Manager.
case MSG_EDIT:
{
MessageDialog("You double-clicked on this object!"_s);
break;
}
void MessageDialog(const maxon::String &str)
#define MSG_EDIT
Allows elements to do some action if the user edits the element (double-click e.g....
Definition: c4d_baselist.h:403

Attribute Manager Interaction

Users edit scene elements and their parameters with the Attribute Manager. The Attribute Manager sends multiple messages to the edited object to inform about the interaction.

// This example just opens a message dialog when a button was pressed.
{
if (dc == nullptr)
return false;
// check the ID of the pressed button
if (dc->_descId[0].id == EXAMPLE_GENERATOR_BUTTON)
{
MessageDialog("You pressed the button."_s);
}
break;
}
#define MSG_DESCRIPTION_COMMAND
Sent by for example BUTTON description element. The corresponding data is DescriptionCommand.
Definition: c4d_baselist.h:395
DescID _descId
Description ID of the parameter that triggered the command.
Definition: lib_description.h:940
Message struct for MSG_DESCRIPTION_COMMAND.
Definition: lib_description.h:948

Further messages are:

// This example defines the content of a popup menu of a "POPUP" parameter element.
{
DescriptionPopup* const dp = static_cast<DescriptionPopup*>(data);
// check the ID of the popup element
if (dp->_descId[0] == EXAMPLE_GENERATOR_POPUP)
{
// if nothing is chosen
// the menu should be build
if (dp->_chosen == 0)
{
menu.InsData(1, "Options"_s);
menu.InsData(10, "Option A"_s);
menu.InsData(20, "Option B"_s);
dp->_popup.InsData(0, menu);
}
else
{
const Int32 option = dp->_chosen;
ApplicationOutput("You chose option @", option);
}
}
break;
}
GeData * InsData(Int32 id, const GeData &n)
Definition: c4d_basecontainer.h:258
#define MSG_DESCRIPTION_POPUP
Allows popup menu handling in the Attribute Manager. The corresponding data is DescriptionPopup.
Definition: c4d_baselist.h:396
Message struct for MSG_DESCRIPTION_POPUP.
Definition: lib_description.h:958
BaseContainer _popup
Popup container.
Definition: lib_description.h:961
Int32 _chosen
Selected element of the popup.
Definition: lib_description.h:959
// This example receives a custom GUI messages sent from
// the Attribute Manager. If the messages is sent from
// a specific custom GUI type, the message data is printed.
{
if (dcgn)
{
// get parameter ID
const Int32 parameterID = dcgn->_descId[-1].id;
ApplicationOutput("Message from parameter: " + String::IntToString(parameterID));
// check the type of custom GUI
if (dcgn->_customGuiId == ID_CUSTOMGUI_COLORSTRING_GFG)
{
// check the message ID
if (dcgn->_subId == MSG_DESCRIPTION_COLORSTRING_COLORCHANGE)
{
// get data from the message
const BaseContainer* messageData = dcgn->_data;
if (messageData)
{
const Vector color = messageData->GetVector(MSG_DESCRIPTION_COLORSTRING_COLOR);
ApplicationOutput("New Color: " + String::VectorToString(color));
}
}
}
}
break;
}
Vector GetVector(Int32 id, const Vector &preset=Vector()) const
Definition: c4d_basecontainer.h:416
static String IntToString(Int32 v)
Definition: c4d_string.h:497
static String VectorToString(const Vector32 &v, Int32 nnk=-1)
Definition: c4d_string.h:573
#define MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION
Sent by a custom GUI to the parent. The corresponding data is DescriptionCustomGuiNotification.
Definition: c4d_baselist.h:425
Definition: lib_description.h:1008
const BaseContainer * _data
The data of the message, can be nullptr.
Definition: lib_description.h:1011
Int32 _customGuiId
The custom GUI plugin ID.
Definition: lib_description.h:1009
Int32 _subId
The message type sub-ID. Depending on the custom GUI implementation a different sub-ID can be passed ...
Definition: lib_description.h:1010

See also Description Notifications.

These messages are related to the Take system:

Creation

  • MSG_MENUPREPARE: Allows tags, objects, shaders etc. to do some setup work when called from the menu. The corresponding data is the current BaseDocument. Is called before the object is added to the document.
// This example adds a tag to the object when it is created from the menu.
{
BaseObject* const op = static_cast<BaseObject*>(node);
BaseTag* const annotationTag = op->MakeTag(Tannotation);
if (annotationTag)
{
const String annotation { "This is a new object." };
}
break;
}
Definition: c4d_basetag.h:52
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
Definition: c4d_string.h:41
#define MSG_MENUPREPARE
Allows tags, objects, shaders etc. to do some setup work when called from the menu....
Definition: c4d_baselist.h:404
#define Tannotation
Annotation.
Definition: ge_prepass.h:1418
@ ANNOTATIONTAG_TEXT
Definition: tannotation.h:21

Document Related

Certain events trigger a broadcast message that is sent to all elements of a BaseDocument.

Some messages are just send to SceneHookData plugins. See also BaseDocument::SendInfo().

// This example catches MSG_DOCUMENTINFO in a ObjectData::Message() function.
// When the document is loaded the value of a old (legacy) parameter is copied
// into a new parameter.
{
DocumentInfoData* const msg = static_cast<DocumentInfoData*>(data);
if (msg == nullptr)
return false;
// switch message sub-type
switch (msg->type)
{
{
BaseObject* const op = static_cast<BaseObject*>(node);
if (!op)
return false;
BaseContainer& bc = op->GetDataInstanceRef();
bc.SetInt32(NEW_PARAMETER, bc.GetInt32(OLD_PARAMETER));
ApplicationOutput("document is loaded"_s);
break;
}
}
break;
}
Int32 GetInt32(Int32 id, Int32 preset=0) const
Definition: c4d_basecontainer.h:348
#define MSG_DOCUMENTINFO_TYPE_LOAD
Document was loaded.
Definition: c4d_baselist.h:480
#define MSG_DOCUMENTINFO
Sent as broadcast message by the document when it is loaded, saved , merged etc. The corresponding da...
Definition: c4d_baselist.h:469
const char const char * msg
Definition: object.h:438
Message struct for the MSG_DOCUMENTINFO message.
Definition: c4d_baselist.h:1154

Also these messages are sent to all elements:

A special message is sent when the element is animated:

  • MSG_ANIMATE: Sent to elements after they have been animated. Only sent to objects with keyframes.

Further Reading