Tag used on multiple objects.



  • I have created a tagdata plugin, that I put on various objects in the hierachy.
    So, the tag is used more than once.
    In the tag I have create a Class variable, but it seems that that variable is the same for all the plugins.

    I added c4d.TAG_MULTIPLE in the registration of the tag plugin, but that did not seem to help.

    What should I do, to get a unique variable (here the distances list) for each instance of the tag?

    Here some code.

    class AFONTTAG(plugins.TagData):
            
            distances = []
        
            def Execute(self, tag, doc, op, bt, priority, flags):
                if (len(self.distances) == 0):
                    children = op.GetChildren()
                    for index in range(len(children)):    #init list depending on number of children
                        self.distances.append(0)          # list should be unique for each instance of the tag
                ....
        
        if __name__ == "__main__": 
            #Register the tag plugin
            okyn = plugins.RegisterTagPlugin(id=PLUGIN_ID_AFONTTAG, str=PLUGINSTRING, info=c4d.TAG_VISIBLE|c4d.TAG_EXPRESSION|c4d.TAG_MULTIPLE, g=AFONTTAG, description="afonttag",  icon=bmp)


  • Hi @pim,

    The main issue is the scope, defining distances as you did, defines distances in the scope of the object AFONTTAG (the class object, not the instance). So it's shared between each instance since distance becomes an attribute of the object, and due to the nature of list in python data are shared(see http://interactivepython.org/runestone/static/CS152f17/Lists/ListsareMutable.html).

    To fix that defines your variable in the scope of your instance.

    class AFONTTAG(plugins.TagData):
        def __init__(self):
            self.distances = []
    

    Cheers,
    Maxime.



  • @m_adam said in Tag used on multiple objects.:

    def __init__(self):
        self.distances = []
    

    Thank you, thank you!!!



  • Sorry, I have another question.

    I am not sure when to initialize my self.distances list?

    The list is initialized with information from the children under the object the tag is attached to.
    So, when the object has 6 children, the length of the list is 6.

    When running the tag for the first it is ok.
    But when I save and re-open the file, I am not sure when to initialize the distances list.
    The distances list seems to be of length 0, when I re-open the scene.

    Also because the tag is running in a thread, it seems that when the distances list is initialized in Execute(), after re-opening the scene, things go wrong.

    I have a command file that insert a null with 6 children under it.
    Then I add the tag to the null.
    So, when to initialize the list and what is the impact of the fact that the tag is threaded?

    When or in what sequence are __ init__(), Init() and Execute() executed?

    -Pim



  • Hi @pim, the usual way is to write data in the BaseContainer of the object so they will be automatically saved in the BaseObject, then in your init you can check if the data exists in this BaseContainer and if its the case restore them.
    While its the preferred way, it's not always possible since BaseContainer only supports predefined Type.

    Another solution is to override NodeData.Read / Write methods. NodeData.Read will be called at the opening of the file, NodeData.Write will be called when the file is saved. You can find a more complete manual in the C++ documentation NodeData::Read() / NodeData::Write() Manual.

    Additionally, you may want to override NodeData.CopyTo, this method will be called each time the user copy a TagData, so you can reset your list for example. You can find more information in the C++ documentation NodeData::CopyTo() Manual.

    If you have any questions, please let me know.
    Cheers,
    Maxime.



  • Read() and Write() works. Thanks.


Log in to reply