Some time ago I worked on some drag&drop things for files and in the outliner. It became apparent that the current system has a couple of limitations that should be resolved sooner or later.
Some of the problems of the old system are:
- Only one file can be dropped into Blender at once.
- Not easy to extend in a clean way.
- All dropboxes are registered when space types are registered and operator idnames are also resolved at that time. That made it impossible to call Python operators on drop events.
- Consequently it was not possible to extend the drag and drop system with Python.
I started experimenting a bit with different approaches and I'm slowly finding a structure that I like.
Most parts of Blender should use abstractions provided by wm_dragdrop.c. There are four main groups of functions that can be used to implement new drag and drop behavior:
- Start Dragging. (WM_drag_start_id, WM_drag_start_filepaths, WM_drag_start_value, ...)
- Set Display Options that are shown next to the mouse cursor while dragging. (WM_drag_display_set_image, WM_drag_display_set_icon, WM_drag_display_set_color, ...)
- Query Drag Data. (WM_drag_query_single_id, WM_drag_query_single_path_image, WM_drag_query_single_color, ...)
- Create Drop Targets. (WM_drop_target_propose__template_1, ...)
The query functions offer great decoupling of the drag starter and the drop target. E.g. there could be a WM_drag_start_collection and a WM_drag_query_objects_all function. The drop target does not need to know about the structure of the data when it was dragged. Instead it will get the data exactly in the structure that fits the use case best. All conversions happen automatically.
When data is dragged, different parts of Blender are requested to "propose" drop targets for the currently dragged data. A drop target includes an operator name, a tooltip, a function to set the operators properties and a couple more. Every drop target also specifies its size (e.g. DROP_TARGET_SIZE_WINDOW, DROP_TARGET_SIZE_REGION, DROP_TARGET_SIZE_BUT, ...). Of all the proposed drop targets, the one with the smallest size will be selected.
One part that does not have a clear design yet is drop target visualization. That means how can a drop target draw something to show the user what will happen. In the old implementation this was simply done in the poll function of dropboxes, however that system does not work in general (because the dropbox might not be selected in the end). A drop target could provide enter, update and exit methods that deal with visualization.
Limitations compared to the old system:
- I removed "support" for multiple drags at the same time (e.g. when using multitouch). I'm not against it, it's just not worth supporting it right now. It can still be added later on if necessary.
- Drop target visualization.
- Bring back outliner drag and drop (all the other parts are pretty much done).
- Implement Python drag and drop API.
Note: This new system is mostly concerned with drag&drop of data (objects, files, ...), not UI elements such as modifiers, panels and the workspace tabs. You could argue that they are also just some data and you would be right, however that was a bit out of scope for me atm. If we come up with a good drop target visualization, the same drag and drop system could be used for those as well.
Obviously this patch is not ready yet, I just wanted to show what I got so far. I hope that the general idea here is considered useful, so that I can spend more time on it in the future.