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

PLUGIN_ID = 1234567890

class LookAtCameraData(c4d.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,

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.


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, …)