Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Tag used on multiple objects.

    Cinema 4D SDK
    python r20
    2
    6
    956
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      pim
      last edited by

      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)
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        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.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • P
          pim
          last edited by

          @m_adam said in Tag used on multiple objects.:

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

          Thank you, thank you!!!

          1 Reply Last reply Reply Quote 0
          • P
            pim
            last edited by pim

            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

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by

              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.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              1 Reply Last reply Reply Quote 1
              • P
                pim
                last edited by

                Read() and Write() works. Thanks.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post