23#include "RNA_prototypes.hh"
37using node_interface::bNodeTreeInterfaceItemReference;
39class NodePanelViewItem;
40class NodeSocketViewItem;
41class NodeTreeInterfaceView;
43class NodeTreeInterfaceDragController :
public AbstractViewItemDragController {
49 explicit NodeTreeInterfaceDragController(NodeTreeInterfaceView &
view,
52 ~NodeTreeInterfaceDragController()
override =
default;
56 void *create_drag_data()
const override;
59class NodeSocketDropTarget :
public TreeViewItemDropTarget {
66 bool can_drop(
const wmDrag &drag,
const char **r_disabled_hint)
const override;
67 std::string drop_tooltip(
const DragInfo &drag_info)
const override;
68 bool on_drop(bContext * ,
const DragInfo &drag_info)
const override;
71class NodePanelDropTarget :
public TreeViewItemDropTarget {
78 bool can_drop(
const wmDrag &drag,
const char **r_disabled_hint)
const override;
79 std::string drop_tooltip(
const DragInfo &drag_info)
const override;
80 bool on_drop(bContext *
C,
const DragInfo &drag_info)
const override;
83class NodeSocketViewItem :
public BasicTreeViewItem {
92 : BasicTreeViewItem(socket.name, ICON_NONE), nodetree_(nodetree), socket_(socket)
94 set_is_active_fn([interface, &socket]() {
return interface.active_item() == &socket.
item; });
95 set_on_activate_fn([&interface](bContext & , BasicTreeViewItem &new_active) {
96 NodeSocketViewItem &
self =
static_cast<NodeSocketViewItem &
>(new_active);
101 void build_row(uiLayout &row)
override
109 uiLayout *input_socket_layout = &row.
row(
true);
118 input_socket_layout->
label(
"", ICON_BLANK1);
121 this->add_label(row);
123 uiLayout *output_socket_layout = &row.
row(
true);
132 output_socket_layout->
label(
"", ICON_BLANK1);
137 bool matches(
const AbstractViewItem &other)
const override
139 const NodeSocketViewItem *other_item =
dynamic_cast<const NodeSocketViewItem *
>(&other);
140 if (other_item ==
nullptr) {
144 return &socket_ == &other_item->socket_;
147 bool supports_renaming()
const override
151 bool rename(
const bContext &
C, StringRefNull new_name)
override
156 nodetree_.tree_interface.tag_item_property_changed();
161 StringRef get_rename_string()
const override
166 std::unique_ptr<AbstractViewItemDragController> create_drag_controller()
const override;
167 std::unique_ptr<TreeViewItemDropTarget> create_drop_target()
override;
170class NodePanelViewItem :
public BasicTreeViewItem {
180 : BasicTreeViewItem(panel.name, ICON_NONE), nodetree_(nodetree), panel_(panel)
182 set_is_active_fn([interface, &panel]() {
return interface.active_item() == &panel.
item; });
183 set_on_activate_fn([&interface](bContext & , BasicTreeViewItem &new_active) {
184 NodePanelViewItem &
self =
static_cast<NodePanelViewItem &
>(new_active);
187 toggle_ = panel.header_toggle_socket();
188 is_always_collapsible_ =
true;
191 void build_row(uiLayout &row)
override
197 if (toggle_ !=
nullptr) {
198 uiLayout *toggle_layout = &row.
row(
true);
205 this->add_label(row);
207 uiLayout *sub = &row.
row(
true);
212 bool matches(
const AbstractViewItem &other)
const override
214 const NodePanelViewItem *other_item =
dynamic_cast<const NodePanelViewItem *
>(&other);
215 if (other_item ==
nullptr) {
219 return &panel_ == &other_item->panel_;
222 bool supports_renaming()
const override
226 bool rename(
const bContext &
C, StringRefNull new_name)
override
229 &nodetree_.id, &RNA_NodeTreeInterfacePanel, &panel_);
235 StringRef get_rename_string()
const override
240 std::unique_ptr<AbstractViewItemDragController> create_drag_controller()
const override;
241 std::unique_ptr<TreeViewItemDropTarget> create_drop_target()
override;
244class NodeTreeInterfaceView :
public AbstractTreeView {
251 : nodetree_(nodetree), interface_(
interface)
265 void build_tree()
override
268 this->add_items_for_panel_recursive(interface_.root_panel, *
this);
277 if (item == skip_item) {
284 NodeSocketViewItem &socket_item = parent_item.add_tree_item<NodeSocketViewItem>(
285 nodetree_, interface_, *socket);
286 socket_item.uncollapse_by_default();
292 NodePanelViewItem &panel_item = parent_item.add_tree_item<NodePanelViewItem>(
293 nodetree_, interface_, *panel);
294 panel_item.uncollapse_by_default();
297 add_items_for_panel_recursive(
306std::unique_ptr<AbstractViewItemDragController> NodeSocketViewItem::create_drag_controller()
const
308 return std::make_unique<NodeTreeInterfaceDragController>(
309 static_cast<NodeTreeInterfaceView &
>(this->get_tree_view()), socket_.
item, nodetree_);
312std::unique_ptr<TreeViewItemDropTarget> NodeSocketViewItem::create_drop_target()
314 return std::make_unique<NodeSocketDropTarget>(*
this, socket_);
317std::unique_ptr<AbstractViewItemDragController> NodePanelViewItem::create_drag_controller()
const
319 return std::make_unique<NodeTreeInterfaceDragController>(
320 static_cast<NodeTreeInterfaceView &
>(this->get_tree_view()), panel_.
item, nodetree_);
323std::unique_ptr<TreeViewItemDropTarget> NodePanelViewItem::create_drop_target()
325 return std::make_unique<NodePanelDropTarget>(*
this, panel_);
328NodeTreeInterfaceDragController::NodeTreeInterfaceDragController(NodeTreeInterfaceView &
view,
331 : AbstractViewItemDragController(
view), item_(item), tree_(
tree)
340void *NodeTreeInterfaceDragController::create_drag_data()
const
344 drag_data->
item = &item_;
345 drag_data->
tree = &tree_;
364 if (panel->contains(drop_target_item)) {
371NodeSocketDropTarget::NodeSocketDropTarget(NodeSocketViewItem &item,
377bool NodeSocketDropTarget::can_drop(
const wmDrag &drag,
const char ** )
const
382 if (is_dragging_parent_panel(drag, socket_.
item)) {
388std::string NodeSocketDropTarget::drop_tooltip(
const DragInfo &drag_info)
const
390 switch (drag_info.drop_location) {
391 case DropLocation::Into:
393 case DropLocation::Before:
394 return TIP_(
"Insert before socket");
395 case DropLocation::After:
396 return TIP_(
"Insert after socket");
402 const DragInfo &drag_info,
418 switch (drag_info.drop_location) {
419 case DropLocation::Before:
420 index = parent->items().as_span().first_index_try(&drop_target_item);
422 case DropLocation::After:
423 index = parent->items().as_span().first_index_try(&drop_target_item) + 1;
430 if (parent ==
nullptr || index < 0) {
434 interface.move_item_to_parent(*drag_item, parent, index);
442bool NodeSocketDropTarget::on_drop(
bContext *
C,
const DragInfo &drag_info)
const
444 bNodeTree &nodetree = this->get_view<NodeTreeInterfaceView>().nodetree();
445 return on_drop_flat_item(
C, drag_info, nodetree, socket_.
item);
453bool NodePanelDropTarget::can_drop(
const wmDrag &drag,
const char ** )
const
464 if (panel->contains(panel_.
item)) {
472std::string NodePanelDropTarget::drop_tooltip(
const DragInfo &drag_info)
const
474 switch (drag_info.drop_location) {
475 case DropLocation::Into:
476 return TIP_(
"Insert into panel");
477 case DropLocation::Before:
478 return TIP_(
"Insert before panel");
479 case DropLocation::After:
480 return TIP_(
"Insert after panel");
485bool NodePanelDropTarget::on_drop(
bContext *
C,
const DragInfo &drag_info)
const
492 bNodeTree &nodetree = get_view<NodeTreeInterfaceView>().nodetree();
497 switch (drag_info.drop_location) {
498 case DropLocation::Into: {
501 const bool has_toggle_socket = panel_.header_toggle_socket() != nullptr;
502 index = has_toggle_socket ? 1 : 0;
505 case DropLocation::Before: {
507 parent = interface.find_item_parent(panel_.item, true);
508 BLI_assert(parent != nullptr);
509 index = parent->items().as_span().first_index_try(&panel_.item);
512 case DropLocation::After: {
514 parent = interface.find_item_parent(panel_.item, true);
515 BLI_assert(parent != nullptr);
516 index = parent->items().as_span().first_index_try(&panel_.item) + 1;
520 if (parent ==
nullptr || index < 0) {
524 interface.move_item_to_parent(*drag_item, parent, index);
551 "Node Tree Declaration Tree View",
552 std::make_unique<blender::ui::nodes::NodeTreeInterfaceView>(nodetree,
interface));
Main * CTX_data_main(const bContext *C)
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
#define BLI_assert_unreachable()
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
NodeTreeInterfaceItemType
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_INPUT
struct bNodeTreeInterface bNodeTreeInterface
struct bNodeTreeInterfaceSocket bNodeTreeInterfaceSocket
struct bNodeTreeInterfacePanel bNodeTreeInterfacePanel
struct bNodeTreeInterfaceItem bNodeTreeInterfaceItem
struct bNodeTree bNodeTree
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 uiTemplateNodeSocket(uiLayout *layout, bContext *C, const float color[4])
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiLayoutSetEmboss(uiLayout *layout, blender::ui::EmbossType emboss)
@ WM_DRAG_NODE_TREE_INTERFACE
constexpr const char * c_str() const
void set_default_rows(int default_rows)
void set_context_menu_title(const std::string &title)
static void build_tree_view(const bContext &C, AbstractTreeView &tree_view, uiLayout &layout, std::optional< StringRef > search_string={}, bool add_box=true)
#define ID_IS_LINKED(_id)
void uiTemplateNodeTreeInterface(uiLayout *layout, bContext *C, PointerRNA *ptr)
void * MEM_callocN(size_t len, const char *str)
T & get_item_as(bNodeTreeInterfaceItem &item)
TreeViewItemContainer TreeViewOrItem
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
bNodeTreeInterfaceItem item
bNodeTreeInterfaceItem item
bNodeTreeInterfaceItem * item
void label(blender::StringRef name, int icon)
uiLayout & row(bool align)