Miscellaneous questions about "BaseContainer","DescID" etc
eZioPan last edited by eZioPan
[I have so many questions in this thread. So first, please let me thank you for taking time! ]
I want to access user data in a more "procedural way". Here is the code after I do lots of searching on the Python (and C++) SDK document:
import c4d from c4d import gui #Welcome to the world of Python def main(): obj = doc.GetActiveObject() objBc = obj.GetData() userdataList = obj.GetUserDataContainer() userdata = userdataList userdataBc = userdata DescIDList = userdata id0 = DescIDList.id id1 = DescIDList.id print(objBc[id0][id1]) if __name__=='__main__': main()
After this, I really want to know how the data of a
BaseObjectorganized and stored. And I make a picture:
I don't know if this reveals some of the data structure of
And I have some doubts in or out of the picture:
[In the picture] After I search in the
BaseObject, I don't find anything data related to a
min/max value/default value, etc.
Where is the
BaseContainerof all these data stored?
[In the picture] Is
DescIDis similar to
BaseContainer? And where are they stored?
[In the picture] What is
DescLevel? I only find
0in this field.
[Out the picture] As for now, is there any easier way to get a
DescLevel.dtype? Comparing and searching in branches of
*.hfiles is not friendly for us without C++ experience.
[Off topic] The name
indexin sample code of
Python SDK Documentis confusing. Especially that all other function documents refer the same thing as
idon the same page.
[Off topic] Is there any articles that have more detail about the foundation concepts for cinema 4d coding?
Here I find some pages in
Python SDK Document:
Cookbook, Plugin Structure, Introduction into the GUI of Cinema 4D.
But they are lack of details and relation with other document.
Also, some foundation concepts only have few introduction paragraphs:
I don't mean to complain, but it's frustrating after spending hours and hours searching in the SDK and the Internet but only get some obscure results. I hope the document could be more friendly to new developers.
Thanks a lot!
s_bach last edited by
An object like BaseObject can store data. This data is typically stored in the object's BaseContainer. But there are cases where the data is not stored in the BaseContainer so in general it is saver to use GetParameter().
A BaseContainer can store any kind of data. This includes other BaseContainers. The BaseContainer of the object stores a sub-BaseContainer that stores all the values of the user data. The ID of the User-Data-BaseContainer is c4d.ID_USERDATA. Using this ID you can obtain the BaseContainer:
bc = op.GetData() userDataValues = bc[c4d.ID_USERDATA] # or userDataValues = op.GetParameter(c4d.ID_USERDATA, c4d.DESCFLAGS_GET_0)
This BaseContainer stores the parameter values of user data parameters.
A parameter is identified using a DescID. This DescID has nothing to do with UUID.
A DescID is composed of one or several DescLevel components. In most cases the DescID has only one DescLevel. The DescLevel defines these properties:
- id: id of the level. Typically the parameter ID.
- dtype: type of the parameter.
- creator: ID of the "creator" of the parameter. E.g. on a cube you have some parameters that were created by the "Cube" (Size, Segments, ...). But there are also other parameters that are shared by all BaseObject's (Position, Scale, ...). These shared parameters are inherited from a base class, in this case Obase (5155). The "creator" value is not always relevant so it might not always be set.
A DescID can have multiple DescLevels since a parameter may be stored inside another parameter. As described above, user data values are stored in a BaseContainer that is stored in the default BaseContainer. The full DescID of a user-data parameter has to reflect that. The DescID of a user-data parameter must first identify the user-data container and then the actual parameter in that container. This is done using two DescLevels:
id = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA, c4d.DTYPE_SUBCONTAINER, 0), c4d.DescLevel(1)) value = op.GetParameter(id, c4d.DESCFLAGS_GET_0)
But the Python API also allows you to do the same with less code:
value = op[c4d.ID_USERDATA, 1]
Or you access the user-data BaseContainer:
bc = op.GetData() userDataValues = bc[c4d.ID_USERDATA] value = userData
The DescIDs are not necessarily stored in a file. The number of parameters of an object may change depending on how the object is used. The list of all displayed parameters is stored in the parameter Description. This Description contains the IDs as well as information on how to display the parameters in the Attribute Manager. The information how the parameter should be displayed is also stored as a BaseContainer (but this is NOT the object's BaseContainer).
The parameter description of user data parameters is stored in the object. You can access this data with GetUserDataContainer():
for id, descriptionBC in op.GetUserDataContainer(): print("User Data ID: " + str(id)) print("User Data Value: " + str(op[id])) print("User Data Name: " + descriptionBC[c4d.DESC_NAME])
To make that clear: the VALUES of user data parameters are stored in the object's BaseContainer. The DESCRIPTION of the user data parameters is stored in the BaseContainers accessed with
You can also find further information about these classes:
- BaseContainer, BaseContainer Manual
- DescID, DescID Manual
- DynamicDescription Manual
- Description Manual
- Description Settings Manual
eZioPan last edited by eZioPan
@s_bach, thank you, I'll start to do some hard reading!