How to find back a specific BaseTag assigned to a BaseObject



  • Hi,

    I need a way to identify a specific tag instance of type Tpolygonselection.
    I create said tag and add it as the first tag to a PolygonObject.
    After which I perform multiple SendModelingCommand on the object (MCOMMAND_JOIN, MCOMMAND_DELETE, MCOMMAND_OPTIMIZE, etc ...). As a result of these actions, the order of the tags get reorganized, and I cannot simply get the first tag and assume it's THE ONE.

    I was wondering, except of providing the tag a "unique" name, how could I distinguish it from any other polygon selection tag the user might have created?
    At first I thought to simply add some information into the tag's BaseContainer. But as a result of all the SendModelingCommand that information does not survive. I seem to have tried this already in the past, but cannot seem to find the topic back.

    Using a "unique" name is quite a tricky solution. While in theory I could define any name long and complex enough to be unique, it still doesn't prevent from ending up with a non-unique name. And it's GUUID or other unique marker might change overtime, as a result of all the SendModelingCommand being performed.

    So, how to find back that one tag I created?



  • Hi @C4DS, thanks for reaching out us and sorry for being late here.

    With regard to your topic, I see the problem and actually there's no API data that can help in making your life easier.
    At the same time, considering that the name is preserved across the deletion and re-creation of selection tags when modeling commands take place, you can make good use of it by hashing the FindUniqueID to obtain a unique string.

    The idea is pretty simple: adding the string representation of the hash of the ByteSeq returned from the FindUniqueID to the PolygonSelection name will make your PolygonSelection "pretty" unique and identifying the ONE shouldn't be an issue anymore.

    The code below, given two meshes each with 3 poly sel tags, shows consistent results with regard to the naming of the tags although the order in the final list is not maintained

    import c4d
    
    def optimize(obj, tolerance) :
        doc = c4d.documents.GetActiveDocument()
    
        # perform the optimization
        settings = c4d.BaseContainer()
        settings[c4d.MDATA_OPTIMIZE_TOLERANCE] = tolerance
        settings[c4d.MDATA_OPTIMIZE_POINTS] = True
        settings[c4d.MDATA_OPTIMIZE_POLYGONS] = True
        settings[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
        c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_OPTIMIZE,
                                      list=[obj],
                                      mode=c4d.MODELINGCOMMANDMODE_ALL,
                                      bc=settings,
                                      doc=doc)
    def join(listofObjs, joinSel) :
        doc = c4d.documents.GetActiveDocument()
    
        # make the objects to be joined child of a null
        joinres = c4d.BaseObject(c4d.Onull)
        joinres.SetName("EndResult")
        for obj in listofObjs:
            obj.InsertUnder(joinres)
    
        # perform the join
        settings = c4d.BaseContainer()
        settings[c4d.MDATA_JOIN_MERGE_SELTAGS] = joinSel
        res = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_JOIN,
                                      list=[joinres],
                                      mode=c4d.MODELINGCOMMANDMODE_ALL,
                                      bc=settings,
                                      doc=doc)
        return res[0]
    
    def hashByteSeq(seq):
        res = ""
        for x in range(1,len(seq)):
            res += str(ord(seq[x]))
    
        return hash(res)
    
    def main():
    
        selectedObjs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER)
        if selectedObjs is None:
            return 
            
        print "Selection tags' name before modeling performing modeling"
        for obj in selectedObjs:
            selTag = obj.GetTag(c4d.Tpolygonselection)
            while selTag is not None and selTag.IsInstanceOf(c4d.Tpolygonselection):
                selTag.SetName(selTag.GetName() +"_HASH["+ str(hashByteSeq(selTag.FindUniqueID(c4d.MAXON_CREATOR_ID)))+"]")
                print selTag.GetName()
                selTag = selTag.GetNext()
    
        # perform the modeling operation
        resObj = join (selectedObjs, False)
        doc.InsertObject(resObj)
        optimize(resObj, 2)    
        c4d.EventAdd()
    
        print "Selection tags' name after modeling performing modeling"
        selTag = resObj.GetTag(c4d.Tpolygonselection)
        while selTag is not None and selTag.IsInstanceOf(c4d.Tpolygonselection):
            print selTag.GetName()
            selTag = selTag.GetNext()
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    Output

    Selection tags' name before modeling performing modeling
    Polygon Selection_HASH[-6888866472923475632]
    Polygon Selection_HASH[-213355520699517116]
    Polygon Selection_HASH[-5105658090163678661]
    Polygon Selection_HASH[-3077831708260302816]
    Polygon Selection_HASH[-7970150277820464537]
    Polygon Selection_HASH[-5099327291605991706]
    Selection tags' name after modeling performing modeling
    Polygon Selection_HASH[-3077831708260302816]
    Polygon Selection_HASH[-7970150277820464537]
    Polygon Selection_HASH[-5099327291605991706]
    Polygon Selection_HASH[-6888866472923475632]
    Polygon Selection_HASH[-213355520699517116]
    Polygon Selection_HASH[-5105658090163678661]
    

    It's maybe not an elegant solution but hope it could help you workaround your issue.

    Best, R



  • @r_gigante said in How to find back a specific BaseTag assigned to a BaseObject:

    FindUniqueID

    Looking up FindUniqueID in the documentation I noticed AddUniqueID and had hoped this could be used with a custom defined ID to store some data in the selection tag. Then later, performing a FindUniqueID with the same unique ID to find back that specific tag. Not necessarily for storing data to be retrieved, but to have an ID added to the tag, which no other tag has.

    Unfortunately, the added unique ID does not survive a connect + delete action.

    From the documentation I had the impression the added data would have been maintained.
    I am right to expect the data should have been maintained?



  • Hi @C4DS, I think that when a new BaseList2D is created from scratch (not cloned) the data set via AddUniqueID is not kept.

    Best, R



  • @r_gigante said in How to find back a specific BaseTag assigned to a BaseObject:

    I think that when a new BaseList2D is created from scratch (not cloned) the data set via AddUniqueID is not kept.

    That I can understand.
    But if you:

    • create 2 objects
    • create a polygon selection for each object
    • give both selection tags a specific name
    • perform an AddUniqueID on both selection tags
    • do a connect + delete with the 2 objects

    you end up with a single merged object, which has 2 selection tags, and both still have the specific name ... but none have the added unique ID. Surely you start to think something is really wrong.

    If a new BaseList2D is created from scratch, and the name is taken over, then why is the added unique ID not taken over? I don't get that. To me this is just another bug.
    Someone thought of providing an interface in the API to add a unique ID, and also provide an interface to find it back. And someone even thought about copying over the name ... But no one thought of copying over the unique ID data?



  • Hi @C4DS , maybe I wasn't enough clear.

    you end up with a single merged object, which has 2 selection tags, and both still have the specific name ... but none have the added unique ID. Surely you start to think something is really wrong.

    Actually you end up in a new mesh with new selection tags which beside having the data copied from the two source selection tags, they are NEW and hence the UniqueID is not supposed to be kept. The names are kept for convenience but I don't see any reason to have also the UniqueID being kept considering that - in the end - they are indeed new instances and have nothing to do with the source selection tags.

    Cheers, R