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. -
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 aDescLevel
In the documentation, it gives a parameter description as followst_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 the15
, 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 to100+
. Is there info where it list all data types with the correspondingint
value? (Correct me if I'm wrong but the documentation only provides thestr
value)
For the0
, 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!