CommandData & GUI ObjectData



  • On 05/06/2017 at 21:32, xxxxxxxx wrote:

    Hello everybody!
    Advise how to solve the problem.
    There are two plug-ins (CommandData) and one plug-in (ObjectData). How to call CommandData plugins from the GUI ObjectData plug-in . When I put the chekbox, I should be called CommandData_1, and when I remove the flag from the checkbox it should work CommandData_2. Separately, each plug-in works fine, but I would like the user to be easier and faster. Thank you in advance.



  • On 05/06/2017 at 21:41, xxxxxxxx wrote:

    Here's what I tried

    class Create(c4d.plugins.CommandData) :

    def Execute(self, doc) :

    doc = c4d.documents.GetActiveDocument()
            op = doc.GetActiveObject()

    selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
     
            if len(selection) <= 0:
                gui.MessageDialog('No master to insert object!')
            else:
                create = Generator(op.GetName())
                create .Create()
                print "Create"

    c4d.EventAdd()

    return True

    class Kill(c4d.plugins.CommandData) :

    def Execute(self, doc) :

    doc = c4d.documents.GetActiveDocument()
            op = doc.GetActiveObject()

    selection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
     
            if len(selection) <= 0:
                gui.MessageDialog('No object to delete!')
            else:
                kill = Generator(op.GetName())
                kill.Kill()
                print "Kill"

    c4d.EventAdd()

    return True

    class ObjectData(c4d.plugins.ObjectData) :

    def __init__(self) :

    self.SetOptimizeCache(True)

    def Draw(self, op, drawpass, bd, bh) :

    doc = c4d.documents.GetActiveDocument()

    if drawpass==c4d.DRAWPASS_HIGHLIGHTS:
                return c4d.DRAWRESULT_SKIP

    ###############################################

    if op[c4d.RM_CREATE] == 1:
                Create()Execute(doc)
            elif op[c4d.RM_CREATE] == 0:
                Kill().Execute(doc)

    ###############################################

    return c4d.DRAWRESULT_OK

    def GetVirtualObjects(self, op, hierarchyhelp) :

    doc = c4d.documents.GetActiveDocument()

    dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTYFLAGS_CHILDREN) or op.IsDirty(c4d.DIRTYFLAGS_DATA)
            if dirty is False:
                 return op.GetCache()

    return c4d.BaseObject(c4d.Onull)



  • On 06/06/2017 at 08:01, xxxxxxxx wrote:

    Hi,

    in general (but please read to the end) a CommandData plugin can be called via CallCommand(). But that's not the right thing to do in your scenario, assuming you want to do this from GetVirtualObjects() or Draw() of an ObjectData plugin. Both functions are called in threaded contexts and CallCommand() is basically like user interaction, only allowed from main thread. See important threading information. Probably no need to say, that it is also forbidden to open any dialogs from within the mentioned functions of an ObjectData plugin. Neither you are not allowed to change the scene (e.g. delete objects) from within these functions, it wouldn't help here to facilitate commands for this, the problem stays the same.

    While talking about ObjectData, it is wrong to call GetActiveDocument() in ObjectData (actually all NodeData derived) plugins. Think for example of a rendering situation, where the document gets cloned in order to render in background. The document being rendered is not the active one, so you will refer to wrong instances in this case. Instead use GeListNode.GetDocument().

    Unfortunately you fail to say anything about the greater context and what you actually want to achieve.
    But from what you describe the way to go here is probably rather the other way round.
    The ObjectData generator creates an object (or even a hierarchy of objects) as a result of GetVirtualObjects(). The behavior can of course depend on parameters, so you can also decide to create nothing (a Null object) based on for example a checkbox in your ObjectData parameter description.

    And if you then still need commands to influence your ObjectData, then you can set parameters in reaction to user interaction with your dialog in GeDialog.Command(). And if needed you can react to these parameter changes in your ObjectData's SetDParameter(). There you could also use CallCommand() as long as you check for the DESCFLAGS_SET_USERINTERACTION flag and only do so, if the flag is set.

    There are a bunch of manuals on these topics in our C++ documentation, which I recommend to take a look at even for Python developers:
    GUI and User Interaction Manual
    Threading Manual



  • On 06/06/2017 at 18:35, xxxxxxxx wrote:

    Thank you. Interesting thing. As soon as I write a post, in the morning comes understanding how to solve the problem. You, as a test indicator)))))) By the way, it's very discouraging for such a moment, I did not immediately understand what the problem is, but you have written in the python documentation, Draw (self, op, drawpass, bd, bh) and in the example Draw (self, data, drawpass, bd, bh). It's a typo? Or is everything right? Can I use op or data? It's a bit discouraging.



  • On 07/06/2017 at 08:19, xxxxxxxx wrote:

    Hi,

    thanks for pointing out the inconsistency in the documentation. In the end it doesn't matter, how the parameters are named, so the code snippet is not wrong. But I agree it can be confusing and we'll fix it.


Log in to reply