Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > PYTHON Development
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Hide child of Object plugin

 Post Reply Post Reply
Author
Message
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Topic: Hide child of Object plugin
    Posted: 2017 Dec 03 at 5:37pm
Hello pluginface!
I'm trying to hide the child object of python generator or object plugin but I don't want to affect visibility flags.
  1. #Get Child
  2. child = op.GetDown()

  3. #Hide in viewport except to viewport select. 
  4. child.ChangeNBit(c4d.NBIT_HIDEEXCEPTVIEWSELECT, c4d.NBITCONTROL_SET)
I tried this code but it's still visible in the render and also, it makes it constantly hidden from the viewport even if I will take it out of the object plugin. I know about NBITCONTROL_CLEAR but I don't know how to execute this code when taking child object out of the object plugin. 
I want to make it work, as a normal generator object(hide object when it is a child of object plugin and unhide again after taking it out)
is this somehow possible in python?


Edited by merkvilson - 2017 Dec 03 at 5:39pm
Follow: www.twitter.com/Merkvilson
Back to Top
gr4ph0s View Drop Down
Member
Member


Joined: 2015 Jul 07
Location: France
Online Status: Offline
Posts: 429
Post Options Post Options   Quote gr4ph0s Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 04 at 1:54am
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


Edited by gr4ph0s - 2017 Dec 04 at 2:48am
Technical lover.
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1599
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 04 at 2:55am
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:

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

Cheers,
Andreas
SDK Support Engineer
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 04 at 7:39am
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! 

Follow: www.twitter.com/Merkvilson
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 04 at 8:19am
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?


Follow: www.twitter.com/Merkvilson
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1599
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 05 at 9:33am
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?

Cheers,
Andreas
SDK Support Engineer
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 05 at 9:47am
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%20Plugin%200.2.rar?dl=0
Follow: www.twitter.com/Merkvilson
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1599
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 06 at 4:42am
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.



Edited by Andreas Block - 2017 Dec 06 at 4:42am
Cheers,
Andreas
SDK Support Engineer
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 06 at 5:05am
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'
Follow: www.twitter.com/Merkvilson
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1599
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 06 at 10:33am
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.

Cheers,
Andreas
SDK Support Engineer
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 11 at 7:05pm
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?

Follow: www.twitter.com/Merkvilson
Back to Top
merkvilson View Drop Down
Member
Member
Avatar

Joined: 2017 Feb 27
Online Status: Online
Posts: 20
Post Options Post Options   Quote merkvilson Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Dec 12 at 11:15am
This goes off topic so I made a new thread about my last question. :)
Follow: www.twitter.com/Merkvilson
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.125 seconds.