Drag and Drop from GeUserArea in Python
-
Hi,
I know, this is a topic that got discussed several times in the past. Nevertheless I can not get it to work properly.
The goal: Being able to drag a yet to be created object or material from my GeUserArea into C4D (desired targets: view port, Material Manager, Object Manager,...).
I said "yet to be created". By this I mean, it is an asset from some library, which is not yet part of the document.
I have two options:- Create and insert the asset before the drag and then remove it again, if the drag fails (either being escaped or dropped onto some forbidden place).
- Or I do insert the asset into the document on successful drop.
The beginning looked promising, HandleMouseDrag() seems to be the function for this scenario and at first it seemed to work as expected.
But how on earth do I find out about the outcome of the drop?
I do receive BFM_DRAGRECEIVE, but I do never get BFM_DRAG_FINISHED or BFM_DRAG_ESC to be true. Only BFM_DRAG_LOST seems to hold information. It is always jumps from false to true, when the user ends the drag in whatever way (escaped, dropped successfully, dropped on forbidden area, it doesn't matter).
Yes, I do return the return value of SetDragDestination() from my Message() function, while in drag, as I found in this forum, that it's needed to notify C4D about my interest in the drag (which I started in the first place... Not being interested in the outcome of something I started feels a bit strange to me... a bit like firing a rocket and not being interested, if it actually started, exploded on the pad or actually reached its destination. Anyway...).And then there's an additional issue with dragged materials:
The result is different, if the user drops it onto an object in viewport or Object Manager or onto the Material Manager. In the first case it works as expected (as long as I insert the material into the document), but in the latter case I end up with two material being created in the MM. So, when dropping onto an object C4D seems to assume, the material is already part of the document and only assigns it (but I am responsible for making it available in the document), while when dropping onto the MM, then C4D seems to automatically create a copy (so I should not insert it into the document myself).
But how am I to decide, what to do and what to expect?
Even if I had a way to find out about the success of the drop operation, I would still be lacking the information about the drop target.Any help would be much appreciated.
Cheers,
Andreas -
Hi @a_block what you are trying is unfortunately not possible. This is not how the Drag and drop system work in Cinema 4D.
There is 2 part the drag part, the one starting the drag operation, is done by callingHandleMouseDrag
. Your code is paused until the drag operation ended. You have no way to know if the operation changed anything in the scene (you could for sure listen for EVMSG_CHANGE) and the return value of HandleMouseDrag only indicate if a drag/Drop operation happened.Then there is the drop part, the one receiving the object. Here it's done through message handled by the targeted GUI. Each managers being specific (e.g. a drop operation on the view port is not the same as a drop operation on the Object Manager) so it's up to this manager to decide what to do for the current received drag information. From a pure implementation point of view, it also does make sense since it would make no sense if each drag operation have to support all possible managers. Side note the system work in a way that the drop part never communicate to the drag part.
Finally it is not possible to drag objects directly to the viewport, see DragDrop Model from UserArea into Viewport or Object Manager if you want to do so you need to pass a Maxon API Asset. The viewport will then load it as when you drag and drop and asset from the Asset Browser to the Viewport. This approach (of using a Maxon API asset) is most likely what you will want to do in order to have the bheavior you expect. In Handbooks - Asset API - Asset Types you can find various examples on how to create an asset for an Object, a Material, a Scene, a texture, or even arbitrary files. Then to drag it you need to pass as value type,
DRAGTYPE_ASSET
and as value an instance of DragAndDropDataAssetArray. Sadly this is not possible in Python for the moment (it will be in the upcoming version) so you will need to do that in C++ for the moment.Cheers,
Maxime. -
Hi Maxime,
that's a bummer.Just a few additions:
is done by calling HandleMouseDrag. Your code is paused until the drag operation ended
Yes, no objection. But it should be said, during this "pause" one does still receive messages, among them BFM_DRAGRECEIVE_START and BFM_DRAGRECEIVE. Just not BFM_DRAGEND. Which makes me think, if only the receiver would not "consume" this message, it could already work...
From a pure implementation point of view, it also does make sense since it would make no sense if each drag operation have to support all possible managers
I wouldn't want it differently. But I still think, the initiator of an action deserves result information. after all these years, I'm still wondering, what's this obsession with not delivering feedback to a caller. Yes, I'm looking at you CallCommand()...
Finally it is not possible to drag objects directly to the viewport
I didn't even consider, drag and drop could work differently for materials and objects, or objects not working at all. So, thanks for the info and avoiding even more headache on my end.
I guess, we are back to the drawing board then.
Anyway, greetings to the team.
Cheers,
Andreas