Open Search

    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:1813
    maxon::Bool Bool
    Definition: ge_sys_math.h:55
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define MSG_UPDATE
    Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
    Definition: c4d_baselist.h:341
    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:386
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210
    Definition: object.h:105
    Definition: c4d_baselist.h:843
    Int32 flags
    The flags for the retrieval.
    Definition: c4d_baselist.h:849
    void * data
    The address returned.
    Definition: c4d_baselist.h:850
    // 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->GetData().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:47
    Filename GetFilename(Int32 id, const Filename &preset=Filename()) const
    Definition: c4d_basecontainer.h:403
    void SetFilename(Int32 id, const Filename &f)
    Definition: c4d_basecontainer.h:583
    Definition: c4d_baselist.h:2190
    BaseContainer GetData()
    Definition: c4d_baselist.h:2311
    Manages file and path names.
    Definition: c4d_file.h:94
    Bool IsPopulated() const
    const Filename GetFile(void) const
    const Filename GetDirectory(void) const
    @ TEXTURESONLY
    Only return texture assets.
    #define MSG_MULTI_CLEARSUGGESTEDFOLDER
    Definition: c4d_baselist.h:516
    #define MSG_GETALLASSETS
    Definition: c4d_shader.h:1133
    struct _node node
    Definition: c4d_baselist.h:1068
    ASSETDATA_FLAG _flags
    The asset data flags: ASSETDATA_FLAG.
    Definition: c4d_baselist.h:1079
    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:440
    #define RESOURCEIMAGE_OK
    Definition: ge_prepass.h:3690
    Bool GetIcon(Int32 lIconID, IconData *pData)
    Message struct for the MSG_GETCUSTOMICON message.
    Definition: c4d_baselist.h:1136
    IconData * dat
    Definition: c4d_baselist.h:1142
    Bool filled
    Set this to true if the icon data dat was changed or set.
    Definition: c4d_baselist.h:1144

    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);
    // since we are going to use our custom MSG_GETCUSTOMICONS code, set this to true so parent object (e.g. BaseObject) will ignore MSG_GETCUSTOMICONS messages.
    // set icon settings container into baselist2d data container
    // default color mode: custom mode
    void SetContainer(Int32 id, const BaseContainer &s)
    Definition: c4d_basecontainer.h:597
    void SetBool(Int32 id, Bool b)
    Definition: c4d_basecontainer.h:498
    void SetString(Int32 id, const maxon::String &s)
    Definition: c4d_basecontainer.h:569
    void SetInt32(Int32 id, Int32 l)
    Definition: c4d_basecontainer.h:505
    Definition: c4d_baseobject.h:225
    @ ID_ICONCHOOSER_SETTINGS_SPECIALCASES
    Definition: customgui_iconchooser.h:33
    @ ID_ICONCHOOSER_SETTINGS_PARENT_IGNORE
    Definition: customgui_iconchooser.h:34
    #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(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(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;
    }
    const BaseContainer & GetDataInstanceRef() const
    Definition: c4d_baselist.h:2344
    Definition: c4d_gedata.h:83
    Int32 GetInt32(void) const
    Definition: c4d_gedata.h:427
    Float GetFloat(void) const
    Definition: c4d_gedata.h:439
    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:197
    #define Ocube
    Cube.
    Definition: ge_prepass.h:1095
    #define Osphere
    Sphere.
    Definition: ge_prepass.h:1096
    MAXON_ATTRIBUTE_FORCE_INLINE COLORTYPE HsvToRgb(const COLORTYPE &hsv)
    Definition: gfx_image_functions_color_conversions.h:51
    #define iferr_ignore(...)
    Definition: resultbase.h:1430
    Definition: c4d_baselist.h:1283
    maxon::BaseArray< maxon::Color > _specialColors
    Special colors (e.g. Light Color for light object)
    Definition: c4d_baselist.h:1287

    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(EXAMPLE_GENERATOR_PARAMETER_FILE, *file, DESCFLAGS_SET::NONE);
    }
    return true;
    }
    @ DRAGTYPE_FILENAME_OTHER
    Other filename.
    Definition: gui.h:780
    #define DRAGANDDROP_FLAG_SOURCE
    Drag and drop message is send to the source objects (objects that were dragged).
    Definition: c4d_baselist.h:913
    #define DRAGANDDROP_FLAG_ACCEPT
    Accept.
    Definition: c4d_baselist.h:909
    #define DRAGANDDROP_FLAG_DROP
    Drop.
    Definition: c4d_baselist.h:908
    #define MSG_DRAGANDDROP
    Received by an element in the Object manager when something is dropped on it. The corresponding data ...
    Definition: c4d_baselist.h:444
    const char const char const char * file
    Definition: object.h:439
    Message struct for the MSG_DRAGANDDROP message.
    Definition: c4d_baselist.h:930
    UInt32 flags
    Definition: c4d_baselist.h:938
    void * data
    The pointer to the dragged elements. Depends on the drag type.
    Definition: c4d_baselist.h:941
    Int32 type
    The drag type: DRAGTYPE.
    Definition: c4d_baselist.h:940

    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:384

    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:376
    DescID _descId
    Description ID of the parameter that triggered the command.
    Definition: lib_description.h:845
    Message struct for MSG_DESCRIPTION_COMMAND.
    Definition: lib_description.h:853

    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:238
    #define MSG_DESCRIPTION_POPUP
    Allows popup menu handling in the Attribute Manager. The corresponding data is DescriptionPopup.
    Definition: c4d_baselist.h:377
    Message struct for MSG_DESCRIPTION_POPUP.
    Definition: lib_description.h:863
    BaseContainer _popup
    Popup container.
    Definition: lib_description.h:866
    Int32 _chosen
    Selected element of the popup.
    Definition: lib_description.h:864
    // 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:371
    static String IntToString(Int32 v)
    Definition: c4d_string.h:495
    static String VectorToString(const Vector32 &v, Int32 nnk=-1)
    Definition: c4d_string.h:571
    #define MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION
    Sent by a custom GUI to the parent. The corresponding data is DescriptionCustomGuiNotification.
    Definition: c4d_baselist.h:406
    Definition: lib_description.h:913
    const BaseContainer * _data
    The data of the message, can be nullptr.
    Definition: lib_description.h:916
    Int32 _customGuiId
    The custom GUI plugin ID.
    Definition: lib_description.h:914
    Int32 _subId
    The message type sub-ID. Depending on the custom GUI implementation a different sub-ID can be passed ...
    Definition: lib_description.h:915

    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." };
    annotationTag->SetParameter(ANNOTATIONTAG_TEXT, annotation, DESCFLAGS_SET::NONE);
    }
    break;
    }
    Definition: c4d_basetag.h:48
    Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
    Definition: c4d_string.h:39
    #define MSG_MENUPREPARE
    Allows tags, objects, shaders etc. to do some setup work when called from the menu....
    Definition: c4d_baselist.h:385
    #define Tannotation
    Annotation.
    Definition: ge_prepass.h:1390
    @ 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:303
    #define MSG_DOCUMENTINFO_TYPE_LOAD
    Document was loaded.
    Definition: c4d_baselist.h:459
    #define MSG_DOCUMENTINFO
    Sent as broadcast message by the document when it is loaded, saved , merged etc. The corresponding da...
    Definition: c4d_baselist.h:448
    const char const char * msg
    Definition: object.h:438
    Message struct for the MSG_DOCUMENTINFO message.
    Definition: c4d_baselist.h:1007

    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