24#include "RNA_prototypes.hh"
42class NodePanelViewItem;
43class NodeSocketViewItem;
44class NodeTreeInterfaceView;
51 explicit NodeTreeInterfaceDragController(NodeTreeInterfaceView &view,
53 virtual ~NodeTreeInterfaceDragController() =
default;
57 void *create_drag_data()
const;
67 bool can_drop(
const wmDrag &drag,
const char **r_disabled_hint)
const override;
68 std::string drop_tooltip(
const DragInfo &drag_info)
const override;
72 wmDragNodeTreeInterface *get_drag_node_tree_declaration(
const wmDrag &drag)
const;
75class NodePanelDropTarget :
public TreeViewItemDropTarget {
82 bool can_drop(
const wmDrag &drag,
const char **r_disabled_hint)
const override;
83 std::string drop_tooltip(
const DragInfo &drag_info)
const override;
84 bool on_drop(
bContext *C,
const DragInfo &drag_info)
const override;
87 wmDragNodeTreeInterface *get_drag_node_tree_declaration(
const wmDrag &drag)
const;
90class NodeSocketViewItem :
public BasicTreeViewItem {
99 : BasicTreeViewItem(socket.name, ICON_NONE), nodetree_(nodetree), socket_(socket)
101 set_is_active_fn([interface, &socket]() {
return interface.active_item() == &socket.
item; });
102 set_on_activate_fn([&interface](
bContext & , BasicTreeViewItem &new_active) {
103 NodeSocketViewItem &
self =
static_cast<NodeSocketViewItem &
>(new_active);
104 interface.active_item_set(&
self.socket_.item);
108 void build_row(
uiLayout &row)
override
121 uiItemL(input_socket_layout,
"", ICON_BLANK1);
124 this->add_label(row);
135 uiItemL(output_socket_layout,
"", ICON_BLANK1);
140 bool matches(
const AbstractViewItem &other)
const override
142 const NodeSocketViewItem *other_item =
dynamic_cast<const NodeSocketViewItem *
>(&other);
143 if (other_item ==
nullptr) {
147 return &socket_ == &other_item->socket_;
150 bool supports_renaming()
const override
154 bool rename(
const bContext &C, StringRefNull new_name)
override
164 StringRef get_rename_string()
const override
169 std::unique_ptr<AbstractViewItemDragController> create_drag_controller()
const override;
170 std::unique_ptr<TreeViewItemDropTarget> create_drop_target()
override;
173class NodePanelViewItem :
public BasicTreeViewItem {
182 : BasicTreeViewItem(panel.name, ICON_NONE), nodetree_(nodetree), panel_(panel)
184 set_is_active_fn([interface, &panel]() {
return interface.active_item() == &panel.
item; });
185 set_on_activate_fn([&interface](
bContext & , BasicTreeViewItem &new_active) {
186 NodePanelViewItem &
self =
static_cast<NodePanelViewItem &
>(new_active);
187 interface.active_item_set(&
self.panel_.item);
191 void build_row(
uiLayout &row)
override
193 this->add_label(row);
200 bool matches(
const AbstractViewItem &other)
const override
202 const NodePanelViewItem *other_item =
dynamic_cast<const NodePanelViewItem *
>(&other);
203 if (other_item ==
nullptr) {
207 return &panel_ == &other_item->panel_;
210 bool supports_renaming()
const override
214 bool rename(
const bContext &C, StringRefNull new_name)
override
223 StringRef get_rename_string()
const override
228 std::unique_ptr<AbstractViewItemDragController> create_drag_controller()
const override;
229 std::unique_ptr<TreeViewItemDropTarget> create_drop_target()
override;
232class NodeTreeInterfaceView :
public AbstractTreeView {
239 : nodetree_(nodetree), interface_(interface)
253 void build_tree()
override
256 this->add_items_for_panel_recursive(interface_.
root_panel, *
this);
264 switch (item->item_type) {
268 NodeSocketViewItem &socket_item = parent_item.add_tree_item<NodeSocketViewItem>(
269 nodetree_, interface_, *socket);
270 socket_item.uncollapse_by_default();
276 NodePanelViewItem &panel_item = parent_item.add_tree_item<NodePanelViewItem>(
277 nodetree_, interface_, *panel);
278 panel_item.uncollapse_by_default();
279 add_items_for_panel_recursive(*panel, panel_item);
287std::unique_ptr<AbstractViewItemDragController> NodeSocketViewItem::create_drag_controller()
const
289 return std::make_unique<NodeTreeInterfaceDragController>(
290 static_cast<NodeTreeInterfaceView &
>(this->get_tree_view()), socket_.
item);
293std::unique_ptr<TreeViewItemDropTarget> NodeSocketViewItem::create_drop_target()
295 return std::make_unique<NodeSocketDropTarget>(*
this, socket_);
298std::unique_ptr<AbstractViewItemDragController> NodePanelViewItem::create_drag_controller()
const
300 return std::make_unique<NodeTreeInterfaceDragController>(
301 static_cast<NodeTreeInterfaceView &
>(this->get_tree_view()), panel_.
item);
304std::unique_ptr<TreeViewItemDropTarget> NodePanelViewItem::create_drop_target()
306 return std::make_unique<NodePanelDropTarget>(*
this, panel_);
309NodeTreeInterfaceDragController::NodeTreeInterfaceDragController(NodeTreeInterfaceView &view,
311 : AbstractViewItemDragController(view), item_(item)
320void *NodeTreeInterfaceDragController::create_drag_data()
const
322 wmDragNodeTreeInterface *drag_data = MEM_cnew<wmDragNodeTreeInterface>(__func__);
323 drag_data->item = &item_;
327NodeSocketDropTarget::NodeSocketDropTarget(NodeSocketViewItem &item,
333bool NodeSocketDropTarget::can_drop(
const wmDrag &drag,
const char ** )
const
338 wmDragNodeTreeInterface *drag_data = get_drag_node_tree_declaration(drag);
344 if (panel->contains(socket_.
item)) {
351std::string NodeSocketDropTarget::drop_tooltip(
const DragInfo &drag_info)
const
353 switch (drag_info.drop_location) {
354 case DropLocation::Into:
356 case DropLocation::Before:
357 return TIP_(
"Insert before socket");
358 case DropLocation::After:
359 return TIP_(
"Insert after socket");
364bool NodeSocketDropTarget::on_drop(
bContext *C,
const DragInfo &drag_info)
const
366 wmDragNodeTreeInterface *drag_data = get_drag_node_tree_declaration(drag_info.drag_data);
371 bNodeTree &nodetree = this->get_view<NodeTreeInterfaceView>().nodetree();
379 switch (drag_info.drop_location) {
380 case DropLocation::Before:
381 index = parent->items().as_span().first_index_try(&socket_.
item);
383 case DropLocation::After:
384 index = parent->items().as_span().first_index_try(&socket_.
item) + 1;
391 if (parent ==
nullptr || index < 0) {
395 interface.move_item_to_parent(*drag_item, parent, index);
403wmDragNodeTreeInterface *NodeSocketDropTarget::get_drag_node_tree_declaration(
407 return static_cast<wmDragNodeTreeInterface *
>(drag.
poin);
415bool NodePanelDropTarget::can_drop(
const wmDrag &drag,
const char ** )
const
420 wmDragNodeTreeInterface *drag_data = get_drag_node_tree_declaration(drag);
426 if (panel->contains(panel_.
item)) {
434std::string NodePanelDropTarget::drop_tooltip(
const DragInfo &drag_info)
const
436 switch (drag_info.drop_location) {
437 case DropLocation::Into:
438 return TIP_(
"Insert into panel");
439 case DropLocation::Before:
440 return TIP_(
"Insert before panel");
441 case DropLocation::After:
442 return TIP_(
"Insert after panel");
447bool NodePanelDropTarget::on_drop(
bContext *C,
const DragInfo &drag_info)
const
449 wmDragNodeTreeInterface *drag_data = get_drag_node_tree_declaration(drag_info.drag_data);
454 bNodeTree &nodetree = get_view<NodeTreeInterfaceView>().nodetree();
459 switch (drag_info.drop_location) {
460 case DropLocation::Into: {
466 case DropLocation::Before: {
468 parent = interface.find_item_parent(panel_.
item,
true);
470 index = parent->items().as_span().first_index_try(&panel_.
item);
473 case DropLocation::After: {
475 parent = interface.find_item_parent(panel_.
item,
true);
477 index = parent->items().as_span().first_index_try(&panel_.
item) + 1;
481 if (parent ==
nullptr || index < 0) {
485 interface.move_item_to_parent(*drag_item, parent, index);
493wmDragNodeTreeInterface *NodePanelDropTarget::get_drag_node_tree_declaration(
497 return static_cast<wmDragNodeTreeInterface *
>(drag.
poin);
519 "Node Tree Declaration Tree View",
520 std::make_unique<blender::ui::nodes::NodeTreeInterfaceView>(nodetree, interface));
Main * CTX_data_main(const bContext *C)
#define BLI_assert_unreachable()
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_INPUT
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *ntree)
void ED_undo_push(bContext *C, const char *str)
blender::ui::AbstractGridView * UI_block_add_view(uiBlock &block, blender::StringRef idname, std::unique_ptr< blender::ui::AbstractGridView > grid_view)
void uiTemplateNodeTreeInterface(uiLayout *layout, PointerRNA *ptr)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiTemplateNodeSocket(uiLayout *layout, bContext *C, const float color[4])
void uiLayoutSetEmboss(uiLayout *layout, eUIEmbossType emboss)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
@ WM_DRAG_NODE_TREE_INTERFACE
void set_default_rows(int default_rows)
void set_context_menu_title(const std::string &title)
static void build_tree_view(AbstractTreeView &tree_view, uiLayout &layout, std::optional< StringRef > search_string={}, bool add_box=true)
T & get_item_as(bNodeTreeInterfaceItem &item)
TreeViewItemContainer TreeViewOrItem
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
bNodeTreeInterfaceItem item
bNodeTreeInterfaceItem item
bNodeTreeInterfacePanel root_panel
bNodeTreeInterface tree_interface
bNodeTreeInterfaceItem * item