SOLVED Drag and Drop "Command" from Treeview

Hey everyone,

I'm currently developing a treeview-plugin for all my scripts/presets etc.. I was wondering if it is possible to drag and drop items of said treeview directly to my layout.

I'm currently thinking along those lines:

In my declared ListItem (obj) I have a property of Instance which can hold the reference to the CommandPlugin for each script.

    @property
    def Instance(self):
        # of course this just a placeholder (but a valid one...)
        return c4d.plugins.FindPlugin(600000174)

In the GenerateDragArray I will create an Array with my said Instance/Reference, also I've tried setting different flags for GetDragType to c4d.DRAGTYPE_COMMAND etc....

    def GenerateDragArray(self, root, userdata, obj):
        if obj.IsSelected:
            return [obj.Instance]
        return None

    def GetDragType(self, root, userdata, obj):
        return c4d.DRAGTYPE_COMMAND

    def SetDragObject(self, root, userdata, obj):
        return obj.Instance

Drag and Drop "Command" from Treeview

...but, sadly it's NOT working as I would expect... 🙂

Is this possible with python in general, or a limitation? What am I missing?

Thanks,
Lasse

Hi @lasselauch,

thank you for reaching out to us. I'll answer/point out some stuff in bullet points:

  1. The error object has no attribute im_function indicates that you are returning an incorrect return value type for an overridden function/method. This rather cryptic message is a bug which will be resolved in the next update (see here and here for details).
  2. The method which you did implement incorrectly is TreeViewFunctions.SetDragObject (link) which has no return type (i.e. the return type None).
  3. You also misinterpreted the purpose of the method. It is there so that you can distinguish between internal and external drag operations by storing a reference to the object of an internal drag operation.
  4. There is also this nice posting made by @m_adam untangling the purposes of the TreeViewFunctions methods.

About the core of your question: Your major misconception here is that you can just "replace" the drag object. Which is not what TreeViewFunctions is intended for. It is just a view model / interface layer between the TreeViewCustomGui logic and the data (layer) you want to be represented in that GUI.

Cinema solves this internally with a special core message (COREMSG_COMMANDDRAGSIMULATION), but this unfortunately does not translate to Python, since it requires you to access the internal representation of a GeUserArea, which is not possible in Python.

So your best bet would be to actually make the data you pass to TreeViewCustomGui.SetRoot() to be the actual PluginData nodes you want to drag. So that you are actually dragging a plugin node and not some stand in. There is however no guarantee that this will work, I would have to try that myself.

Cheers,
Ferdinand

@lasselauch said in Drag and Drop "Command" from Treeview:

GetDragType

I highly doubt that this is possible with Python. The docs state not supported.
You should give C++ a try. 😉

@mp5gosu Damn. That's really not the answer I wanted to hear, Robert! 😸

Hi @lasselauch,

thank you for reaching out to us. I'll answer/point out some stuff in bullet points:

  1. The error object has no attribute im_function indicates that you are returning an incorrect return value type for an overridden function/method. This rather cryptic message is a bug which will be resolved in the next update (see here and here for details).
  2. The method which you did implement incorrectly is TreeViewFunctions.SetDragObject (link) which has no return type (i.e. the return type None).
  3. You also misinterpreted the purpose of the method. It is there so that you can distinguish between internal and external drag operations by storing a reference to the object of an internal drag operation.
  4. There is also this nice posting made by @m_adam untangling the purposes of the TreeViewFunctions methods.

About the core of your question: Your major misconception here is that you can just "replace" the drag object. Which is not what TreeViewFunctions is intended for. It is just a view model / interface layer between the TreeViewCustomGui logic and the data (layer) you want to be represented in that GUI.

Cinema solves this internally with a special core message (COREMSG_COMMANDDRAGSIMULATION), but this unfortunately does not translate to Python, since it requires you to access the internal representation of a GeUserArea, which is not possible in Python.

So your best bet would be to actually make the data you pass to TreeViewCustomGui.SetRoot() to be the actual PluginData nodes you want to drag. So that you are actually dragging a plugin node and not some stand in. There is however no guarantee that this will work, I would have to try that myself.

Cheers,
Ferdinand

This post is deleted!

Hi,

I understand that this thread has not yet come to a final conclusion, but without further feedback, we will consider this thread as solved by Monday and flag it accordingly.

Cheers,
Ferdinand