View Python: User Data
Cinema 4D’s Python API allows you to browse and modify the User Data on an object. The Python API doesn’t offer the full implementation of the Description or DynamicDescription classes from the C++ API, so User Data is currently the only method for creating dynamic description elements.
Browsing User Data
To Browse the User Data, use BaseList2D.GetUserDataContainer():
for id, bc in op.GetUserDataContainer(): print id, bc
The BaseContainer is identical to the Description BaseContainer which is explained within the c4d.Description section of the Python API.
This version of the function iterates through the c4d symbols to show the constant associated with each key.
for descId, bc in op.GetUserDataContainer(): print "*"*5,descId,"*"*5 for key, val in bc: for txt, i in c4d.__dict__.iteritems(): if key == i and txt[:5]=="DESC_": print txt,"=",val break else: print key,"=",val
Creating User Data
To create User Data, use BaseList2D.AddUserData(). The following convenience functions demonstrate how to create common User Data elements:
import c4d
from c4d import gui
#Welcome to the world of Python
def CreateUserDataGroup(obj, name, parentGroup=None, columns=None, shortname=None):
if obj is None: return False
if shortname is None: shortname = name
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_GROUP)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = shortname
bc[c4d.DESC_TITLEBAR] = 1
if parentGroup is not None:
bc[c4d.DESC_PARENTGROUP] = parentGroup
if columns is not None:
#DESC_COLUMNS VALUE IS WRONG IN 15.057 - SHOULD BE 22
bc[22] = columns
return obj.AddUserData(bc)
def CreateUserDataLink(obj, name, link, parentGroup=None, shortname=None):
if obj is None: return False
if shortname is None: shortname = name
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_BASELISTLINK)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = shortname
bc[c4d.DESC_DEFAULT] = link
bc[c4d.DESC_ANIMATE] = c4d.DESC_ANIMATE_OFF
bc[c4d.DESC_SHADERLINKFLAG] = True
if parentGroup is not None:
bc[c4d.DESC_PARENTGROUP] = parentGroup
element = obj.AddUserData(bc)
obj[element] = link
return element
def CreateUserDataFloat(obj, name, val=0, parentGroup=None, unit=c4d.DESC_UNIT_REAL):
if obj is None: return False
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_REAL)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc[c4d.DESC_DEFAULT] = val
bc[c4d.DESC_ANIMATE] = c4d.DESC_ANIMATE_ON
bc[c4d.DESC_UNIT] = unit
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_REALSLIDER
bc[c4d.DESC_MINSLIDER] = -500
bc[c4d.DESC_MAXSLIDER] = 500
bc[c4d.DESC_STEP] = 1
if parentGroup is not None:
bc[c4d.DESC_PARENTGROUP] = parentGroup
element = obj.AddUserData(bc)
obj[element] = val
return element
def CreateUserDataInEx(obj, name, parentGroup=None):
if obj is None: return False
bc = c4d.GetCustomDatatypeDefault(c4d.CUSTOMDATATYPE_INEXCLUDE_LIST)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_INEXCLUDE_LIST
bc[c4d.IN_EXCLUDE_FLAG_NUM_FLAGS] = 1
bc[c4d.IN_EXCLUDE_FLAG_INIT_STATE] = 1
bc[c4d.IN_EXCLUDE_FLAG_IMAGE_01_ON] = 1018640
bc[c4d.IN_EXCLUDE_FLAG_IMAGE_01_OFF] = 1018641
bc[c4d.DESC_HIDE] = not bool(obj[c4d.ART_USEMOGRAPH])
if parentGroup is not None:
bc[c4d.DESC_PARENTGROUP] = parentGroup
element = obj.AddUserData(bc)
return element
To create a new top-level group that will appear as a tab within the Attribute Manager, call CreateUserDataGroup with parentGroup=c4d.DescID(0), or if not using the convenience functions above set bc[c4d.DESC_PARENTGROUP]=c4d.DescID(0):
self.layerGroup = self.CreateUserDataGroup(node,"Layers",c4d.DescID(0))
Full usage example of convenience functions:
def main(): layerGroup = CreateUserDataGroup(op,"Layers",c4d.DescID(0)) subGroup = CreateUserDataGroup(op,"Sub Group",layerGroup,3) float1 = CreateUserDataFloat(op,"Float 1",0,subGroup) float2 = CreateUserDataFloat(op,"Float 2",0,subGroup) float3 = CreateUserDataFloat(op,"Float 3",0,subGroup) float4 = CreateUserDataFloat(op,"Float 4",0,subGroup,c4d.DESC_UNIT_PERCENT) float5 = CreateUserDataFloat(op,"Float 5",0,subGroup,c4d.DESC_UNIT_PERCENT) float6 = CreateUserDataFloat(op,"Float 6",0,subGroup,c4d.DESC_UNIT_PERCENT) subGroup2 = CreateUserDataGroup(op,"Sub Group 2",layerGroup,1) link1 = CreateUserDataLink(op,"Link",None,subGroup2) c4d.EventAdd()