c4d.plugins.NodeData

The base type for instantiable plugins. Use RegisterNodePlugin() to register the plugin.

Members

NodeData.InitAttr(host, type, id)

Initializes an object’s description parameter at id with its default value for the data type.

Just call this method in the Init() method of any node data class:

import c4d

def Init(self, node):
  self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_RAD])
  self.InitAttr(op, float, [c4d.PY_TUBEOBJECT_IRADX])

  node[c4d.PY_TUBEOBJECT_RAD]= 200.0
  node[c4d.PY_TUBEOBJECT_IRADX] = 50.0

See also

The Py-RoundedTube example and its Init() method.

Parameters:
  • host (c4d.BaseObject) – The host object.
  • type (type) – Just pass the type like float, int, PriorityData
  • id (c4d.DescID) – The parameter description ID to initialize. Check out the example above.
Return type:

bool

Returns:

True if the parameter could be successfully initialized, otherwise False.

NodeData.Init(self, node)

Override - Called when a new instance of the node plugin has been allocated.

Note

If your class has a constructor it is called as usual before this function, but at that time there’s no node link established.

Parameters:node (c4d.GeListNode) – The list node connected with this instance.
Return type:bool
Returns:True on success, otherwise False.

Warning

Please note, if you return False, the object will not be created.

NodeData.Free(self, node)

Override - If your class has a destructor it is called as usual after this function.

Parameters:node (c4d.GeListNode) – The list node connected with this instance.
NodeData.Read(self, node, hf, level)

Override - Called when a node is loaded from a file. Use this function to read any settings for your plugin that are not stored in the BaseContainer. You must read these settings from the HyperFile such as:

hf.ReadInt32(offset)
hf.ReadBool(object_access)

For future extensions of your plugin you should check the level and only read the appropriate values:

if level >= 0:
  hf.ReadInt32(offset)
  hf.ReadBool(object_access)
if level >= 1:
  hf->ReadFloat(a_new_feature)

Init() will have already been called before this function is called.

Note

It is recommended to store as much as possible in the BaseContainer as Cinema 4D will handle the reading of those values automatically. Only use member variables when necessary.

Important

If you implement at least one of Read(), Write() and CopyTo(), you must usually implement all three. Otherwise data might be lost.

Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • hf (c4d.GeListNode) – The hyper file to read the data from.
  • level (int) –

    The plugin level is similar to a version number for your settings. The default level is 0, you can then increase this for new revisions of your plugin, this allows for forward and backward compatibility.

    As an example you may have updated your plugin, if you now need to write additional information for new settings or changed types for old settings you can increase the level. During loading either a 0 is passed (if the file was written using your old plugin) or 1 (if the file was written by the new plugin). This allows you to easily save/read new values.

    Important

    For forward and backward compatibility to work you must not change any existing read order from a given level, Cinema 4D will skip any new settings automatically if they have not been read for your plugin.

    Note

    If you only use containers for all your values, you do not have to deal with level.

Return type:

bool

Returns:

True if the data was read successfully, otherwise False.

NodeData.Write(self, node, hf)

Override - Called when a node is saved to a file. Use this function to write any settings for your plugin that are not stored in the BaseContainer. You must read these settings from the HyperFile such as:

hf.WriteInt32(offset)
hf.WriteBool(object_access)

For future extensions of your plugin you should make sure to introduce a new level (See Read()) when writing new values:

// Level 0
hf.WriteInt32(offset)
hf.WriteBool(object_access)

// Level 1
hf.WriteFloat(a_new_feature)

Free() will be called after this function is called.

Note

It is recommended to store as much as possible in the BaseContainer as Cinema 4D will handle the writing of those values automatically. Only use member variables when necessary.

Important

If you implement at least one of Read(), Write() and CopyTo(), you must usually implement all three. Otherwise data might be lost.

Parameters:
Return type:

bool

Returns:

True if the data was written successfully, otherwise False.

NodeData.CopyTo(self, dest, snode, dnode, flags, trn)
Override - Called when a node is duplicated. Init() is called for the destination node before this function.
Use this function to copy any settings for the plugin that are not stored in the BaseContainer. Simply transfer them from the current node data to dest and/or snode to dnode:
dest.offset = offset
dest.object_access = object_access

Note

It is recommended to store as much as possible in the BaseContainer as Cinema 4D will handle the copying of those values automatically. Only use member variables when necessary.

Important

If at least one of Read(), Write() and CopyTo() is implemented, it is recommended to implement all three, otherwise data might be lost.

Parameters:
  • dest (c4d.plugins.NodeData) – The destination node data.
  • snode (c4d.GeListNode) – The source node data, i.e. the current node.
  • dnode (c4d.GeListNode) – The destination node data.
  • flags (int) –

    The copy flags:

    COPYFLAGS_0 None
    COPYFLAGS_NO_HIERARCHY Copy without children.
    COPYFLAGS_NO_ANIMATION Copy without tracks, sequences or keys.
    COPYFLAGS_NO_BITS Do not copy BaseList2D bits.
    COPYFLAGS_NO_MATERIALPREVIEW Do not create a new material preview.
    COPYFLAGS_NO_BRANCHES Do not copy branches, for example tags on an object. Automatically implies COPYFLAGS_NO_ANIMATION, as animation is a branch.
    COPYFLAGS_DOCUMENT This is a read-only flag that’s set when a complete document is copied.
    COPYFLAGS_NO_NGONS Do not copy N-gons.
    COPYFLAGS_CACHE_BUILD Build caches.
    COPYFLAGS_RECURSIONCHECK Checks and avoids instances to cause recursions.
    COPYFLAGS_PRIVATE_IDENTMARKER Private.
    COPYFLAGS_PRIVATE_NO_INTERNALS Private.
    COPYFLAGS_PRIVATE_NO_PLUGINLAYER Private.
    COPYFLAGS_PRIVATE_UNDO Private.
    COPYFLAGS_PRIVATE_CONTAINER_COPY_DIRTY Private.
    COPYFLAGS_PRIVATE_CONTAINER_COPY_IDENTICAL Private.
    COPYFLAGS_PRIVATE_BODYPAINT_NODATA Private.
    COPYFLAGS_PRIVATE_BODYPAINT_CONVERTLAYER Private.
  • trn (c4d.AliasTrans) –

    Changed in version R17.032.

    An alias translator for the operation.

Return type:

bool

Returns:

True if the data was copied successfully, otherwise False.

NodeData.Message(self, node, type, data)

Override - Called when a node receives messages.

Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • type (int) –

    The message ID, one of the following:

    MSG_POINTS_CHANGED The points have changed. The corresponding data is VariableChanged.
    MSG_POLYGONS_CHANGED The polygons have changed. The corresponding data is VariableChanged.
    MSG_UPDATE Must be sent if the bounding box has to be recalculated. (Otherwise you can use MSG_CHANGE.)
    MSG_SMALLUPDATE Part of the object has changed that needs no cache rebuilding. Note: This message should be used very carefully, it is there for (small) performance enhancements, for example if a polygon selection is changed then the caches needn’t be rebuilt, so MSG_SMALLUPDATE can be sent.
    MSG_CHANGE Must be sent if any object data (except for the matrix) has been changed.
    MSG_BASECONTAINER Message with a container, for example from a C.O.F.F.E.E. plugin. The corresponding data is BaseContainer.
    MSG_SEGMENTS_CHANGED The segments have changed. The corresponding data is VariableChanged.
    MSG_FILTER A message filter that lets you block C4DAtom.MultiMessage() calls. The corresponding data is MessageFilter. Return True to let the message pass and False to block it!
    MSG_TRANSFERGOALS Internal message!
    MSG_DESCRIPTION_INITUNDO Allows elements to create undo actions for the following parameter changes in the attributes manager. This is already automatically handled for keys, tags, objects etc. The corresponding data is DescriptionInitUndo.
    MSG_DESCRIPTION_CHECKUPDATE Allows elements to determine the type of refresh after a parameter has been changed in the Active manager. This is already automatically handled for keys, tags, objects etc. The corresponding data is DescriptionCheckUpdate. Note: Currently this message is completely handled by all baseclasses. Most plugins won’t need to modify the message data. it is more interesting to start some update action - e.g. deleting data that will be rebuilt with the next access.
    MSG_DESCRIPTION_CHECKUPDATE_AUTOTAKE

    New in version R17.032.

    Element supports automatic Take overrides.

    MSG_DESCRIPTION_CHECKUPDATE_BASELISTEDIT

    New in version R17.032.

    Edit node is updating the current Take override value.

    MSG_DESCRIPTION_COMMAND Sent by for example BUTTON (description element). See example below.
    MSG_DESCRIPTION_POPUP Allows popup menu handling in the Attribute Manager. The corresponding data is DescriptionPopup.
    MSG_DESCRIPTION_POSTSETPARAMETER After a SetParameter() call to an atom element this message is sent to the object. The corresponding data is DescriptionPostSetValue.
    MSG_DESCRIPTION_VALIDATE Allows you to update dependencies or to check for invalid values after a parameter has been changed (For example: the light’s inner radius always must be smaller than the light’s outer radius - so this routine checks for it and corrects it). The corresponding data is DescriptionValidate.
    MSG_EDIT Allows elements to do some action if the user edits the element (doubleclick e.g. in object manager).
    MSG_MENUPREPARE Allows tags, objects, shaders etc. to do some setup work when called from the menu. The corresponding data is the current BaseDocument.
    MSG_RETRIEVEPRIVATEDATA A generic private message to retrieve data from an object. Specific for every type of object so no public documentation available. The corresponding data is RetrievePrivateData.
    MSG_DESCRIPTION_REMOVE_ENTRY Tells the node to remove a description entry. The corresponding data is DescriptionCommand.
    MSG_DESCRIPTION_EDIT_ENTRY Tells the node to edit a description entry. The corresponding data is DescriptionCommand.
    MSG_DESCRIPTION_CHECKDRAGANDDROP Asks the node if a drag and drop onto for example a LINK (description element) field should be accepted. The corresponding data is DescriptionCheckDragAndDrop.
    MSG_DESCRIPTION_GETBITMAP Queries the object for updated bitmaps for BitmapButtonCustomGui elements in the description. (E.g. the lens flare preview.) The corresponding data is DescriptionGetBitmap.
    MSG_DESCRIPTION_GETOBJECTS Private.
    MSG_DESCRIPTION_USERINTERACTION_END End of user interaction.
    MSG_DESCRIPTION_GETINLINEOBJECT Sent by the Attribute Manager to the object. The object can check for a description ID and return the linked objects in the atom array. The corresponding data is DescriptionInlineObjectMsg.
    MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION

    New in version R19.

    Sent by a custom GUI to the parent NodeData.

    MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION_ID

    New in version R19.

    The custom GUI ID in the message container for MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION.

    MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION_CONTENT

    New in version R19.

    The user data in the message container for MSG_DESCRIPTION_CUSTOMGUI_NOTIFICATION.

    MSG_DESCRIPTION_ALLOWOVERRIDE

    New in version R17.032.

    Sent before a Take override is added to allow it or not. The corresponding data is DescriptionAllowOverride.

    MSG_DESCRIPTION_TAKECHANGED

    New in version R17.032.

    Sent to each overridden node when the user changes the current Take. Sent to both the node storing the data in the Take and the node releasing the data to the document. The corresponding data is DescriptionTakeChanged.

    MSG_MOVE_FINISHED Sent after a handle or the object has been moved.
    MSG_MOVE_START Sent before a handle or the object has been moved.
    MSG_EDITABLE_END Private.
    MSG_GETCUSTOMICON Every atom can return a custom icon with this message. The corresponding data is GetCustomIconData.
    MSG_MATERIALDRAGANDDROP Received by a material upon dropping an instance of the material onto an object. The material can choose to create a tag of its own, or trigger other actions, instead of letting Cinema 4D create a normal material assignment. The corresponding data is MaterialDragAndDrop. For example Sketch and Toon creates its own type of tag and returns it in result. Cinema 4D creates the undo for it and activates it. Inserting the tag is done by the material.
    MSG_DRAGANDDROP Received when something is dropped on it. The corresponding data is DragAndDrop.
    MSG_INITIALCHANNEL See HandleInitialChannel().
    MSG_DOCUMENTINFO Sent as broadcast message to the document when it its loaded, saved etc. The corresponding data is DocumentInfoData. (See the type member for more information about when the message is sent.)
    MSG_GETSELECTION Private.
    MSG_MULTI_RENDERNOTIFICATION A document and all of its elements receive this message before a render starts. The corresponding data is RenderNotificationData.
    MSG_MULTI_MARKMATERIALS When data is None this is sent to plugin nodes to let them mark the materials that they use. Otherwise the message is sent to let you translate you material links, for example when a material is replaced, and then the corresponding structure is MarkMaterials. (An example for both cases is included on the MarkMaterials page.)
    MSG_MULTI_DOCUMENTCLONED The document has been cloned.
    MSG_MULTI_DOCUMENTIMPORTED After a Cinema 4D document has been loaded this message is sent to the document (and all children structures). The corresponding data is DocumentImported.
    MSG_MULTI_SETNEWMARKERS Private.
    MSG_MULTI_CLEARSUGGESTEDFOLDER Objects have to remove absolute paths (only if they support MSG_GETALLASSETS). Both are important for SaveProject to work and to collect all items.
    MSG_TOOL_SWITCHACTION

    New in version R17.032.

    Sent to tools on mouse input and cursor info if they have the flag PLUGINFLAG_TOOL_SWITCHACTION set to allow to change action on modifier key.

    MSG_TRANSLATE_POINTS Sent by the modeling core to let tags etc. update after point changes. The corresponding data is TranslationMaps.
    MSG_TRANSLATE_POLYGONS Sent by the modeling core to let tags etc. update after polygon changes. The corresponding data is TranslationMaps.
    MSG_TRANSLATE_NGONS Sent by the modeling core to let tags etc. update after N-gon changes. The corresponding data is TranslationMaps.
    MSG_TRANSLATE_SEGMENTS Sent by the modeling core to let tags etc. update after segment changes. The corresponding data is TranslationMaps.
    MSG_PRETRANSLATE_POINTS Sent before MSG_TRANSLATE_POINTS, before the changes are actually carried out. The corresponding data is TranslationMaps.
    MSG_PRETRANSLATE_POLYGONS Sent before MSG_TRANSLATE_POLYGONS, before the changes are actually carried out. The corresponding data is TranslationMaps.
    MSG_PRETRANSLATE_NGONS Sent before MSG_TRANSLATE_NGONS, before the changes are actually carried out. The corresponding data is TranslationMaps.
    MSG_PRETRANSLATE_SEGMENTS Sent before MSG_TRANSLATE_SEGMENTS, before the changes are actually carried out. The corresponding data is TranslationMaps.
    MSG_UPDATE_NGONS Should be sent if points are changed and any N-gons need updating. Cinema 4D will then update the N-gons, if the user has this option enabled.
    MSG_DOCUMENT_MODE_CHANGED Sent to the active tool plugin during BaseDocument.SetMode().
    MSG_TOOL_RESTART Private. (Handles the tool description apply behaviour after mouse clicks.)
    MSG_DEFORMMODECHANGED Private.
    MSG_ANIMATE Sent to objects after they have been animated.
    MSG_CALCMEMUSAGE Private.
    MSG_SCALEDOCUMENT Tells the document that another document with different scale has been merged. The corresponding data is MessageScaleDocument.
    MSG_GET_INHERITANCECONTAINER Private.
    MSG_SOFTTAG_UPDATE Private.
    • Here is how to process MSG_DESCRIPTION_COMMAND message:
      def Message(self, node, type, data):
        if type==c4d.MSG_DESCRIPTION_COMMAND:
          if data[‘id’][0].id==THE_BUTTON_ID:
            print “Pushed button with command ID”, THE_BUTTON_ID
            return True
      
  • data (any) – The message data.
Return type:

bool

Returns:

Depends on the message type.

NodeData.GetDocument(self, node)

If you create your own BaseList elements this allows you to tell Cinema 4D how to retrieve the document. Any call to GeListNode.GetDocument() ends up here.

Note

Standard nodes like objects, tags etc. do not need to override this function. Only if you create elements that are allocated with AllocListNode(), AllocSmallListNode() and AllocMultiNode() do need this function.

Parameters:node (c4d.GeListNode) – The list node connected with this instance.
Return type:c4d.documents.BaseDocument
Returns:The document.
NodeData.IsInstanceOf(self, node, type)

Called to know if the node is an instance of the given base type.

Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • type (int) – The type to check.
Return type:

bool

Returns:

True if the node is an instance of the given type, otherwise False.

NodeData.IsDocumentRelated(self, node)

New in version R18.011.

Called by the Attribute Manager for correct undo handling.

Warning

Should not be overloaded by regular plugins and should be used with extra care. If False is returned no undo is possible.

Parameters:node (c4d.GeListNode) – The list node connected with this instance.
Return type:bool
Returns:True if the node is part of the document, otherwise False.
NodeData.GetBubbleHelp(self, node)

New in version R18.011.

Called to create a contextual bubble help and status bar information for the node.

Note

When dealing with strings it is advised to use the string resources files and the GeLoadString() function. This keeps the plugin easy to localize for any language to support and makes full use of the language features of Cinema 4D.

Parameters:node (c4d.GeListNode) – The list node connected with this instance.
Return type:str
Returns:The bubble help string.
NodeData.GetDDescription(self, node, description, flags)

New in version R18.011.

Called to add parameters to the description for the node. Modify the passed description as needed and return the appropriate flags.

Note

If only a description resource is used it is not needed to overload GetDDescription().

For instance, here is how GetDDescription() can be implemented:

def GetDDescription(self, node, description, flags):

    # Before adding dynamic parameters, load the parameters from the description resource
    if not description.LoadDescription(node.GetType()):
        return False

    # Get description single ID
    singleID = description.GetSingleDescID()

    # Check if dynamic parameter with ID paramID has to be added
    paramID = ...
    if singleID is None or paramID.IsPartOf(singleID)[0]:
        # Add dynamic parameter
        if not description.SetParameter(paramID, ...):
            return False

    ...

    # After parameters have been loaded and added successfully, return True and DESCFLAGS_DESC_LOADED with the input flags
    return (True, flags | c4d.DESCFLAGS_DESC_LOADED)
Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • description (c4d.Description) – The node’s description to add the parameters to.
  • flags (int) –

    The flags for the description operation:

    DESCFLAGS_DESC_0 None.
    DESCFLAGS_DESC_RESOLVEMULTIPLEDATA Private and unused.
    DESCFLAGS_DESC_LOADED Set if elements have been added to the description, either by loading or manual addition.
    DESCFLAGS_DESC_RECURSIONLOCK Private.
    DESCFLAGS_DESC_DONTLOADDEFAULT Don’t load defaults. Used internally for old plugin tools.
    DESCFLAGS_DESC_MAPTAGS If this is specified the object description will also contain the tag’s descriptions (as subcontainers).
    DESCFLAGS_DESC_NEEDDEFAULTVALUE Set if “Reset to Default” was called by the user.
Return type:

bool or tuple(bool, int)

Returns:

One of these options:

bool: True if successful, otherwise False. Useful in error state to only return False.
tuple(bool, int): The status (True if successful, otherwise False) and description flags (DESCFLAGS_DESC).

NodeData.GetDParameter(self, node, id, flags)

New in version R18.011.

Called to override the reading of description parameters. Necessary for parameters that are not simply stored in the node’s container e.g. class members.
Return the parameter data and the appropriate flags if the right id is provided.

Note

If only a description resource is used it is not needed to overload GetDParameter().

Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • id (c4d.DescID) – The ID of the parameter.
  • flags (int) –

    The flags for the description operation:

    DESCFLAGS_DESC_0 None.
    DESCFLAGS_DESC_RESOLVEMULTIPLEDATA Private and unused.
    DESCFLAGS_DESC_LOADED Set if elements have been added to the description, either by loading or manual addition.
    DESCFLAGS_DESC_RECURSIONLOCK Private.
    DESCFLAGS_DESC_DONTLOADDEFAULT Don’t load defaults. Used internally for old plugin tools.
    DESCFLAGS_DESC_MAPTAGS If this is specified the object description will also contain the tag’s descriptions (as subcontainers).
    DESCFLAGS_DESC_NEEDDEFAULTVALUE Set if “Reset to Default” was called by the user.
Return type:

bool or tuple(bool, any, int)

Returns:

One of these options:

bool: True if successful, otherwise False. Useful in error state to only return False.
tuple(bool, any, int): The status (True if successful, otherwise False), parameter data and description flags (DESCFLAGS_DESC).

NodeData.SetDParameter(self, node, id, t_data, flags)

New in version R18.011.

Called to override the writing of parameters. Read the passed t_data if the right id is provided, store the data and return the appropriate flags.

Note

If only a description resource is used it is not needed to overload SetDParameter().

Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • id (c4d.DescID) – The ID of the parameter.
  • t_data (any) – The parameter data to set.
  • flags (int) –

    The flags for the description operation:

    DESCFLAGS_DESC_0 None.
    DESCFLAGS_DESC_RESOLVEMULTIPLEDATA Private and unused.
    DESCFLAGS_DESC_LOADED Set if elements have been added to the description, either by loading or manual addition.
    DESCFLAGS_DESC_RECURSIONLOCK Private.
    DESCFLAGS_DESC_DONTLOADDEFAULT Don’t load defaults. Used internally for old plugin tools.
    DESCFLAGS_DESC_MAPTAGS If this is specified the object description will also contain the tag’s descriptions (as subcontainers).
    DESCFLAGS_DESC_NEEDDEFAULTVALUE Set if “Reset to Default” was called by the user.
Return type:

bool or tuple(bool, int)

Returns:

One of these options:

bool: True if successful, otherwise False. Useful in error state to only return False.
tuple(bool, int): The status (True if successful, otherwise False) and description flags (DESCFLAGS_DESC).

NodeData.GetDEnabling(self, node, id, t_data, flags, itemdesc)

Called to let decide which parameters should be enabled or disabled (ghosted). This can be used both for parameters that are stored in the node’s container and for custom parameters.

Just read the passed t_data if the right id was provided, and return True to enable the parameter or False to disable it depending on the value.

And if the passed id element is not processed, include a call to the base class method as last return:

return NodeData.GetDEnabling(self, node, id, t_data, flags, itemdesc)
Parameters:
  • node (c4d.GeListNode) – The list node connected with this instance.
  • id (c4d.DescID) – The ID of the parameter.
  • t_data (any) – The current data for the parameter.
  • flags (int) – Not used currently.
  • itemdesc (c4d.BaseContainer) – The description, encoded to a container as described in Description.
Return type:

bool

Returns:

True if the parameter should be enabled, otherwise False.

Note

It is recommended to include a call to the base class method as last return.

NodeData.TranslateDescID(self, node, id)

New in version R18.011.

Called by the Attribute Manager for every object and every description ID.
Gives a NodeData plugin the opportunity to route a description ID in the description of a node to another one.
For example used for tags that are embedded in an object description so that the keyframer for a tag property creates the track on the tag and not on the object.
Parameters:
Return type:

bool or tuple(bool, DescID, C4DAtom)

Returns:

One of these options:


bool: True if successful, otherwise False. Useful in error state to only return False.
tuple(bool, DescID, C4DAtom): The status (True if successful, otherwise False), target description ID and object.

NodeData Management

In the following chapter we are going to understand some internal things of Cinema 4D. Normally you do not need to care about this, but sometimes it is very effective for debugging to dive into the deep to understand how things work.

Imagine you are writing your own tag plugin. To do this you write a class derived from TagData and register it with the corresponding function:

import c4d
from c4d import plugins

PLUGIN_ID = 1234567890

class LookAtCameraData(plugins.TagData):

  def Execute(self, tag, doc, op, bt, priority, flags):
    #...
    return c4d.EXECUTIONRESULT_OK

if __name__ == "__main__":
  plugins.RegisterTagPlugin(id=PLUGIN_ID, str="Look At Camera", g=LookAtCameraData,
                            description="pylookatcamera", icon=None,
                            info=c4d.TAG_MULTIPLE|c4d.TAG_EXPRESSION|c4d.TAG_VISIBLE)

Now you can create an instance of your tag in Cinema 4D. What you now see is a little icon, which represents a new instance of type BaseTag. You might wonder why you get an object of this type, and not as expected of LookAtCameraData.

../../../../_images/lookatcamera.png

To clarify this, we need to understand the steps what Cinema 4D does, when you create this tag.

First a new instance of BaseTag is created along with an instance of your type LookAtCameraData. The base tag is stored in the document and works like a controller with settings for the instance of LookAtCameraData. The instance of LookAtCameraData itself is invisible for the user.

When you take a look at the second argument of TagData.Execute() which is of type BaseTag. This object contains all the parameters which are set by the user in the document. When the user now changes a parameter, the current established BaseTag is put onto the undo stack and replaced by a new base tag which gets the new settings. The next time TagData.Execute() of this instance is executed, it gets the new parameter.

This concept works for all node data plugins (ObjectData, SceneSaverData, …)

../../../../_images/association.png