Stuck with loop through tags



  • Hello everyone!

    I`m noobie and working on simple script that should generate on selected layers Redshift Object tag with checked Object ID Override. Also I need to make uniqe Object ID numbers by adding 1 to each tag.

    Problem: When I make loop through tags and try to increase Object ID parameters by 1 (I need 1, 2, 3,...) it pass all the tags exept the last and make the last tag Object ID parameter equal to objects quantity (9 in my case)

    1. How to increase Object ID parameters for each tags with uniqe data from 1 to {tags quantity}?
    2. How to improve this code?

    screenshot

    import c4d
    from c4d import gui
    
    
    
    def main():
        doc.StartUndo()
    
        selection = doc.GetSelection()
        collectedObjects = []
    
    
        if selection:
            for s in selection:
                collectedObjects.append(s)
        else:
            c4d.gui.MessageDialog('Please choose objects')
    
    
        for s in collectedObjects:
            tag = c4d.BaseTag(1036222)
            tag[c4d.REDSHIFT_OBJECT_OBJECTID_OVERRIDE] = True
            s.InsertTag(tag)
            doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
            
            
            
        for tags in range(len(collectedObjects)):
            
            tag[c4d.REDSHIFT_OBJECT_OBJECTID_ID] += 1
            
    
            
        doc.EndUndo()    
            
            
    if __name__=='__main__':
        c4d.CallCommand(13957)
        main()
        c4d.EventAdd()
    

    Thank you for your attention!



  • Hi,

    it is easier just to answer in commented code, you will find anything there.

    import c4d
    from c4d import gui
    
    def main():
    
        # This would also include tags and materials, i.e. is not what you
        # want.    
        # selection = doc.GetSelection()
    
        # This does not accomplish anything. 'selection' is already a list and
        # you just build element by element a new list of it.
    
        # collectedObjects = []
        # if selection:
        #     for s in selection:
        #         collectedObjects.append(s)
        # else:
        #     c4d.gui.MessageDialog('Please choose objects')  
    
        # This part is technically okay, but we will consolidate it with the
        # next loop.
        # for s in collectedObjects:
        #     tag = c4d.BaseTag(1036222)
        #     tag[c4d.REDSHIFT_OBJECT_OBJECTID_OVERRIDE] = True
        #     s.InsertTag(tag)
        #     doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
        
        # You never use your loop variable 'tags'. And you are referencing
        # 'tag', which was the symbol for the BaseTag you did instantiate in 
        # the last loop. Because of that you will only increment the last tag
        # you have created in this last loop over and over.
    
        # for tags in range(len(collectedObjects)):
        #     tag[c4d.REDSHIFT_OBJECT_OBJECTID_ID] += 1
    
        # If you want to enumerate some objects, you could just create a counter
        # and increment it manually.
    
        counter = 0
        for char in ["A", "B", "C", "D"]:
            print counter, char
            counter += 1
    
        # But that would not be very pythonic. Python has the wonderful function
        # enumerate for this scenario, which will enumerate a collection object.
    
        # This will only return the selected BaseObject nodes. See the docs for
        # details. I did choose the flags so that we also include nodes that are
        # not top level nodes and that the returned list reflects the selection
        # order, which seems important in this case.
        flags = (c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER | 
                 c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
        selection = doc.GetActiveObjects(flags)
    
        if not selection:
            raise ValueError("No objects selected.")
    
        doc.StartUndo()
        for i, node in enumerate(selection):
            # Since I do not own ReadShift, I will just be using the annotation
            # tag.
            tag = c4d.BaseList2D(c4d.Tannotation)
            tag[c4d.ANNOTATIONTAG_TEXT] = str(i)
            node.InsertTag(tag)
            doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
        doc.EndUndo()    
        c4d.EventAdd()
              
    if __name__=='__main__':
        #c4d.CallCommand(13957)
        main()
    

    Cheers,
    zipit



  • Hi,

    it is easier just to answer in commented code, you will find anything there.

    import c4d
    from c4d import gui
    
    def main():
    
        # This would also include tags and materials, i.e. is not what you
        # want.    
        # selection = doc.GetSelection()
    
        # This does not accomplish anything. 'selection' is already a list and
        # you just build element by element a new list of it.
    
        # collectedObjects = []
        # if selection:
        #     for s in selection:
        #         collectedObjects.append(s)
        # else:
        #     c4d.gui.MessageDialog('Please choose objects')  
    
        # This part is technically okay, but we will consolidate it with the
        # next loop.
        # for s in collectedObjects:
        #     tag = c4d.BaseTag(1036222)
        #     tag[c4d.REDSHIFT_OBJECT_OBJECTID_OVERRIDE] = True
        #     s.InsertTag(tag)
        #     doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
        
        # You never use your loop variable 'tags'. And you are referencing
        # 'tag', which was the symbol for the BaseTag you did instantiate in 
        # the last loop. Because of that you will only increment the last tag
        # you have created in this last loop over and over.
    
        # for tags in range(len(collectedObjects)):
        #     tag[c4d.REDSHIFT_OBJECT_OBJECTID_ID] += 1
    
        # If you want to enumerate some objects, you could just create a counter
        # and increment it manually.
    
        counter = 0
        for char in ["A", "B", "C", "D"]:
            print counter, char
            counter += 1
    
        # But that would not be very pythonic. Python has the wonderful function
        # enumerate for this scenario, which will enumerate a collection object.
    
        # This will only return the selected BaseObject nodes. See the docs for
        # details. I did choose the flags so that we also include nodes that are
        # not top level nodes and that the returned list reflects the selection
        # order, which seems important in this case.
        flags = (c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER | 
                 c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
        selection = doc.GetActiveObjects(flags)
    
        if not selection:
            raise ValueError("No objects selected.")
    
        doc.StartUndo()
        for i, node in enumerate(selection):
            # Since I do not own ReadShift, I will just be using the annotation
            # tag.
            tag = c4d.BaseList2D(c4d.Tannotation)
            tag[c4d.ANNOTATIONTAG_TEXT] = str(i)
            node.InsertTag(tag)
            doc.AddUndo(c4d.UNDOTYPE_NEW, tag)
        doc.EndUndo()    
        c4d.EventAdd()
              
    if __name__=='__main__':
        #c4d.CallCommand(13957)
        main()
    

    Cheers,
    zipit



  • @zipit I appreciate your answer. Thank you very much!



  • hi @SuperHomiak welcome to the forum.
    Thanks @zipit for the answer :)

    For your next threads, please help us keeping things organised and clean. I know it's not your priority but it really simplify our work here.

    I've set the thread to a question and marked zipit answer as the right answer :)

    Cheers,
    Manuel


Log in to reply