diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 438aa0ece10..d7f08a3472f 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC ../../render ../../windowmanager ../../../../intern/ghost + ../../../../extern/fmtlib/include ../../bmesh # RNA_prototypes.h ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/interface/interface_template_grease_pencil_layer_tree.cc b/source/blender/editors/interface/interface_template_grease_pencil_layer_tree.cc index 4f40998ec09..e6f07f8e468 100644 --- a/source/blender/editors/interface/interface_template_grease_pencil_layer_tree.cc +++ b/source/blender/editors/interface/interface_template_grease_pencil_layer_tree.cc @@ -18,10 +18,133 @@ #include "RNA_access.h" #include "RNA_prototypes.h" +#include + namespace blender::ui::greasepencil { using namespace blender::bke::greasepencil; +class LayerTreeView : public AbstractTreeView { + public: + explicit LayerTreeView(GreasePencil &grease_pencil) : grease_pencil_(grease_pencil) {} + + void build_tree() override; + + private: + void build_tree_node_recursive(TreeViewOrItem &parent, TreeNode &node); + GreasePencil &grease_pencil_; +}; + +class LayerNodeDropTarget : public TreeViewItemDropTarget { + TreeNode &drop_tree_node_; + + public: + LayerNodeDropTarget(AbstractTreeView &view, TreeNode &drop_tree_node, DropBehavior behavior) + : TreeViewItemDropTarget(view, behavior), drop_tree_node_(drop_tree_node) + { + } + + bool can_drop(const wmDrag &drag, const char ** /*r_disabled_hint*/) const override + { + return drag.type == WM_DRAG_GREASE_PENCIL_LAYER; + } + + std::string drop_tooltip(const DragInfo &drag_info) const override + { + const wmDragGreasePencilLayer *drag_grease_pencil = + static_cast(drag_info.drag_data.poin); + Layer &drag_layer = drag_grease_pencil->layer->wrap(); + + std::string_view drag_name = drag_layer.name(); + std::string_view drop_name = drop_tree_node_.name; + + switch (drag_info.drop_location) { + case DropLocation::Into: + return fmt::format(TIP_("Move layer {} into {}"), drag_name, drop_name); + case DropLocation::Before: + return fmt::format(TIP_("Move layer {} above {}"), drag_name, drop_name); + case DropLocation::After: + return fmt::format(TIP_("Move layer {} below {}"), drag_name, drop_name); + default: + BLI_assert_unreachable(); + break; + } + + return ""; + } + + bool on_drop(struct bContext * /*C*/, const DragInfo &drag_info) const override + { + const wmDragGreasePencilLayer *drag_grease_pencil = + static_cast(drag_info.drag_data.poin); + Layer &drag_layer = drag_grease_pencil->layer->wrap(); + + LayerGroup &drag_parent = drag_layer.parent_group(); + LayerGroup *drop_parent_group = drop_tree_node_.parent_group(); + if (!drop_parent_group) { + /* Root node is not added to the tree view, so there should never be a drop target for this. + */ + BLI_assert_unreachable(); + return false; + } + + switch (drag_info.drop_location) { + case DropLocation::Into: { + BLI_assert_msg(drop_tree_node_.is_group(), + "Inserting should not be possible for layers, only for groups, because " + "only groups use DropBehavior::Reorder_and_Insert"); + + LayerGroup &drop_group = drop_tree_node_.as_group_for_write(); + drag_parent.unlink_node(&drag_layer.as_node()); + drop_group.add_layer(&drag_layer); + return true; + } + case DropLocation::Before: + drag_parent.unlink_node(&drag_layer.as_node()); + /* Draw order is inverted, so inserting before means inserting below. */ + drop_parent_group->add_layer_after(&drag_layer, &drop_tree_node_); + return true; + case DropLocation::After: + drag_parent.unlink_node(&drag_layer.as_node()); + /* Draw order is inverted, so inserting after means inserting above. */ + drop_parent_group->add_layer_before(&drag_layer, &drop_tree_node_); + return true; + } + + return false; + } +}; + +class LayerViewItemDragController : public AbstractViewItemDragController { + GreasePencil &grease_pencil_; + Layer &dragged_layer_; + + public: + LayerViewItemDragController(LayerTreeView &tree_view, GreasePencil &grease_pencil, Layer &layer) + : AbstractViewItemDragController(tree_view), + grease_pencil_(grease_pencil), + dragged_layer_(layer) + { + } + + eWM_DragDataType get_drag_type() const override + { + return WM_DRAG_GREASE_PENCIL_LAYER; + } + + void *create_drag_data() const override + { + wmDragGreasePencilLayer *drag_data = MEM_new(__func__); + drag_data->layer = &dragged_layer_; + return drag_data; + } + + void on_drag_start() override + { + grease_pencil_.set_active_layer(&dragged_layer_); + } +}; + class LayerViewItem : public AbstractTreeViewItem { public: LayerViewItem(GreasePencil &grease_pencil, Layer &layer) @@ -74,6 +197,18 @@ class LayerViewItem : public AbstractTreeViewItem { return layer_.name(); } + std::unique_ptr create_drag_controller() const override + { + return std::make_unique( + static_cast(get_tree_view()), grease_pencil_, layer_); + } + + std::unique_ptr create_drop_target() override + { + return std::make_unique( + get_tree_view(), layer_.as_node(), DropBehavior::Reorder); + } + private: GreasePencil &grease_pencil_; Layer &layer_; @@ -137,6 +272,12 @@ class LayerGroupViewItem : public AbstractTreeViewItem { return group_.name(); } + std::unique_ptr create_drop_target() override + { + return std::make_unique( + get_tree_view(), group_.as_node(), DropBehavior::ReorderAndInsert); + } + private: GreasePencil &grease_pencil_; LayerGroup &group_; @@ -160,17 +301,6 @@ class LayerGroupViewItem : public AbstractTreeViewItem { } }; -class LayerTreeView : public AbstractTreeView { - public: - explicit LayerTreeView(GreasePencil &grease_pencil) : grease_pencil_(grease_pencil) {} - - void build_tree() override; - - private: - void build_tree_node_recursive(TreeViewOrItem &parent, TreeNode &node); - GreasePencil &grease_pencil_; -}; - void LayerTreeView::build_tree_node_recursive(TreeViewOrItem &parent, TreeNode &node) { using namespace blender::bke::greasepencil; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 3843a6ed565..16c04f8f959 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -1088,6 +1088,7 @@ typedef enum eWM_DragDataType { WM_DRAG_COLOR, WM_DRAG_DATASTACK, WM_DRAG_ASSET_CATALOG, + WM_DRAG_GREASE_PENCIL_LAYER, } eWM_DragDataType; typedef enum eWM_DragFlags { @@ -1146,6 +1147,10 @@ typedef struct wmDragPath { int file_type; /* eFileSel_File_Types */ } wmDragPath; +typedef struct wmDragGreasePencilLayer { + struct GreasePencilLayer *layer; +} wmDragGreasePencilLayer; + typedef char *(*WMDropboxTooltipFunc)(struct bContext *, struct wmDrag *, const int xy[2], diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index 5d204973f93..b6c64a5a8ad 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -201,6 +201,7 @@ wmDrag *WM_drag_data_create( WM_drag_add_local_ID(drag, static_cast(poin), nullptr); } break; + case WM_DRAG_GREASE_PENCIL_LAYER: case WM_DRAG_ASSET: case WM_DRAG_ASSET_CATALOG: /* Move ownership of poin to wmDrag. */