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 plugin and Dirty check

    Cinema 4D SDK
    r20 python
    2
    5
    817
    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 pim

      I have a tag plugin that is attached to an object with several children.
      In the tag I test if one of the childrens matrix is changed.

      class AFONTTAG(plugins.TagData):
          def Execute(self, tag, doc, op, bt, priority, flags):
              child = op.GetDown().GetDown()    
              if (child.IsDirty(c4d.DIRTYFLAGS_MATRIX)): 
                 ....
      

      My issue is that, if one of the children is dirty (in this case due to scaling), I get the scale of the child using child[c4d.ID_BASEOBJECT_REL_SCALE], to calculate the new size of the object.

      Note: This is done is Object Mode, because one of the grandchildren has a Pose Morph tag.

      To calculate the size I use GetRad() and multiple it with the scale.

      However, sometimes GetRad() returns (0,0,0)?

      I know the tag is threaded, so that might have something to do with it?
      I do not insert objects, just change the position of the children.

      What am I doing wrong?

      class AFONTTAG(plugins.TagData):
      
          def Execute(self, tag, doc, op, bt, priority, flags):
      
              child = op.GetDown().GetDown()    
      
              if (child.IsDirty(c4d.DIRTYFLAGS_MATRIX)): 
                  bbRadiusA = child.GetRad()
                  if (bbRadiusA[0] == 0):             #Sometime zero!!!
                      print "error: ", bbRadiusA
                      return True
                  
                  if (doc.GetAction() == c4d.ID_MODELING_SCALE):                        
                      a = child.GetRad()
                      b = child[c4d.ID_BASEOBJECT_REL_SCALE]
                      bbRadiusA = a * c4d.Matrix(v1=c4d.Vector(b[0],0,0), v2=c4d.Vector(0,b[1],0), v3=c4d.Vector(0,0,b[2]))
      
                  .....
                      
              return c4d.EXECUTIONRESULT_OK
              
      if __name__ == "__main__":
      
          bmp = bitmaps.BaseBitmap()
          dir, file = os.path.split(__file__) 
          bitmapfile = os.path.join(dir, "res", "AFont.png")
          result = bmp.InitWith(bitmapfile)
          
          PLUGINSTRINGTAG = "AFont TEST"
          okyn = plugins.RegisterTagPlugin(id=PLUGIN_ID_AFONTTAG, str=PLUGINSTRINGTAG, info=c4d.TAG_VISIBLE|c4d.TAG_EXPRESSION|c4d.TAG_MULTIPLE, g=AFONTTAG, description="afonttag",  icon=bmp)
          if (not okyn): 
              print "Error initializing " + PLUGINSTRINGTAG
              
      

      Here the hierarchy.
      9870fabf-329e-40d8-80c9-cef5bba5c15a-image.png

      1 Reply Last reply Reply Quote 0
      • r_giganteR
        r_gigante
        last edited by

        Hi pim, thanks for reaching out us.

        With regard to your issue I've tried to replicate the behavior and I was able to have the BaseObject::GetRad() returning a 0-valued vector only when performing undo steps.
        If this is the sole case then it's likely to be caused by the Subdivision Surface generator actually regenerating its cache after your custom tag has been executed. This is also confirmed with the Subdivision Surface generator not being in the hierarchy: all the tests never produced a single 0-valued vector returned by BaseObject::GetRad().

        If, instead, you're able to reproduce in a different scenario, please provide detailed steps in order to dig down more.

        Cheers, Riccardo

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

          Ok, but how to solve the issue "Subdivision Surface generator actually regenerating its cache after your custom tag has been executed."? What can I do know that the BaseObject::GetRad() will return a valid value?

          For example, set the priority, wait awhile, etc.?

          -Pim

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

            Ok, I have a scene file and a plugin that reproduces the error all the time.

            The error is always there when I have saved the file and reload the file.
            In Execute(), I test whether one of the children is dirty and this is true when loading the scene.
            I then get the bounding box of the children and there it goes wrong.
            Cinema always returns a bbox of zero.

            3af77ee5-868a-4590-b467-9c905076f533-image.png
            No Undo steps are performed.

            Here the Execute() part of the tag plugin (only the part to show where it goes wrong).

                def Execute(self, tag, doc, op, bt, priority, flags):
            
                    children = op.GetChildren()
                    
                    childIsDirty = False
                    for index, obj in enumerate(children):      # check if one of the children is dirty.
                        child = obj.GetDown()      
            
                        if not(child): return True
                        if (child.IsDirty(c4d.DIRTYFLAGS_MATRIX)): 
                            childIsDirty = True
                            break
                            
                    if (childIsDirty):
                        for child in children:     
                            sssObj = child.GetDown()                # get Subdivision Surface Object
                            bbRadiusA = sssObj.GetRad()             # Get BBox
                            if (bbRadiusA[0] == 0):
                                print "ERROR GetRad: ", bbRadiusA, sssObj.GetName()    
                                                        
                    return c4d.EXECUTIONRESULT_OK
            

            If needed I can send you the complete source file and the scene file.

            Hope we can solve this.
            -Pim

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

              I create a workaround that is working.
              I think, like you say, that the Subdivision Surface is not ok, when I initially load the scene.
              I now get the polygon object under the sss and that works.

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