Tag plugin - adding childs to Cycle

On 21/08/2017 at 01:49, xxxxxxxx wrote:

I have a Tag plugin and its properties are defined by a res file.
In it is a cycle field for which I want to add dynamically children.
Because it is  not a dialog, I can not use GeDialog.AddChild(id, subid, child)

What should I do to add a child dynamically to the cycle?


On 22/08/2017 at 05:18, xxxxxxxx wrote:

Hi Pim,

in GetDDescription() you need to store/modify a BaseContainer stored under DESC_CYCLE, see Description.

In our C++ docs we also have a manual about Description Settings (here section Values).

On 23/08/2017 at 01:41, xxxxxxxx wrote:

Hi Andreas,

Great thanks you.
I think Descriptions are easier in c++ than in python.

On 23/08/2017 at 07:51, xxxxxxxx wrote:

Hi Pim,

I'm not sure why Descriptions should be easier in C++ than in Python?
Since R18 you can pretty much work with them like in C++. But please, correct me, if I overlooked anything or misunderstood the comment.

On 23/08/2017 at 12:06, xxxxxxxx wrote:

To be honest, perhaps it is my lack of understanding of python R16 Descriptions.
All these various levels, confuses me.
In c++, for me it is more straight forward.

And of course, my main platform for developing plugins is still R16.
Maybe it is time to go over to R18.

Could you perhaps do the c++ example in python for me?


On 23/08/2017 at 12:58, xxxxxxxx wrote:

So I have this tag plugin that uses this res file:

CONTAINER globalswitch
	NAME globalswitch;
        LONG nw1

What Descriptions should I use to add / remove child's from the cycle?


On 24/08/2017 at 06:18, xxxxxxxx wrote:

Hi Pim,

yes indeed, if you want to work with Descriptions in Python it will be much easier from R18 on.
Actually I'm not sure you will be able to dynamically fill a Cycle/Combo box in Python with versions previous R18, as you are lacking the ability to overwrite GetDDescription(). the only real option I see is to do it via Cycle in User Data. See this thread: Adding cycles to a UserData Field

For everybody working with R18 and later, it's quite easy and roughly looks like this:

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()
    myCycleID = c4d.DescID(nw1)  # using ID from above post
    if singleID is None or myCycleID.IsPartOf(singleID)[0]:
        # Add dynamic parameter
        bcCycle = c4d.GetCustomDataTypeDefault(c4d.DTYPE_LONG)
        bcCycle.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
        bcCycle.SetString(c4d.DESC_NAME, "Cycle")
        # Cycle elements get filled into another container
        items = c4d.BaseContainer()
        items.SetString(0, "Item 0")
        items.SetString(1, "Item 1")
        items.SetString(2, "Item 2")
        bcCycle.SetContainer(c4d.DESC_CYCLE, items)
        # Add cycle to the parameters in specified group
        if not description.SetParameter(myCycleID, bcCycle, c4d.DescLevel(SWITCHFRAMEGROUP)) # group ID from above post
            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)

On 24/08/2017 at 06:29, xxxxxxxx wrote:

Regarding creation from user data even if I think pgroof already understand it, but since there is no proper exemple for handle it, I would share a class I did for a plugin in order to help future readers. 

On 24/08/2017 at 09:39, xxxxxxxx wrote:

Thanks, the cycle is now updated and indeed quite easy, thanks!

One questions:
I see that function GetDDescription is executed quite often.
So, I guess inserting the Cycle must be done somewhere else. For example in Init()?


PS one small error.  The line "if not description.SetParameter(myCycleID, bcCycle, c4d.DescLevel(SWITCHFRAMESGROUP)) :" should have a DescID and not a DescLevel.

On 24/08/2017 at 09:40, xxxxxxxx wrote:

Originally posted by xxxxxxxx

Regarding creation from user data even if I think pgrooff already understand it, but since there is no proper example for handle it, I would share a class I did for a plugin in order to help future readers.

Thanks you very much, very helpful!

On 24/08/2017 at 09:58, xxxxxxxx wrote:

Look at the Message function and more specially about c4d.MSG_MENUPREPARE

On 25/08/2017 at 00:40, xxxxxxxx wrote:

Great, thanks.

On 25/08/2017 at 00:43, xxxxxxxx wrote:

I guess GetDDescription is executed every time a description is changed?

Is that the only way to detect whether a different entry cycle is selected, or is there a message I can check.

On 25/08/2017 at 05:13, xxxxxxxx wrote:


GetDDescription() is called every time Cinema is interested in the parameter description of an element. The edited Description it not stored anywhere so you have to define your custom parameter description every time GetDDescription() is called (since the parameter description can change at any time).

If you are interested when a parameter value changed you can implement NodeData.SetDParameter() or you can listen for the MSG_DESCRIPTION_POSTSETPARAMETER message.

best wishes,

On 25/08/2017 at 06:43, xxxxxxxx wrote:

So, now I can update the children in the Cycle field.

In the tag plugin, message() is used to get the value to define a new child of Cycle.
I add the input to a List, that is used in GetDDescription to define the children of Cycle.

However, how can I trigger GetDDescription to be executed, so the update Cycle is shown?

def Message(self, node, type, data) :
    if type == c4d.MSG_DESCRIPTION_COMMAND:
        if (data['id'][0].id == ADDCHILD) :
            data = node.GetDataInstance()
            child= data[CHILDINPUT]
	    self.children.append[child]	#used in GetDDescription to define the children of Cycle
            #now trigger GetDDescription  to show the updated Cycle
    return True   

On 25/08/2017 at 08:56, xxxxxxxx wrote:


you can make the host object dirty be setting the dirty flag DIRTYFLAGS_DESCRIPTION. That should trigger GetDDescription () again.

best wishes,

On 26/08/2017 at 05:10, xxxxxxxx wrote:

Thanks, it works if I set the tag to dirty using DIRTYFLAGS_DESCRIPTION.