make UserData in C++

On 02/09/2013 at 21:14, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R12 
Platform:    Mac  ;  
Language(s) :     C++  ;


Is it possible to add User Data (as in the User Data tab of the Attributes window) to an object that is created in my code? I guess you use GetDynamicDescription to access existing User Data.



On 03/09/2013 at 01:02, xxxxxxxx wrote:

Exactly. You can use DynamicDescription::Alloc(), passing the user-data's description as a
BaseContainer, to append a new user-data parameter. The description ID of the new parameter
will be returned.

On 04/09/2013 at 13:34, xxxxxxxx wrote:

Thanks NiklasR

I am currently trying to find example code and wading through the docs to find how to actually do this.
My understanding is a bit nebulous at this point.


On 04/09/2013 at 13:50, xxxxxxxx wrote:

Bool AddShaderField(BaseObject* op) {
    Bool success = RenameDialog(&name);

// Break if the rename dialog was canceled.
    if (!success) {
        return TRUE;

// Create a cusotm datatype container.
    BaseContainer container = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);
    container.SetString(DESC_NAME, name);
    container.SetString(DESC_SHORT_NAME, name);

// Obtain the object's user-data description.
    DynamicDescription* desc = op->GetDynamicDescription();
    if (!desc) {
        MessageDialog(GeLoadString(IDS_SHADERCOLLECTION_ADDSHADERDDERROR, __FILE__, LongToString(__LINE__)));
        return FALSE;

// Create a new UserData entry.
    return TRUE;

On 04/09/2013 at 16:56, xxxxxxxx wrote:

Thanks. That made it much clearer. The ways of the SDK are often very mysterious to me.


On 04/09/2013 at 21:16, xxxxxxxx wrote:

And  promptly a new question pops up.

How can I create groups? Or, actually I did create a group like this:

                    bc = GetCustomDataTypeDefault(DTYPE_GROUP);
                    bc.SetString(DESC_NAME, "General");
                    bc.SetString(DESC_SHORT_NAME, "General");
                    bc.SetBool(DESC_GUIOPEN, TRUE);
                    bc.SetBool(DESC_TITLEBAR, TRUE);

But how to I move my other data into the group?

On 05/09/2013 at 07:59, xxxxxxxx wrote:

Small example without any error checking stuff:

//This example creates a group UserData item  
//Then it creates a Real type userData item as a child of the group  
  BaseDocument *doc = GetActiveDocument();  
  BaseObject *obj = doc->GetActiveObject();  
  DynamicDescription* dd = obj->GetDynamicDescription();  
  BaseContainer groupContainer;  
  dd->FillDefaultContainer(groupContainer, DTYPE_GROUP, "New Group");  
  DescID groupID = dd->Alloc(groupContainer);  
  dd->Set(groupID, groupContainer, obj);  
  BaseContainer realContainer;  
  dd->FillDefaultContainer(realContainer, DTYPE_REAL, "New Real");  
  GeData dataID;  
  dataID.SetCustomDataType(CUSTOMDATATYPE_DESCID, groupID);  
  realContainer.SetData(DESC_PARENTGROUP, dataID);  
  DescID realID = dd->Alloc(realContainer);  
  dd->Set(realID, realContainer, obj);


On 06/09/2013 at 13:56, xxxxxxxx wrote:

Great. That works although I am not sure I would have come up with it. In retrospect it looks logical.



On 09/09/2013 at 15:38, xxxxxxxx wrote:

And here we go again. I find DynamicDescription dramatically confusing because references to it are all over the place in the documentation. I understand groups now but I am stuck at how to implement a Popup menu. I suppose you use DTYPE_POPUP to make a container for the menu and use DESC_CYCLE to populate it?

On 10/09/2013 at 01:30, xxxxxxxx wrote:

With "Popup menu", do you mean a Cycle field? The elements in a Cycle field are described using a
BaseContainer. Take a look at the documentation of the Description class, all IDs are listed up there
with quite good description.

BaseContainer cycle;
cycle.SetString(0, "Cycle Value 0");
cycle.SetString(1, "Cycle Value 1");
itemdesc->SetContainer(DESC_CYCLE, cycle);


On 10/09/2013 at 08:19, xxxxxxxx wrote:

The popup button doesn't seem to work like the ComboButton Nik.
It's either broken. Or the the way we populate it with entries is different.

Example that adds a UD ComboButton to the active object:

    BaseObject *obj = doc->GetActiveObject();  
  if (!obj) return FALSE;  
  //Create a list of ComboButton values  
  BaseContainer names;  
  BaseContainer bc = NULL;  
  bc.SetString(DESC_NAME, "My Combo");  
  bc.SetString(DESC_SHORT_NAME, "My Combo");  
  bc.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_CYCLEBUTTON);  //<--- put CUSTOMGUI_POPUP here and it no longer works!!!  
  bc.SetContainer(DESC_CYCLE, names);  
  //Get the object's master UD container that holds all the UserData entries  
  DynamicDescription *dd = obj->GetDynamicDescription();  
  if(!dd) return FALSE;  
  //Create a new UserData entry using the container values above  
  SendCoreMessage(COREMSG_CINEMA, BaseContainer(COREMSG_CINEMA_FORCE_AM_UPDATE)); //Refresh the AM to see the changes in real time