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

    Dynamic Update on Plug-ins

    Cinema 4D SDK
    r20 python
    3
    5
    641
    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.
    • B
      bentraje
      last edited by

      NOTE: Not talking about updating to new version but updating the execution of the plug-in.

      I have a test plug-in that prints out "There are no objects in the scene" or "There are # objects in the scene".
      It works as expected upon initial open of the plug-in but not through-out.

      You can see an illustration of the problem here:
      https://www.dropbox.com/s/6j0aqtvgg6o2vg6/c4d131_automatic_update-plug-in.mp4?dl=0

      Thank you for looking at my problem

      P.S. I need the LayoutFLushGroup and LayoutChanged in the code since I'm planning to list all objects and all their parameters.

      You can see the illustration code here:

      import c4d
      import os
      from c4d import gui, plugins, bitmaps, utils, documents
      
      
      
      PLUGIN_ID   = 1011321
      
      class MyDialog(gui.GeDialog):
      
      
          def get_all_objects(self, op):
          
            output = []
            
            while op:
                output.append(op)
                self.get_all_objects(op.GetDown())
                op = op.GetNext()
      
            return output
      
          def CreateLayout(self):
      
            doc = c4d.documents.GetActiveDocument()
      
            self.object_count = len(self.get_all_objects(doc.GetFirstObject()))
      
            self.GroupBegin(id=1000, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging")
      
      
            if self.object_count == 0:
              self.LayoutFlushGroup(1001)
              self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene")
              self.LayoutChanged(1001)
      
      
            if self.object_count > 0 :
              self.LayoutFlushGroup(1001)
              self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count)
              self.LayoutChanged(1001)
      
            self.GroupEnd()
      
            return True
      
          def Command(self, id, msg):
      
              return True
      
      class MyMenuPlugin(plugins.CommandData): 
          
          dialog = None 
          def Execute(self, doc): 
      
             if self.dialog is None: 
                self.dialog = MyDialog() 
      
             return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) 
      
      if __name__ == "__main__": 
      
          plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())   
      
      
      1 Reply Last reply Reply Quote 0
      • C4DSC
        C4DS
        last edited by

        I haven't looked at your dropbox video, but from your explanation I seem to understand you will have to listen and react to message EVMSG_CHANGE. There is no other way to react to objects being added, or removed from the Object Manager.
        Obviously, the EVMSG_CHANGE will be called for every little change that occur in a scene, so you will probably need to filter out "false positives", if you don't want/need to update too frequently.

        1 Reply Last reply Reply Quote 1
        • B
          bentraje
          last edited by

          @C4DS
          Thanks for the response. I incorporated the EVMSG_CHANGE. It does not error out but it also does not work as expected (Behavior is still the same as before). Is there a way around this?

          You can check the revised code here:

          import c4d
          import os
          from c4d import gui, plugins, bitmaps, utils, documents
          
          
          
          PLUGIN_ID   = 1011321
          
          class MyDialog(gui.GeDialog):
          
          
              def get_all_objects(self, op):
              
                output = []
                
                while op:
                    output.append(op)
                    self.get_all_objects(op.GetDown())
                    op = op.GetNext()
          
                return output
          
          
              def Update(self): # NEW CODE
          
                if self.object_count == 0:
                  self.LayoutFlushGroup(1001)
                  self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene")
                  self.LayoutChanged(1001)
          
                if self.object_count > 0 :
                  self.LayoutFlushGroup(1001)
                  self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count)
                  self.LayoutChanged(1001)
          
              def CreateLayout(self):
          
                doc = c4d.documents.GetActiveDocument()
          
                self.object_count = len(self.get_all_objects(doc.GetFirstObject()))
          
                self.GroupBegin(id=1001, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging")
          
                self.GroupEnd()
          
                self.Update() # NEW CODE
          
                return True
          
              def Command(self, id, msg):
          
                return True
          
              def CoreMessage(self, id, msg):
          
                if id == c4d.EVMSG_CHANGE: # NEW CODE
                  self.Update()
          
                return True
          
          class MyMenuPlugin(plugins.CommandData):
          
              
              dialog = None 
              def Execute(self, doc): 
          
                 if self.dialog is None: 
                    self.dialog = MyDialog() 
          
                 return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) 
          
          if __name__ == "__main__": 
          
              plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())   
          
          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by Manuel

            hello @bentraje,

            In your code get_all_objects was not called and not updating object_count

            I've changed your code a bit. I've used a non-recursive hierarchy iteration found in our blog[URL-REMOVED] so you don't hit the stack limit in case of a big hierarchy.

            InitValues is called after CreateLayout so that's why I've used __init__ in the first place to init my values.

            In my code i'm using self.objectsList to store the object list. It's just for this example, GeDialog is not the best place to store data.

            import c4d
            import os
            from c4d import gui, plugins, bitmaps, utils, documents
            
            
            
            PLUGIN_ID   = 1011321
            
            class MyDialog(gui.GeDialog):
                
                def __init__(self):
                    # Be sure that we have the object list before building the UI
                    # as InitValues is called after CreateLayout()
                    self.objectsList = []
                    self.GetAllObjects()
                    self.object_count = len(self.objectsList)
            
            
                def InitValues(self):
                    # Use to Init and in Case of an Update needed.
                    self.objectsList = []
                    self.GetAllObjects()
                    self.object_count = len(self.objectsList)
                    self.Update()
                    return True
            
                def GetNextObject(self, op ):
                    # use a non-recursive method to iterate the hierarchy
                    # [URL-REMOVED]
                    # allow to not hit the recursive stack limit.
                    
                    if not op:
                        return None
            
                    if op.GetDown():
                        return op.GetDown()
            
                    while not op.GetNext() and op.GetUp():
                        op = op.GetUp()
            
                    return op.GetNext()
            
                def GetAllObjects(self):
                
                    doc = c4d.documents.GetActiveDocument()
                    op = doc.GetFirstObject()
            
                    self.objectsList = []
                  
                    while op:
                        self.objectsList.append(op)
                        op = self.GetNextObject(op)
            
                    
            
            
                def Update(self): # NEW CODE
            
                    if self.object_count == 0:
                        self.LayoutFlushGroup(1001)
                        self.AddStaticText(0, c4d.BFH_CENTER, name="There are no objects in the scene")
                        self.LayoutChanged(1001)
            
                    if self.object_count > 0 :
                        self.LayoutFlushGroup(1001)
                        self.AddStaticText(0, c4d.BFH_CENTER, name="There are %s objects in the scene" %self.object_count)
                        self.LayoutChanged(1001)
            
                def CreateLayout(self):
            
                            
                    print "nombre d'objet ", self.object_count
                    self.GroupBegin(id=1001, flags=c4d.BFH_FIT, cols=0, rows=4, title="Rigging")
            
                    self.GroupEnd()
            
                    self.Update() # NEW CODE
            
                    return True
            
                def Command(self, id, msg):
            
                    return True
            
            
                def CoreMessage(self, id, msg):
            
                    if id == c4d.EVMSG_CHANGE: # NEW CODE
            
                        self.InitValues()
            
                    return True
            
            class MyMenuPlugin(plugins.CommandData):
            
                
                dialog = None 
                def Execute(self, doc): 
            
                    if self.dialog is None: 
                        self.dialog = MyDialog() 
            
                    return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=200, defaulth=150, xpos=-1, ypos=-1) 
            
            if __name__ == "__main__": 
            
                plugins.RegisterCommandPlugin(PLUGIN_ID, "BT Utilities",0, None, "Python Menu", MyMenuPlugin())   
            
            

            Cheers
            Manuel


            [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 2
            • B
              bentraje
              last edited by

              Hi @m_magalhaes

              Thanks for the response and clarification specially with the
              def __init___ and def InitValuesthat was news to me.

              The plug-in works as expected. Have a great day ahead!

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