Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    RemoveUserData does not fully remove User Data

    Cinema 4D SDK
    python
    2
    4
    1.5k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      dmp
      last edited by r_gigante

      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?

      1 Reply Last reply Reply Quote 0
      • D
        dmp
        last edited by dmp

        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)
        
        1 Reply Last reply Reply Quote 0
        • Y
          y_puech
          last edited by y_puech

          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

          1 Reply Last reply Reply Quote 0
          • D
            dmp
            last edited by

            This worked. Thank you.

            1 Reply Last reply Reply Quote 0
            • First post
              Last post