Solved 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 value

Anyone know any workarounds? Like how to flush the memory of the user data?

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 use del() 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).

Former MAXON SDK Engineer

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 use del() 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).

Former MAXON SDK Engineer

This worked. Thank you.