Access Custom User Data By Name (not by ID)



  • 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.



  • 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.



  • @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.



  • 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.



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


Log in to reply