Unique name for object
-
Hi,
I was wonder if the API (C++ and/or Python) has an helper function to generate a unique name forBaseTag
, or anyBaseList2D
-derived object in general?Example:
In case you create a polygon selection tag, it's default name is "Polygon Selection". Create an additional one and it will be named "Polygon Selection.1", etc ... Same for objects in the Object Manager.This seems trivial functionality which is used on different places that I would assume it is a common function used throughout the application, when it needs to generate a default name for an object.
I understand this would be easy to set up one-self by looking up if the default name is already in use, and increment a suffix until the name is unique.
As I am lazy I'd rather use some existing implementation instead of trying the reinvent the wheel.
I just cannot figure out an appropriate function name to perform a search on. Hence I haven't yet found such helper function in the SDK ... if there is one available. -
BaseDocument::InsertObject()
has the argumentchecknames
, used to perform that unique name creation. Strangely, the option is marked as deprecated in the C++ API, but not the Python API.See Checknames option.
-
@PluginStudent
Thanks for that.
But that is only when inserting aBaseObject
into a document. Still when creating aBaseTag
the same behaviour happens behind the scenes, but seems not to be available within the SDK.As such I can understand the
checknames
to be deprecated. As a more generic solution would be advised for any naming to be made unique, not onlyBaseObject
. -
Hi,
I am not quite sure what you would consider a name, but with
C4DAtom.FindUniqueID
in combination withc4d.MAXON_CREATOR_ID
you can hash atoms in a document. I had recently some questions about it here, if you are interested in the collision resistance of the method.You could then map this hash (i think this is a 64 bit or 8 character hash) to a shorter, more user friendly hash (in Python you could do this with
hashlib
). If you want some sort of ordering, e.g. an alphanumerical one, you probably will need some sort of object/type that manages that. At least I do not know a way how to do this out of the box, other than Cinema's build in naming scheme, which sort of tries to avoid collisions, but is not perfect.Cheers,
zipit -
OK ... so I reinvented the wheel.
# make unique tag name def makeUniqueTagName(theTag): if theTag != None: obj = theTag.GetObject() # get all names of the tags of same type usedNames = [] if obj != None: tag = obj.GetFirstTag() while tag != None: # skip the tag and # ignore tags of other types if tag != theTag and tag.IsInstanceOf(theTag.GetType()) == True: usedNames.append(tag.GetName()) tag = tag.GetNext() # If the name is already taken we will append a dot and number # and increment the number until a unique name is found. # Note that since we have created the tag we can assume that # the original name does not have a dot and number already. suffix = 0 uniqueName = theTag.GetName() while uniqueName in usedNames: suffix = suffix + 1 uniqueName = theTag.GetName() + '.' + str(suffix) theTag.SetName(uniqueName) return
Maybe not the best nor cleanest code, but then again I am not used to code in Python.
I am sure others might have a better solution, but this seems to work for what I need, so I am happy with how it turned out.