Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Attribute Manamger Update Delay When Description Added Dynamically

    Cinema 4D SDK
    python r23
    4
    15
    2.0k
    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.
    • beatgramB
      beatgram
      last edited by beatgram

      Hello guys,

      I'm trying to make a python tag plugin with button. My goal is to add description to tag description when user hit add button in tag property.
      I feel my code works properly but Atrribute Manager doesn't update until I move the current time indicator (see below).
      Is it possible to add descripton dynamically with button in python plugin?
      I searched through this forum and I think "Update button" might be related but I can't understand enough... so please help me if you know the workaround!

      dynamic_description_delay.gif

      Here's my code.
      test_tag.pyp

      import os
      import c4d
      from c4d import plugins
      
      
      PLUGIN_ID = *******
      START_NO = 1100
      
      
      class TestTagData(c4d.plugins.TagData):
          def Init(self, node):
              self.links_list = []
              pd = c4d.PriorityData()
              if pd is None:
                  raise MemoryError("Failed to create a priority data.")
              pd.SetPriorityValue(lValueID = c4d.PRIORITYVALUE_MODE, data = c4d.CYCLE_EXPRESSION)
              node[c4d.EXPRESSION_PRIORITY] = pd
              return True
      
          def Execute(self, tag, doc, op, bt, priority, flags):
              return c4d.EXECUTIONRESULT_OK
      
          def Message(self, node, type, data):
              if type == c4d.MSG_DESCRIPTION_COMMAND:
                  if data["id"][0].id == c4d.TTESTTAG_ADD_BUTTON:
                      bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_BASELISTLINK)
                      self.links_list.append(bc)
              return True
      
          def GetDDescription(self, node, description, flags):
              if not description.LoadDescription(node.GetType()):
                  return False
              singleId = description.GetSingleDescID()
              groupId = c4d.DescID(c4d.DescLevel(c4d.TTESTTAG_LINKS_GROUP, c4d.DTYPE_GROUP, node.GetType()))
              links_num = len(self.links_list)
              if links_num > 0:
                  for i in range(links_num):
                      paramId = c4d.DescID(c4d.DescLevel(START_NO + (i + 1)))
                      if singleId is None or paramId.IsPartOf(singleId)[0]:
                          bc = self.links_list[i]
                          bc.SetString(c4d.DESC_NAME, "Controller " + str(i + 1))
                          bc.SetString(c4d.DESC_SHORT_NAME, "Controller " + str(i + 1))
                          bc.SetInt32(c4d.DESC_ANIMATE, c4d.DESC_ANIMATE_ON)
                          if not description.SetParameter(paramId, bc, groupId):
                              return False
              return (True, flags | c4d.DESCFLAGS_DESC_LOADED)
      
      
      if __name__ == "__main__":
          c4d.plugins.RegisterTagPlugin(id = PLUGIN_ID, str = "Test Tag", info = c4d.TAG_EXPRESSION|c4d.TAG_VISIBLE, g = TestTagData, description = "ttesttag", icon = None)
      

      ttesttag.res

      CONTAINER Ttesttag
      {
          NAME Ttesttag;
          INCLUDE Texpression;
      
          GROUP ID_TAGPROPERTIES
          {
              GROUP TTESTTAG_LINKS_GROUP
              {
                  GROUP
                  {
                      COLUMNS 2;
                      BUTTON TTESTTAG_ADD_BUTTON { SCALE_H; }
                      BUTTON TTESTTAG_REMOVE_BUTTON { SCALE_H; }
                  }
              }
          }
      }
      

      ---------- User Information ----------

      Cinema 4D version: R23
      OS: Windows 10
      Language: Python

      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        @beatgram said in Attribute Manamger Update Delay When Description Added Dynamically:

        self.links_list = []
        (...)
        self.links_list.append(bc)

        This is an instance attribute that you change during the button handling. Changing it will not automatically cause C4D to redraw the GUI, which would be necessary to execute GetDDescription where the interface is actually built. Try to enforce the redraw with c4d.EventAdd().

        beatgramB 1 Reply Last reply Reply Quote 0
        • beatgramB
          beatgram @Cairyn
          last edited by

          @Cairyn Thank you for taking your time.

          I see. So to execute GetDDescription, "c4d.EventAdd()" should be added to Message() function like below?

              def Message(self, node, type, data):
                  if type == c4d.MSG_DESCRIPTION_COMMAND:
                      if data["id"][0].id == c4d.TTESTTAG_ADD_BUTTON:
                          bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_BASELISTLINK)
                          self.links_list.append(bc)
                          c4d.EventAdd()
                  return True
          

          I tried this code but it doesn't work and the result is the same as before.

          1 Reply Last reply Reply Quote 0
          • CairynC
            Cairyn
            last edited by

            Okay, I tested it on my machine, and it seems that you need to use
            node.SetDirty(c4d.DIRTYFLAGS_DESCRIPTION)
            instead of just refreshing the GUI. Apparently the change to the description through SetParameter does not suffice to inform C4D about a necessary redraw.

            This works for me... now I just would like to know why it creates float fields for the 2nd to 4th "Add", but link fields for all others...

            beatgramB 1 Reply Last reply Reply Quote 1
            • beatgramB
              beatgram @Cairyn
              last edited by beatgram

              @Cairyn Thank you again for helping me.
              Yep, SetDirty(c4d.DIRTYFLAGS_DESCRIPTION) works like a charm! 👍

                  def Message(self, node, type, data):
                      if type == c4d.MSG_DESCRIPTION_COMMAND:
                          if data["id"][0].id == c4d.TTESTTAG_ADD_BUTTON:
                              bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_BASELISTLINK)
                              self.links_list.append(bc)
                              node.SetDirty(c4d.DIRTYFLAGS_DESCRIPTION)  # This was needed!
                      return True
              

              I'm sorry but I'm not sure what you mean about float fields for 2nd to 4th "Add". On my end, my code adds link fields everytime user click the Add button.
              Let me know if my understanding is wrong.

              CairynC 1 Reply Last reply Reply Quote 0
              • M
                mp5gosu
                last edited by

                By the way, it is also worth mentioning the Note on MSG_CHANGE

                beatgramB 1 Reply Last reply Reply Quote 0
                • beatgramB
                  beatgram @mp5gosu
                  last edited by

                  @mp5gosu Oh I couldn't find that. Thank you for your heads up!

                  1 Reply Last reply Reply Quote 0
                  • CairynC
                    Cairyn @beatgram
                    last edited by

                    @beatgram I changed some parts of the code since I was wondering about a few details, so this may be solely on my side. Do you have a ttesttag.h file that you don't show, and a .str file? For my test, I created these files (plugin didn't start without). That may have created some differences.

                    beatgramB 1 Reply Last reply Reply Quote 0
                    • beatgramB
                      beatgram @Cairyn
                      last edited by

                      @Cairyn Okay, here's my .h / .str files. Sorry, I should have shared these in the first post.

                      ttesttag.h

                      #ifndef _TTESTTAG_H_
                      #define _TTESTTAG_H_
                      
                      enum
                      {
                          TTESTTAG_LINKS_GROUP = 1001,
                          TTESTTAG_ADD_BUTTON = 1002,
                          TTESTTAG_REMOVE_BUTTON = 1003,
                      }
                      
                      #endif
                      

                      ttesttag.str

                      STRINGTABLE Ttesttag
                      {
                          Ttesttag "Test Tag";
                          TTESTTAG_LINKS_GROUP "";
                          TTESTTAG_ADD_BUTTON "Add";
                          TTESTTAG_REMOVE_BUTTON "Remove";
                      }
                      
                      CairynC 1 Reply Last reply Reply Quote 0
                      • CairynC
                        Cairyn @beatgram
                        last edited by

                        @beatgram Ah yes, that makes sense that these files exist. It doesn't explain the phenomenon though, since I chose precisely the same numeric values...

                        I believe C4D is doing something in the background with these files, otherwise you wouldn't be able to write c4d.TTESTTAG_LINKS_GROUP - this is not a constant that C4D defines, so somehow it is generated in the header parsing process. I suppose I need to look into that, although the original question has been answered now 😉

                        beatgramB 1 Reply Last reply Reply Quote 0
                        • beatgramB
                          beatgram @Cairyn
                          last edited by

                          @Cairyn Interesting investigation but it's a bit difficult for newbie like me. 🙄
                          Anyway, I appreciate your help!

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

                            Hi @beatgram so far nothing to add from our side, what @Cairyn said is the correct way to proceed with node.SetDirty(c4d.DIRTYFLAGS_DESCRIPTION).

                            Regarding ttesttag.h and more generally about resources in Cinema 4D.
                            They are parsed during the startup of Cinema 4D, due to a bug currently if you change the content of the file it will not update it and you will need to update the symbolcache for more information about it see Dealing with Symbolcache.

                            However, I can't really explain why it was creating float description and not DTYPE_BASELISTLINK, if you are able to reproduce the issue please share the whole project so we can look at it. And except if you override the value of DTYPE_BASELISTLINK I don't see any valid reason for the Python symbol parser to produce the change.

                            Cheers,
                            Maxime.

                            MAXON SDK Specialist

                            Development Blog, MAXON Registered Developer

                            beatgramB 1 Reply Last reply Reply Quote 0
                            • beatgramB
                              beatgram @m_adam
                              last edited by

                              @m_adam Thank you for confirming.
                              I already know symbolcache thingy, so it's no problem.

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

                                Hi with the latest update of Cinema 4D (R24 SP1),
                                any update to a description files should now be reflected correctly to the symbolcache files, so it's not needed to delete it manually anymore.

                                Cheers,
                                Maxime.

                                MAXON SDK Specialist

                                Development Blog, MAXON Registered Developer

                                beatgramB 1 Reply Last reply Reply Quote 0
                                • beatgramB
                                  beatgram @m_adam
                                  last edited by beatgram

                                  @m_adam Oh, that's a little update for many users but huge for tiny developers like me!
                                  Thank you so much for the heads up. 😳

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