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

    Access Custom User Data By Name (not by ID)

    Cinema 4D SDK
    r20 python
    2
    5
    1.4k
    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.
    • B
      bentraje
      last edited by

      Hi,

      Is there a way to access user data by name and not by ID? Base on this post (May 2018), it is not yet possible. But I'm wondering if there is a recent change that allows so.

      I'm trying to write a procedure where
      (1) It checks if a user data has been created
      (2) If it exist, ignore
      (3) If it doesn't exist, create the user data.

      That is why I needed the name of user data. Is there a way around this? Or if you have better way of doing this. I am all ears.

      Thank you for looking at the problem.

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @bentraje this can be done by iterating through the UserData Description Container.
        Then you can Check for DESC_NAME like so:

        import c4d
        
        def IsUserDataPresentByName(obj, name):
            """
            Check if an user data parameter is already named like that on the passed obj
            :param obj: Any object that can holds User Data
            :param name: the name to looking for
            """
            
            if op is None:
                raise TypeError("obj is none.")
            
            if not name or not isinstance(name, str):
                raise TypeError("name is not valid.")
            
            # Iterate over all users data description
            for userDataId, bc in obj.GetUserDataContainer():
                
                # Retrieves the current name we iterates
                currentName = bc.GetString(c4d.DESC_NAME)
                
                # If the name is the same return True
                if currentName == name:
                    return True
                
            # If we ended the loop without returning that means we didn't found our description
            return False
                
        def createIntSliderUserData(obj, value, sliderText=""):
            """
            Create a slider of integer on the given object.
            :param value: int => default value of the slider
            :param sliderText: the name of the slider
            """
            
            bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
            bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_LONGSLIDER
            bc[c4d.DESC_NAME] = sliderText
            bc[c4d.DESC_MIN] = 10
            bc[c4d.DESC_MAX] = 100
            description = obj.AddUserData(bc)
            if description is None:
                raise RuntimeError("Failed to creates a UserData.")
            
            obj[description] = value
            return description
        
        def main():
            if not IsUserDataPresentByName(op, "Something"):
                createIntSliderUserData(op, 50, "Something")
                c4d.EventAdd()
            
        
        # Execute main()
        if __name__=='__main__':
            main()
        

        If you have any question, please let me know.
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 2
        • B
          bentraje
          last edited by

          @m_adam

          Thanks for the response. Works as expected. Appreciate the code a lot.

          Just a quick question on GetUserDataContainer()
          It returns a tuple: First is the DescID and the second Container.

          Running your script as default, it returns a description of
          ((700, 5, 0), (1, 15, 0))

          I run a type() command on this and it returns a DescLevel
          In the documentation, it gives a parameter description as follows

          t_id (int) – Initial value for id.
          t_datatype (int) – Initial value for dtype.
          t_creator (int) – Initial value for creator.
          
          

          There are two DescLevels above.
          (1) My question for first one (700, 5, 0) is where did it came from? Why 700 and why 5?

          (2) For the second one, I get the 1 as the ID. No question here
          For the 15, I get this is a data type but the list is erratic. I tried changing data type on creation and it gave me varied result up to 100+. Is there info where it list all data types with the corresponding int value? (Correct me if I'm wrong but the documentation only provides the str value)
          For the 0, not sure why it is zero.

          P.S. To be honest, I'm not sure if my additional question is going to help me. Just trying to explore 🙂

          Thanks again for looking at my problem.

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by m_adam

            700 is the ID of the UserData Container (c4d.ID_USERDATA) 5 is the type, as I said it's a container of other objects so 5 is the numerical representation of c4d.DTYPE_SUBCONTAINER.

            Value of datatypes are not bound to a given range, see DTYPE. No value is printed in the documentation but you can print the value in the console.

            Moreover, in C++ you can also register CustomDataType to retrieves a full list of existing DataType for a c4d instance you can use c4d.plugins.FilterPluginList(c4d.PLUGINTYPE_CUSTOMDATATYPE, True)

            I hope it answers your question.
            Cheers,
            Maxime.

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 2
            • B
              bentraje
              last edited by

              Thanks for the response @m_adam
              Have a great day ahead!

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