Unique name for object



  • Hi,
    I was wonder if the API (C++ and/or Python) has an helper function to generate a unique name for BaseTag, or any BaseList2D-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 argument checknames, 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 a BaseObject into a document. Still when creating a BaseTag 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 only BaseObject.



  • Hi,

    I am not quite sure what you would consider a name, but with C4DAtom.FindUniqueID in combination with c4d.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.