RemoveUserData does not fully remove User Data
-
If I add a string field with AddUserData.
And then I delete that string field with DeleteUserData.
And then try to add a float field with AddUser Data:
I get
TypeError: setitem expected str, not float
And if I try to get the value before EventAdd, I get the old, deleted valueAnyone know any workarounds? Like how to flush the memory of the user data?
-
Here's a simple test to run in the script editor:
Add a Cube to the scene.import c4d current_doc = c4d.documents.GetActiveDocument() cube = current_doc.SearchObject('Cube') def AddStringDataType(obj): if obj is None: return bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_STRING) bc[c4d.DESC_NAME] = "String" element = obj.AddUserData(bc) obj[element] = 'bob' c4d.EventAdd() def AddFloatDataType(obj): if obj is None: return bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_REAL) bc[c4d.DESC_NAME] = "Float" element = obj.AddUserData(bc) obj[element] = 22.2 c4d.EventAdd() AddStringDataType(cube) cube.RemoveUserData(1) AddFloatDataType(cube)
-
Hi,
Even if a user data parameter is removed its data is still stored. And when [] operator is used, the Python API layer checks the type of a parameter before setting its data.
The solution is to usedel()
passing the parameter data to clear its type and value. Then the parameter can be set any data.Here is how I modified the script you posted:
import c4d def AddUserData(obj, dtype, name): if obj is None: return # Retrieves default user data container for the passed type bc = c4d.GetCustomDataTypeDefault(dtype) bc[c4d.DESC_NAME] = name # Adds the user data element = obj.AddUserData(bc) # Returns the user data description ID return element def main(): # Searches for 'Cube' object cube = doc.SearchObject('Cube') if cube is None: return # Adds string user data dataID = AddUserData(cube, c4d.DTYPE_STRING, "String") cube[dataID] = 'bob' # Removes user data cube.RemoveUserData(dataID) # Clears user data type and value del(cube[dataID]) # Adds float user data dataID = AddUserData(cube, c4d.DTYPE_REAL, "Float") cube[dataID] = 22.2 # Updates Cinema c4d.EventAdd() if __name__=='__main__': main()
Note it's recommended to use main() like in the default script. Also when Cinema 4D runs scripts doc is the active document (op is the active object).
-
This worked. Thank you.