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
    • Recent
    • Tags
    • Users
    • Login

    Objectdata plugin is not refreshed / updated

    Scheduled Pinned Locked Moved PYTHON Development
    15 Posts 0 Posters 1.1k Views
    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.
    • H Offline
      Helper
      last edited by

      On 26/04/2013 at 09:01, xxxxxxxx wrote:

      Ok, because the spline is not part of the plugin, it is not updated?

      The first time the plugin works, because I add a spline as child to the plugin?
      After that, changing the spline is not refreshed.
      However changing (e.g. from top to right) refreshed the plugin.

      I will try and use a link.

      Thanks for the support.

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 26/04/2013 at 09:29, xxxxxxxx wrote:

        hm,

        something i haven't thought of is that there is a special flag for your scenario. that your
        plugin is updated under certain conditions and under some not might be caused by your 
        current flag. so you might want to try the  _OBJECT_INPUT  _flag, which will kind of 
        automate this desired caching behaviour i guess.

        plugins.RegisterObjectPlugin(...
        `

        • Object Plugin Flags
        _<_t_<__<_t_>_<_<_t_>_lgroup> OBJECT_MODIFIER Modifier object. Deforms the surrounding object. (E.g. bend.)
        OBJECT_HIERARCHYMODIFIER Hierarchical modifier. Deforms the surrounding objects together with other instances in a hierarchy chain. Only the top-most instance of the plugin in a chain is called. (E.g. bones.)
        OBJECT_GENERATOR Generator object. Produces a polygonal or spline representation on its own. (E.g. primitive cube.)
        OBJECT_INPUT Used in combination with  OBJECT_GENERATOR. Specifies that the generator uses builds a polygon or spline, using its subobjects as input. (E.g. Sweep NURBS, Boolean.)
        OBJECT_PARTICLEMODIFIER Particle modifier.
        OBJECT_ISSPLINE The object is a spline.
        OBJECT_USECACHECOLOR If this flag is specified, the generator object itself controls the objects' colors (the ones that determine the wireframe/shaded color). Normally these are automatically overwritten by the generator objects settings. E.g. if the instance object is set to green, automatically all of its cache objects get the green color. By setting this flag an instance object could individually color objects.
        OBJECT_CAMERADEPENDENT Camera dependent.
        OBJECT_POINTOBJECT Point Object.
        OBJECT_POLYGONOBJECT Polygon object.
        OBJECT_NO_PLA Objects derived from PointObject[URL-REMOVED] will not use auto-keyframing (e.g. Joints can contain points and PLA auto-keyframing is not useful for them)
        OBJECT_DONTFREECACHE Objects' (generators) caches will not be be deleted - users must maintain caches themselves.
        OBJECT_CALL_ADDEXECUTION Must be set to call ObjectData.Execute()[URL-REMOVED] in the priority pipeline specified by ObjectData.AddToExecution()[URL-REMOVED]._<_t_>_

        `


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

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 26/04/2013 at 10:23, xxxxxxxx wrote:

          Ok, I changed it, but no success.

              okyn = plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="SweepObj",
                                          g=SweepObj,
                                          description="SweepObj", icon=icon,
                                          info=c4d.OBJECT_GENERATOR | c4d.OBJECT_INPUT)
          
          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 26/04/2013 at 11:07, xxxxxxxx wrote:

            Using a link, it works!
            Thanks.

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 26/04/2013 at 13:24, xxxxxxxx wrote:

              i am not sure why the flag is not working. please note, that it was only a guess, it is 
              not guaranteed that the flag is meant to add that special cache rebuilding behaviour.

              alternatively you could follow just the NodeData.Message() approach., if you want to 
              maintain the c4d workflow. simply store a reference to the path object in your class
              and each time Message() receives a change msgid, test if self.reference is node.GetDown()
              and flag your node dirty depending on the result.

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 26/04/2013 at 13:56, xxxxxxxx wrote:

                Thanks for all your help and I understand it was only a guess.

                I have to think and of course try out, your other option, the NodeData.message approach.

                I have read some other posts about other simular issues
                I now better understand and it might be an option, something ScottA posted:
                What about triggering a hidden UserData field in your code to update it instead?
                https://developers.maxon.net/forum/topic/6070/6249_getcontour-refresh-or-uncache-how&PID=26194#26194

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 26/04/2013 at 14:04, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  alternatively you could follow just the NodeData.Message() approach., if you want to 
                  maintain the c4d workflow. simply store a reference to the path object in your class
                  and each time Message() receives a change msgid, test if self.reference is node.GetDown()
                  and flag your node dirty depending on the result.

                  You mean:
                  Listen to NodeData.Message( self , node , type , data )
                  if self.reference = child object (node.getdown())
                      set dirty plugin node

                  Not quite sure about it, but I''ll give it a try.

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    On 26/04/2013 at 14:18, xxxxxxxx wrote:

                    i think you mean == instead = and i am not sure about the rest of the line, but despite that
                    i actually meant the is keyword.

                    def __init__(self) :
                        self.reference = None
                      
                    def Message(self, node, type, data) :
                        if node.getdown() is not self.reference:
                            self.reference = node.GetDown()
                            node.SetDirty(0)
                    

                    practically you could check first if the msg id is the change msg and only then execute the rest.
                    you would also have to check the case where the object is the same, but the bc has changed.
                    for a parametric spline for example which is animated.

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 26/04/2013 at 14:48, xxxxxxxx wrote:

                      It is working and more simple then we thought.
                      All I did was remove the following lines:

                      def __init__(self) :
                              self.SetOptimizeCache(True)

                      The downside is that Render Active View is not working anymore!
                      More testing to do.

                        
                      import os
                      import math
                      import sys
                      import c4d
                        
                      from c4d import plugins, utils, bitmaps, gui
                        
                      PLUGIN_ID = 10252501
                        
                      class SweepObj(plugins.ObjectData) :
                       
                          def GetVirtualObjects(self, op, hierarchyhelp) :
                              # Disabled the following lines because cache flag was set
                              # So the cache build is done before this method is called
                              #dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA)
                              #if dirty is False: return op.GetCache(hierarchyhelp)
                        
                              #Get the child / parent object (to use as the sweep spline)
                              #Use GetClone so we aren't working on the object itself
                              
                              source = op.GetDown()               
                              if (source is None) : return None
                              source = op.GetDown().GetClone()         
                              
                              #Create a Circle Primitive to act as the sweep profile
                              circle = c4d.BaseObject(c4d.Osplinecircle) 
                              #Set the radius
                              circle[c4d.PRIM_CIRCLE_RADIUS] = 10.0   
                              #Create a new SweepNURBS
                              sweep = c4d.BaseObject(c4d.Osweep)
                        
                              #Insert the source sweep spline under the SweepNURBS
                              source.InsertUnder(sweep)
                              #Insert the circle profile spline under the SweepNURBS
                              circle.InsertUnder(sweep)
                        
                              sweep.Message (c4d.MSG_UPDATE)    #update sweep in viewport  
                              c4d.EventAdd()
                        
                              #Return the SweepNURBS
                              return sweep
                        
                      if __name__ == "__main__":
                        
                          pluginstr = "SweepObj TEST v01"
                          dir, file = os.path.split(__file__)
                          icon = bitmaps.BaseBitmap()
                          icon.InitWith(os.path.join(dir, "res", "sweepobj.tif"))
                          okyn = plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="SweepObj",
                                                      g=SweepObj,
                                                      description="SweepObj", icon=icon,
                                                      info=c4d.OBJECT_GENERATOR | c4d.OBJECT_INPUT)
                          if (okyn) : 
                              print pluginstr + " initialized."
                          else: print "Error initializing " + pluginstr
                      
                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        Helper
                        last edited by

                        On 26/04/2013 at 14:55, xxxxxxxx wrote:

                        because you have disabled caching with that 😉 if another node is polling your node the node
                        will always recalculate its output instead of returning its cache when the underlying data
                        has not changed.

                        1 Reply Last reply Reply Quote 0
                        • H Offline
                          Helper
                          last edited by

                          On 26/04/2013 at 15:06, xxxxxxxx wrote:

                          Yes, the manual tells us:
                          The method GetVirtualObjects() is called on each frame and if you don't want to calculate the object on each frame again and again you can still return the cache object with the following code:

                          I tried your option, but without any testing.
                          That did not solve it. Is 0 the correct flag value  to set?
                          How and when is SetDirty used by Cinema 4d?

                          def Message(self, node, type, data) :
                          
                              node.SetDirty(0)
                          
                              return True
                          
                          1 Reply Last reply Reply Quote 0
                          • H Offline
                            Helper
                            last edited by

                            On 26/04/2013 at 15:57, xxxxxxxx wrote:

                            hi,

                            i didn't actually test my posted code and assumed that a node is notified each time 
                            one of its children changes, however that is not the case (at least not always, 
                            messages tend to be confusing ). long story short here is a working version, i have 
                            actually tested this time 😉 it returns a Null when the object has no child and then 
                            alternating a sphere or cube each time the cache is rebuild.

                            the cache is rebuild when either the direct child changes or the direct child is dirty.

                            import c4d, os, sys
                            from c4d import bitmaps, documents, gui, modules,  plugins
                              
                            class fhOdataTestData(plugins.ObjectData) :
                                def __init__(self) :
                                    self.reference = None
                                    self.toggle    = False
                              
                                def GetVirtualObjects(self, node, hierarchyhelp) :
                                    if node.GetDown() != self.reference:
                                        self.reference = node.GetDown()
                                        node.SetDirty(c4d.DIRTY_DATA)
                                    elif node.GetDown() and node.GetDown().IsDirty(c4d.DIRTY_DATA) :
                                        node.SetDirty(c4d.DIRTY_DATA)
                              
                                    if not (node.CheckCache(hierarchyhelp) or node.IsDirty(c4d.DIRTY_DATA)) :
                                        return node.GetCache(hierarchyhelp)
                              
                                    if self.reference:
                                        if self.toggle:
                                            res = c4d.BaseObject(c4d.Ocube)
                                        else:
                                            res = c4d.BaseObject(c4d.Osphere)
                                        self.toggle = not self.toggle
                                        return res
                                    else:
                                        return None
                              
                            if __name__ == "__main__":
                                path, file = os.path.split(__file__)
                                bmp = bitmaps.BaseBitmap()
                                bmp.InitWith(os.path.join(path, "res", "fhOdataTest.tif"))
                                plugins.RegisterObjectPlugin(id          = 1029736, 
                                                             str         = "odatatest",
                                                             g           = fhOdataTestData,
                                                             description = "odatatest", 
                                                             icon        = bmp,
                                                             info        = c4d.OBJECT_GENERATOR)
                            
                            1 Reply Last reply Reply Quote 0
                            • H Offline
                              Helper
                              last edited by

                              On 27/04/2013 at 02:22, xxxxxxxx wrote:

                              Briljant, thank you very much!
                              It works as hoped.

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