Page MenuHome

New Drag & Drop System [WIP]
Needs ReviewPublic

Authored by Jacques Lucke (JacquesLucke) on Dec 12 2018, 7:23 PM.
Tags
None
Tokens
"Love" token, awarded by DaPaulus."Love" token, awarded by oenvoyage."Love" token, awarded by GeorgiaPacific."Love" token, awarded by elbox01."Love" token, awarded by TheRedWaxPolice."Love" token, awarded by billreynish."Love" token, awarded by rbx775."Love" token, awarded by BYOB."Love" token, awarded by Loner."Love" token, awarded by manitwo."Love" token, awarded by ThinkingPolygons.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

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:

  1. Start Dragging. (WM_drag_start_id, WM_drag_start_filepaths, WM_drag_start_value, ...)
  2. 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, ...)
  3. Query Drag Data. (WM_drag_query_single_id, WM_drag_query_single_path_image, WM_drag_query_single_color, ...)
  4. 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.

Major Todos:

  • 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.

Diff Detail

Repository
rB Blender
Branch
drag_drop (branched from blender2.8)
Build Status
Buildable 2622
Build 2622: arc lint + arc unit

Event Timeline

Jacques Lucke (JacquesLucke) retitled this revision from New Drag & Drop System to New Drag & Drop System [WIP].Dec 12 2018, 7:24 PM

I am wondering if this patch can also deal with drag and drop of external meshes like an obj from the system's file browser? Rigth now one has to go through import to do all that but most 3d applications support drag and drop of mesh from outside.

thanks

I am wondering if this patch can also deal with drag and drop of external meshes like an obj from the system's file browser? Rigth now one has to go through import to do all that but most 3d applications support drag and drop of mesh from outside.

thanks

Yes of course, making things like that possible is one of the main goals here (should become very easy once we have a Python API for drag & drop).

Other things I want to see in the future:

  • Dropping multiple images or a .zip into the shader editor to create a pbr material.
  • Drop a .py or .zip file into Blender to install an addon.
  • Drag&Drop stuff directly from a webbrowser (however that needs some more low level changes that I don't understand yet)

All this sounds really really good, thanks for working on it.

This seems like a good idea.

I wonder if it would make sense to put more of the drop target stuff into operators. It interesting to decouple the drag & drop from operators, but it's also kind of a pain to pass things through operator properties. In the outliner it used to pass for example the ID name, but that is ambiguous in case of library linking and inconvenient as well.

Maybe an idea is to add a drop_target_find method to operators, where it does something similar to your drop_target_find but for just a single operator. Then if there is a match and the users drops, it calls invoke with the data found in event. Each editor could have a list of such operators.

I think there are two types of operators here:

  1. Generic operators that are (and should be) independent of drag data, meaning that they don't care about where its properties come from. Those need some kind of set_properties function. I don't find that too inconvenient. It's just a way to keep the operator independent of the drag&drop system.
  2. Specialized operators that are only invoked on drop events. Those do not need the set_properties function because they access the dragged data directly (this would be used for outliner drop and similar things).

Having something like a poll_drop function in an operator that returns true when the operator can handle the current drag data could work but it does not solve one other problem (see below). Also just having such a list of operators per editor/space does not work in general because some operators are space-independent (e.g. the drop color operator). Those would have to be in all lists.

Another problem I tried to solve is that there were many hidden dependencies between the poll functions of different drop boxes. Also there was a lot of duplicated code. Two examples:

  • When dropping an image into the viewport the code had to decide whether to create an image empty or a camera background. Previously the decision process for that was very hidden in two poll functions.
  • It was even worse in the outliner where the code had to decide whether to drop the parent, clear the parent, move collections, ... This decision process was hidden in multiple poll functions, again. It was hard to understand, difficult to get right and annoying to maintain.

Those thoughts led me to the conclusion that it would be better to make the drop target selection of multiple operators in a single function. Nevertheless it could make sense build other functionality on top of this base framework; should be fairly easy as it is quite flexible in that regard.