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

    Hide child of Object plugin

    Scheduled Pinned Locked Moved PYTHON Development
    12 Posts 0 Posters 1.8k 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 04/12/2017 at 01:54, xxxxxxxx wrote:

      Basicly you return the same object, so logically "both" object are hidden.
      What you should do is hide the children then doing your modfication under a clone of this object and return this clone.

          def GetVirtualObjects(self, op, hh) :
        
              dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTY_DATA)
              if dirty is False: return op.GetCache(hh)
        
              obj = op.GetDown()
              if not obj: return
        
              clonedObj = obj.GetClone(c4d.COPYFLAGS_NO_ANIMATION)
        
              # Hide obj
              op.NewDependenceList()
              op.AddDependence(hh, obj); 
              op.TouchDependenceList();
              
              #Do some stuff on your clonedObj for example an extrude
        
              #select faces
              bs = clonedObj.GetPolygonS()
              bs.Select(0)
        
              #Extrude
              settings = c4d.BaseContainer()                 # Settings
              settings[c4d.MDATA_EXTRUDE_OFFSET] = 50.0      # Length of the extrusion
        
              res = c4d.utils.SendModelingCommand(command = c4d.ID_MODELING_EXTRUDE_TOOL,
                                              list = [clonedObj],
                                              mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                              bc = settings,
                                              doc = clonedObj.GetDocument())
        
              return clonedObj
      

      As you may see you should use DependanceList to handle the hide. Actually TouchDependenceList is the command that hide obj. For more informations please read C++ manual of BaseObject Generator

      But a more cleaner way or at least more user-friendly way is to use GetAndCheckHierarchyclone which will internally do a dependanceList, touch objects and return you a clone of this object or a null with all the child inside it

      So with all the check it will give us something like

          def GetVirtualObjects(self, op, hh) :
              first = op.GetDown()
              if not first: return
        
              dic = op.GetAndCheckHierarchyClone(hh, first, c4d.HIERARCHYCLONEFLAGS_ASPOLY, False)
        
              if not dic["dirty"] and not op.IsDirty(c4d.DIRTY_DATA) and op.GetCache() :
                  return op.GetCache().GetClone() #Do not know why op.GetCache() fail sometime but returning a cloned works like a charm !
        
              #If we are here that mean something has changed so we need to rebuild everythings.
              obj = dic["clone"]
              
              #Do some stuff on your Obj for example an extrude, Keep in mind 
              #select faces
              bs = obj.GetPolygonS()
              bs.Select(0)
        
              #Extrude
              settings = c4d.BaseContainer()                 # Settings
              settings[c4d.MDATA_EXTRUDE_OFFSET] = 50.0      # Length of the extrusion
        
              res = c4d.utils.SendModelingCommand(command = c4d.ID_MODELING_EXTRUDE_TOOL,
                                              list = [obj],
                                              mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                              bc = settings,
                                              doc = obj.GetDocument())
        
              return obj
      

      BTW make sure to register your ObjectData plugin with OBJECT_INPUT set

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

        On 04/12/2017 at 02:55, xxxxxxxx wrote:

        Hi,

        unfortunately I saw gr4ph0s post too late and as I had written this already, I thought I'd post it nevertheless...

        First, please note, the following is not possible in the same way with the Python Generator object, as the Python generator object is not registered with the OBJECT_INPUT flag.

        You don't need to hide objects used as input for your ObjectData generator, explicitly. Instead register your ObjectData Generator plugin with the additional OBJECT_INPUT flag.
         
        And then, when retrieving the caches from the input objects (e.g. in GetVirtualObjects()), these need to be marked as "touched", which is done by so called dependency lists (BaseObject functions NewDependenceList(), AddDependence(), CompareDependenceList(), TouchDependenceList()). Luckily you usually don't have to worry about these, because there's a convenience function, which basically does everything (test for changes (dirty state), return clones of input caches and mark input objects as touched) for you: GetAndCheckHierarchyClone(). Check out gr4ph0s last code snippet above for an example.

        This topic is also discussed in these threads:
        CSTO on a Cloner
        NBIT_HIDEEXCEPTVIEWSELECT

        Already linked to by gr4ph0s, the BaseObject Manual in our C++ docs may also be an interesting read.

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

          On 04/12/2017 at 07:39, xxxxxxxx wrote:

          Thanks guys! I tested this code in my test plugin and now I included it in the main plugin. As you can see, it already works like a charm since I'm not forced to manually hide its child object by affecting its visibility flags. And cache is optimized pretty well.
          Thanks again!

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

            On 04/12/2017 at 08:19, xxxxxxxx wrote:

            Another question regarding this part of the code:
                    #select faces
                    bs = clonedObj.GetPolygonS()
                    bs.Select(0)

            when this code is included in the object plugin, it works when I'm in object/model mode but when I attempt to select the polygon mode it hides my object plugin if it's also selected. is this a bug?

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

              On 05/12/2017 at 09:33, xxxxxxxx wrote:

              Can you please post a bit more code? Or tell us, in which of the above examples you are working?
              I'd recommend to stick with gr4ph0s' second example as it's "more complete". The first example seems to assume the input object is already a PolygonObject, which it is clearly not in your video.
              Do you get any error messages on the Console?

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

                On 05/12/2017 at 09:47, xxxxxxxx wrote:

                No, I'm not getting any errors in the console. And I'm making object editable from the plugin but this problem occurs even if I manually making it editable.

                1. """
                2. Test Plugin 0.1
                3. Coptright: Merk Vilson (www.patreon.com/merkvilson)
                4. Name-US: Test Plugin
                5. Description-US: Creates Test Plugins
                6. """
                7. import c4d
                8. from c4d import plugins
                9. import os
                10. TESTPLUGIN_ID = 1000001 #Temporary ID
                11. TESTPLUGIN_VALUE = 10000 #Real Slider
                12. class Testplugin(c4d.plugins.ObjectData) :
                13. def Init(self, node) :
                14. self.InitAttr(node, float, [TESTPLUGIN_VALUE])
                15. node[TESTPLUGIN_VALUE] = 10.0
                16. return True
                17. def GetVirtualObjects(self, op, hh) :
                18. #Get Child
                19. first = op.GetDown()
                20. if not first: return
                21. dic = op.GetAndCheckHierarchyClone(hh, first, c4d.HIERARCHYCLONEFLAGS_ASPOLY, False)
                22. if not dic["dirty"] and not op.IsDirty(c4d.DIRTY_DATA) and op.GetCache() :
                23. return op.GetCache().GetClone()
                24. obj = dic["clone"]
                25. #Make Editable
                26. res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                27. list = [obj],
                28. mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                29. bc = c4d.BaseContainer(),
                30. doc = obj.GetDocument())
                31. #Select faces
                32. bs = obj.GetPolygonS()
                33. bs.Select(0)
                34. #Extrude
                35. settings = c4d.BaseContainer()
                36. settings[c4d.MDATA_EXTRUDE_OFFSET] = op[10000]
                37. res = c4d.utils.SendModelingCommand(command = c4d.ID_MODELING_EXTRUDE_TOOL,
                38. list = [obj],
                39. mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                40. bc = settings,
                41. doc = obj.GetDocument())
                42. return obj
                43. if __name__ == "__main__":
                44. bmp = c4d.bitmaps.BaseBitmap()
                45. dir, file = os.path.split(__file__)
                46. fn = os.path.join(dir, "res", "icon.tif")
                47. bmp.InitWith(fn)
                48. result = plugins.RegisterObjectPlugin(id = TESTPLUGIN_ID,
                49. str = "Test Plugin",
                50. g = Testplugin,
                51. description = "Otestplugin",
                52. info = c4d.OBJECT_GENERATOR | c4d.OBJECT_POLYGONOBJECT | c4d.OBJECT_INPUT,
                53. icon = bmp)

                Download plugin: https://www.dropbox.com/s/nb80fnnxe3s77n5/Test Plugin 0.2.rar?dl=0

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

                  On 06/12/2017 at 04:42, xxxxxxxx wrote:

                  Hi,

                  the issue is with the registration of your ObjectData plugin. You set the OBJECT_POLYGONOBJECT flag. This flag should not be set, your ObjectData is a generator, not a simple polygon object.

                  Our documentation is a bit weak here, but these flags OBJECT_POLYGONOBJECT and OBJECT_POINTOBJECT just need to be used in rare cases. For example see the objectdata_latticeplanemodifier, while being a modifier, the cage is a point object.

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

                    On 06/12/2017 at 05:05, xxxxxxxx wrote:

                    Thank you! The problem is solved 🙂
                    Seems like C++ has better examples than python.
                    Are there any good courses for C++/C4D? Something like 'Python Scripting in Cinema 4D from FXPHD'

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

                      On 06/12/2017 at 10:33, xxxxxxxx wrote:

                      I'm not aware of anything like the FXPHD Python tutorial for C++.
                      We have a bunch of links here. And well, of course these forums. Of course we can't teach C++ programming itself here, but we have a very knowledgeable and helpful community. In the end our measly SDK Support Team might also be able to help out once in a while.

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

                        On 11/12/2017 at 19:05, xxxxxxxx wrote:

                        Hello again 🙂
                        I'm using this code by gr4ph0s in my object plugin:

                        def GetVirtualObjects(self, op, hh) :
                                first = op.GetDown()
                                if not first: return

                        dic = op.GetAndCheckHierarchyClone(hh, first, c4d.HIERARCHYCLONEFLAGS_ASPOLY, False)

                        if not dic["dirty"] and not op.IsDirty(c4d.DIRTY_DATA) and op.GetCache() :
                                    return op.GetCache().GetClone() #Do not know why op.GetCache() fail sometime but returning a cloned works like a charm !

                        #If we are here that mean something has changed so we need to rebuild everythings.
                                obj = dic["clone"]
                                
                                #Do some stuff on your Obj for example an extrude, Keep in mind 
                                #select faces
                                bs = obj.GetPolygonS()
                                bs.Select(0)

                        #Extrude
                                settings = c4d.BaseContainer()                 # Settings
                                settings[c4d.MDATA_EXTRUDE_OFFSET] = 50.0      # Length of the extrusion

                        res = c4d.utils.SendModelingCommand(command = c4d.ID_MODELING_EXTRUDE_TOOL,
                                                                list = [obj],
                                                                mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION,
                                                                bc = settings,
                                                                doc = obj.GetDocument())

                        return obj

                        I read in docs that GetAndCheckHierarchyClone will generate new cache if something is changed but it constantly generates new cache even if nothing is changed in object plugin or in its child object.

                        Previously I was using this code:

                        child = op.GetDown() if not child: return dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTY_DATA) or child.IsDirty(c4d.DIRTYFLAGS_DATA) if dirty is False: 	return op.GetCache(hh)  
                        

                        I tried to apply this code in conjunction with gr4ph0s'  version but it hides plugin's child object only if I'm changing something in a hierarchy and if nothing is changed, the child object is visible.

                        is it possible to optimize the code so it could generate cache only if something in changed?

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

                          On 12/12/2017 at 11:15, xxxxxxxx wrote:

                          This goes off topic so I made a new thread about my last question. 🙂
                          https://developers.maxon.net/forum/topic/10513/13964_optimize-getandcheckhierarchyclone

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