From 6ffc585fb864fbff9f2ee4c99cee73654ac5c75f Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 9 Oct 2024 15:45:43 +0200 Subject: [PATCH] Refactor: Geometry Nodes: recursive node declarations This refactor contains the following changes: * Each `PanelDeclaration` contains its direct children. Previously, it only knew how many children it had. That added complexity to wherever we iterate over the node declaration. * Adds a new `DeclarationListBuilder` that is a base class of `NodeDeclarationBuilder` and `PanelDeclarationBuilder`. It makes sure that the same API for adding sockets, panels and separators exist for both. * Modified declare functions for group, group input and group output nodes to use the normal node builder api instead of doing something custom. No functional changes are expected. The main reason for this refactor is to simplify working with nested panels in node declarations which is useful when we want to support nested panels in the node editor. The node drawing code is not simplified in this patch, but that should be easier afterwards. Pull Request: https://projects.blender.org/blender/blender/pulls/128799 --- .../interface_template_node_inputs.cc | 6 +- .../blender/editors/space_node/node_draw.cc | 14 +- .../editors/space_node/node_templates.cc | 4 +- source/blender/nodes/NOD_node_declaration.hh | 260 +++++++--------- .../blender/nodes/NOD_socket_declarations.hh | 28 +- source/blender/nodes/intern/node_common.cc | 254 ++++++---------- .../blender/nodes/intern/node_declaration.cc | 284 ++++++------------ source/blender/nodes/intern/node_socket.cc | 4 +- .../nodes/intern/node_socket_declarations.cc | 9 - 9 files changed, 320 insertions(+), 543 deletions(-) diff --git a/source/blender/editors/interface/templates/interface_template_node_inputs.cc b/source/blender/editors/interface/templates/interface_template_node_inputs.cc index 209412a2122..4699f8eeaf1 100644 --- a/source/blender/editors/interface/templates/interface_template_node_inputs.cc +++ b/source/blender/editors/interface/templates/interface_template_node_inputs.cc @@ -97,7 +97,7 @@ static void handle_node_declaration_items(bContext *C, else if (const PanelDeclaration *panel_decl = dynamic_cast( item_decl)) { - const ItemIterator panel_item_end = item_iter + panel_decl->num_child_decls; + const ItemIterator panel_item_end = item_iter + panel_decl->items.size(); BLI_assert(panel_item_end <= item_end); /* Use a root panel property to toggle open/closed state. */ @@ -138,8 +138,8 @@ void uiTemplateNodeInputs(uiLayout *layout, bContext *C, PointerRNA *ptr) if (node.declaration()) { /* Draw socket inputs and panel buttons in the order of declaration panels. */ - ItemIterator item_iter = node.declaration()->items.begin(); - const ItemIterator item_end = node.declaration()->items.end(); + ItemIterator item_iter = node.declaration()->all_items.begin(); + const ItemIterator item_end = node.declaration()->all_items.end(); Panel *root_panel = uiLayoutGetRootPanel(layout); blender::ui::nodes::handle_node_declaration_items( C, root_panel, layout, ptr, item_iter, item_end); diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index b3ace4d5a2e..29bf2be0c4c 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -622,12 +622,12 @@ static Vector node_build_item_data(bNode &node) BLI_assert(is_node_panels_supported(node)); BLI_assert(node.runtime->panels.size() == node.num_panel_states); - ItemDeclIterator item_decl = node.declaration()->items.begin(); + ItemDeclIterator item_decl = node.declaration()->all_items.begin(); SocketIterator input = node.input_sockets().begin(); SocketIterator output = node.output_sockets().begin(); PanelStateIterator panel_state = node.panel_states().begin(); PanelRuntimeIterator panel_runtime = node.runtime->panels.begin(); - const ItemDeclIterator item_decl_end = node.declaration()->items.end(); + const ItemDeclIterator item_decl_end = node.declaration()->all_items.end(); const SocketIterator input_end = node.input_sockets().end(); const SocketIterator output_end = node.output_sockets().end(); const PanelStateIterator panel_state_end = node.panel_states().end(); @@ -635,7 +635,7 @@ static Vector node_build_item_data(bNode &node) UNUSED_VARS_NDEBUG(input_end, output_end, panel_state_end, panel_runtime_end); Vector result; - result.reserve(node.declaration()->items.size()); + result.reserve(node.declaration()->all_items.size()); while (item_decl != item_decl_end) { if (const nodes::SocketDeclaration *socket_decl = @@ -729,7 +729,7 @@ static void node_update_panel_items_visibility_recursive(int num_items, const bool is_collapsed = is_parent_collapsed || item.state->is_collapsed(); node_update_panel_items_visibility_recursive( - item.panel_decl->num_child_decls, is_collapsed, *item.state, state); + item.panel_decl->items.size(), is_collapsed, *item.state, state); if (item.panel_decl->draw_buttons) { item.state->flag |= NODE_PANEL_CONTENT_VISIBLE; } @@ -842,7 +842,7 @@ static void add_panel_items_recursive(const bContext &C, block, locx, locy, - item.panel_decl->num_child_decls, + item.panel_decl->items.size(), is_collapsed, item.panel_decl->name.c_str(), item.runtime, @@ -2477,7 +2477,7 @@ static void node_draw_panels_background(const bNode &node, uiBlock &block) float last_panel_content_y = 0.0f; int panel_i = 0; - for (const nodes::ItemDeclarationPtr &item_decl : decl.items) { + for (const nodes::ItemDeclarationPtr &item_decl : decl.all_items) { const nodes::PanelDeclaration *panel_decl = dynamic_cast( item_decl.get()); if (panel_decl == nullptr) { @@ -2533,7 +2533,7 @@ static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block const rctf &rct = node.runtime->totr; int panel_i = 0; - for (const nodes::ItemDeclarationPtr &item_decl : decl.items) { + for (const nodes::ItemDeclarationPtr &item_decl : decl.all_items) { const nodes::PanelDeclaration *panel_decl = dynamic_cast( item_decl.get()); if (panel_decl == nullptr) { diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index 0446d22dc93..bb98a9d2434 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -811,10 +811,10 @@ static void ui_node_draw_node( using SocketIterator = blender::Span::iterator; using PanelStateIterator = blender::MutableSpan::iterator; - ItemDeclIterator item_decl = node.declaration()->items.begin(); + ItemDeclIterator item_decl = node.declaration()->all_items.begin(); SocketIterator input = node.input_sockets().begin(); PanelStateIterator panel_state = node.panel_states().begin(); - const ItemDeclIterator item_decl_end = node.declaration()->items.end(); + const ItemDeclIterator item_decl_end = node.declaration()->all_items.end(); bool panel_collapsed = false; const char *panel_label = nullptr; diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index bc1df943a57..c71d4f813a8 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -252,6 +252,8 @@ class SocketDeclaration : public ItemDeclaration { }; class NodeDeclarationBuilder; +class DeclarationListBuilder; +class PanelDeclarationBuilder; class BaseSocketDeclarationBuilder { protected: @@ -264,6 +266,7 @@ class BaseSocketDeclarationBuilder { SocketDeclaration *decl_base_ = nullptr; friend class NodeDeclarationBuilder; + friend class DeclarationListBuilder; public: virtual ~BaseSocketDeclarationBuilder() = default; @@ -274,6 +277,8 @@ class BaseSocketDeclarationBuilder { BaseSocketDeclarationBuilder &multi_input(bool value = true); + BaseSocketDeclarationBuilder &compact(bool value = true); + BaseSocketDeclarationBuilder &short_label(std::string value = ""); BaseSocketDeclarationBuilder &description(std::string value = ""); @@ -404,6 +409,7 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { SocketDecl *decl_; friend class NodeDeclarationBuilder; + friend class DeclarationListBuilder; }; using SocketDeclarationPtr = std::unique_ptr; @@ -422,8 +428,8 @@ class PanelDeclaration : public ItemDeclaration { std::string description; std::string translation_context; bool default_collapsed = false; - int num_child_decls = 0; PanelDrawButtonsFunction draw_buttons = nullptr; + Vector items; private: friend NodeDeclarationBuilder; @@ -437,23 +443,25 @@ class PanelDeclaration : public ItemDeclaration { void update_or_build(const bNodePanelState &old_panel, bNodePanelState &new_panel) const; }; -class PanelDeclarationBuilder { - protected: - using Self = PanelDeclarationBuilder; - NodeDeclarationBuilder *node_decl_builder_ = nullptr; - PanelDeclaration *decl_; - /** - * Panel is complete once items are added after it. - * Completed panels are locked and no more items can be added. - */ - bool is_complete_ = false; - - friend class NodeDeclarationBuilder; - +/** + * This is a base class for #NodeDeclarationBuilder and #PanelDeclarationBuilder. It unifies the + * behavior of adding sockets and other items to the root node and to panels. + */ +class DeclarationListBuilder { public: - Self &description(std::string value = ""); - Self &default_closed(bool closed); - Self &draw_buttons(PanelDrawButtonsFunction func); + NodeDeclarationBuilder &node_decl_builder; + Vector &items; + + DeclarationListBuilder(NodeDeclarationBuilder &node_decl_builder, + Vector &items) + : node_decl_builder(node_decl_builder), items(items) + { + } + + template + typename DeclType::Builder &add_socket(StringRef name, + StringRef identifier, + eNodeSocketInOut in_out); template typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); @@ -473,17 +481,38 @@ class PanelDeclarationBuilder { StringRef name, StringRef identifier = ""); + PanelDeclarationBuilder &add_panel(StringRef name, int identifier = -1); + void add_separator(); }; +class PanelDeclarationBuilder : public DeclarationListBuilder { + protected: + using Self = PanelDeclarationBuilder; + PanelDeclaration *decl_; + + friend class NodeDeclarationBuilder; + + public: + PanelDeclarationBuilder(NodeDeclarationBuilder &node_builder, PanelDeclaration &decl) + : DeclarationListBuilder(node_builder, decl.items), decl_(&decl) + { + } + + Self &description(std::string value = ""); + Self &default_closed(bool closed); + Self &draw_buttons(PanelDrawButtonsFunction func); +}; + using PanelDeclarationPtr = std::unique_ptr; class NodeDeclaration { public: - /* Combined list of socket and panel declarations. - * This determines order of sockets in the UI and panel content. */ - Vector items; - /* NOTE: inputs and outputs pointers are owned by the items list. */ + /* Contains all items including recursive children.*/ + Vector all_items; + /* Contains only the items in the root. */ + Vector root_items; + /* All input and output socket declarations. */ Vector inputs; Vector outputs; std::unique_ptr anonymous_attribute_relations_; @@ -508,8 +537,8 @@ class NodeDeclaration { friend NodeDeclarationBuilder; - /** Returns true if the declaration is considered valid. */ - bool is_valid() const; + /** Asserts that the declaration is considered valid. */ + void assert_valid() const; bool matches(const bNode &node) const; Span sockets(eNodeSocketInOut in_out) const; @@ -522,7 +551,7 @@ class NodeDeclaration { MEM_CXX_CLASS_ALLOC_FUNCS("NodeDeclaration") }; -class NodeDeclarationBuilder { +class NodeDeclarationBuilder : public DeclarationListBuilder { private: NodeDeclaration &declaration_; const bNodeTree *ntree_ = nullptr; @@ -534,7 +563,7 @@ class NodeDeclarationBuilder { bool is_function_node_ = false; private: - friend PanelDeclarationBuilder; + friend DeclarationListBuilder; public: NodeDeclarationBuilder(NodeDeclaration &declaration, @@ -567,27 +596,6 @@ class NodeDeclarationBuilder { void use_custom_socket_order(bool enable = true); void allow_any_socket_order(bool enable = true); - template - typename DeclType::Builder &add_input(StringRef name, StringRef identifier = ""); - template - typename DeclType::Builder &add_output(StringRef name, StringRef identifier = ""); - PanelDeclarationBuilder &add_panel(StringRef name, int identifier = -1); - - BaseSocketDeclarationBuilder &add_input(eNodeSocketDatatype socket_type, - StringRef name, - StringRef identifier = ""); - BaseSocketDeclarationBuilder &add_input(eCustomDataType data_type, - StringRef name, - StringRef identifier = ""); - BaseSocketDeclarationBuilder &add_output(eNodeSocketDatatype socket_type, - StringRef name, - StringRef identifier = ""); - BaseSocketDeclarationBuilder &add_output(eCustomDataType data_type, - StringRef name, - StringRef identifier = ""); - - void add_separator(); - aal::RelationsInNode &get_anonymous_attribute_relations() { if (!declaration_.anonymous_attribute_relations_) { @@ -602,16 +610,6 @@ class NodeDeclarationBuilder { } private: - template - typename DeclType::Builder &add_socket(StringRef name, - StringRef identifier_in, - StringRef identifier_out, - eNodeSocketInOut in_out); - - /* Mark the most recent builder as 'complete' when changing builders - * so no more items can be added. */ - void set_active_panel_builder(const PanelDeclarationBuilder *panel_builder); - void build_remaining_anonymous_attribute_relations(); }; @@ -632,33 +630,71 @@ std::unique_ptr make_declaration_for_socket_type( eNodeSocketDatatype socket_type); /* -------------------------------------------------------------------- */ -/** \name #PanelDeclarationBuilder Inline Methods +/** \name #DeclarationListBuilder Inline Methods * \{ */ template -typename DeclType::Builder &PanelDeclarationBuilder::add_input(StringRef name, - StringRef identifier) +inline typename DeclType::Builder &DeclarationListBuilder::add_input(StringRef name, + StringRef identifier) { - if (is_complete_) { - static typename DeclType::Builder dummy_builder = {}; - BLI_assert_unreachable(); - return dummy_builder; - } - ++this->decl_->num_child_decls; - return node_decl_builder_->add_socket(name, identifier, "", SOCK_IN); + return this->add_socket(name, identifier, SOCK_IN); } template -typename DeclType::Builder &PanelDeclarationBuilder::add_output(StringRef name, - StringRef identifier) +inline typename DeclType::Builder &DeclarationListBuilder::add_output(StringRef name, + StringRef identifier) { - if (is_complete_) { - static typename DeclType::Builder dummy_builder = {}; - BLI_assert_unreachable(); - return dummy_builder; + return this->add_socket(name, identifier, SOCK_OUT); +} + +template +inline typename DeclType::Builder &DeclarationListBuilder::add_socket(StringRef name, + StringRef identifier, + eNodeSocketInOut in_out) +{ + static_assert(std::is_base_of_v); + using SocketBuilder = typename DeclType::Builder; + + BLI_assert(ELEM(in_out, SOCK_IN, SOCK_OUT)); + + std::unique_ptr socket_decl_builder_ptr = std::make_unique(); + SocketBuilder &socket_decl_builder = *socket_decl_builder_ptr; + this->node_decl_builder.socket_builders_.append(std::move(socket_decl_builder_ptr)); + + std::unique_ptr socket_decl_ptr = std::make_unique(); + DeclType &socket_decl = *socket_decl_ptr; + this->node_decl_builder.declaration_.all_items.append(std::move(socket_decl_ptr)); + this->items.append(&socket_decl); + + socket_decl_builder.node_decl_builder_ = &this->node_decl_builder; + + socket_decl_builder.decl_ = &socket_decl; + socket_decl_builder.decl_base_ = &socket_decl; + socket_decl.name = name; + socket_decl.identifier = identifier.is_empty() ? name : identifier; + socket_decl.in_out = in_out; + socket_decl.socket_type = DeclType::static_socket_type; + + if (this->node_decl_builder.is_function_node_) { + if (in_out == SOCK_IN) { + socket_decl_builder.supports_field(); + } + else { + socket_decl_builder.dependent_field(); + } } - ++this->decl_->num_child_decls; - return node_decl_builder_->add_socket(name, "", identifier, SOCK_OUT); + + if (in_out == SOCK_IN) { + this->node_decl_builder.input_socket_builders_.append(&socket_decl_builder); + socket_decl_builder.index_ = this->node_decl_builder.declaration_.inputs.append_and_get_index( + &socket_decl); + } + else { + this->node_decl_builder.output_socket_builders_.append(&socket_decl_builder); + socket_decl_builder.index_ = this->node_decl_builder.declaration_.outputs.append_and_get_index( + &socket_decl); + } + return socket_decl_builder; } /** \} */ @@ -684,80 +720,4 @@ inline bool BaseSocketDeclarationBuilder::is_output() const /** \} */ -/* -------------------------------------------------------------------- */ -/** \name #NodeDeclarationBuilder Inline Methods - * \{ */ - -template -inline typename DeclType::Builder &NodeDeclarationBuilder::add_input(StringRef name, - StringRef identifier) -{ - set_active_panel_builder(nullptr); - return this->add_socket(name, identifier, "", SOCK_IN); -} - -template -inline typename DeclType::Builder &NodeDeclarationBuilder::add_output(StringRef name, - StringRef identifier) -{ - set_active_panel_builder(nullptr); - return this->add_socket(name, "", identifier, SOCK_OUT); -} - -template -inline typename DeclType::Builder &NodeDeclarationBuilder::add_socket(StringRef name, - StringRef identifier_in, - StringRef identifier_out, - eNodeSocketInOut in_out) -{ - static_assert(std::is_base_of_v); - using Builder = typename DeclType::Builder; - - BLI_assert(ELEM(in_out, SOCK_IN, SOCK_OUT)); - - std::unique_ptr socket_decl_builder = std::make_unique(); - socket_decl_builder->node_decl_builder_ = this; - - if (in_out & SOCK_IN) { - std::unique_ptr socket_decl = std::make_unique(); - socket_decl_builder->decl_ = &*socket_decl; - socket_decl_builder->decl_base_ = &*socket_decl; - socket_decl->name = name; - socket_decl->identifier = identifier_in.is_empty() ? name : identifier_in; - socket_decl->in_out = SOCK_IN; - socket_decl->socket_type = DeclType::static_socket_type; - socket_decl_builder->index_ = declaration_.inputs.append_and_get_index(socket_decl.get()); - declaration_.items.append(std::move(socket_decl)); - input_socket_builders_.append(&*socket_decl_builder); - } - if (in_out & SOCK_OUT) { - std::unique_ptr socket_decl = std::make_unique(); - socket_decl_builder->decl_ = &*socket_decl; - socket_decl_builder->decl_base_ = &*socket_decl; - socket_decl->name = name; - socket_decl->identifier = identifier_out.is_empty() ? name : identifier_out; - socket_decl->in_out = SOCK_OUT; - socket_decl->socket_type = DeclType::static_socket_type; - socket_decl_builder->index_ = declaration_.outputs.append_and_get_index(socket_decl.get()); - declaration_.items.append(std::move(socket_decl)); - output_socket_builders_.append(&*socket_decl_builder); - } - - if (is_function_node_) { - if (in_out == SOCK_IN) { - socket_decl_builder->supports_field(); - } - else { - socket_decl_builder->dependent_field(); - } - } - - Builder &socket_decl_builder_ref = *socket_decl_builder; - socket_builders_.append(std::move(socket_decl_builder)); - - return socket_decl_builder_ref; -} - -/** \} */ - } // namespace blender::nodes diff --git a/source/blender/nodes/NOD_socket_declarations.hh b/source/blender/nodes/NOD_socket_declarations.hh index c76eb31a40f..928ee111790 100644 --- a/source/blender/nodes/NOD_socket_declarations.hh +++ b/source/blender/nodes/NOD_socket_declarations.hh @@ -255,11 +255,20 @@ class IDSocketDeclaration : public SocketDeclaration { bool can_connect(const bNodeSocket &socket) const override; }; +template class IDSocketDeclarationBuilder : public SocketDeclarationBuilder { + public: + IDSocketDeclarationBuilder &default_value_fn(std::function fn) + { + this->decl_->default_value_fn = std::move(fn); + return *this; + } +}; + class Object : public IDSocketDeclaration { public: static constexpr eNodeSocketDatatype static_socket_type = SOCK_OBJECT; - using Builder = SocketDeclarationBuilder; + using Builder = IDSocketDeclarationBuilder; Object(); }; @@ -268,7 +277,7 @@ class Material : public IDSocketDeclaration { public: static constexpr eNodeSocketDatatype static_socket_type = SOCK_MATERIAL; - using Builder = SocketDeclarationBuilder; + using Builder = IDSocketDeclarationBuilder; Material(); }; @@ -277,7 +286,7 @@ class Collection : public IDSocketDeclaration { public: static constexpr eNodeSocketDatatype static_socket_type = SOCK_COLLECTION; - using Builder = SocketDeclarationBuilder; + using Builder = IDSocketDeclarationBuilder; Collection(); }; @@ -286,7 +295,7 @@ class Texture : public IDSocketDeclaration { public: static constexpr eNodeSocketDatatype static_socket_type = SOCK_TEXTURE; - using Builder = SocketDeclarationBuilder; + using Builder = IDSocketDeclarationBuilder; Texture(); }; @@ -295,7 +304,7 @@ class Image : public IDSocketDeclaration { public: static constexpr eNodeSocketDatatype static_socket_type = SOCK_IMAGE; - using Builder = SocketDeclarationBuilder; + using Builder = IDSocketDeclarationBuilder; Image(); }; @@ -358,6 +367,13 @@ class Custom : public SocketDeclaration { class CustomTypeBuilder : public SocketDeclarationBuilder { public: CustomTypeBuilder &idname(const char *idname); + + CustomTypeBuilder &init_socket_fn( + std::function fn) + { + decl_->init_socket_fn = std::move(fn); + return *this; + } }; /* -------------------------------------------------------------------- */ @@ -552,6 +568,4 @@ inline CustomTypeBuilder &CustomTypeBuilder::idname(const char *idname) /** \} */ -SocketDeclarationPtr create_extend_declaration(const eNodeSocketInOut in_out); - } // namespace blender::nodes::decl diff --git a/source/blender/nodes/intern/node_common.cc b/source/blender/nodes/intern/node_common.cc index 1363a3d610b..b6d182d3c22 100644 --- a/source/blender/nodes/intern/node_common.cc +++ b/source/blender/nodes/intern/node_common.cc @@ -239,196 +239,132 @@ get_init_socket_fn(const bNodeTreeInterface &interface, const bNodeTreeInterface }; } -/* in_out overrides the socket declaration in/out type (bNodeTreeInterfaceSocket::flag) - * because a node group input is turned into an output socket for group input nodes. */ -static SocketDeclarationPtr declaration_for_interface_socket( - const bNodeTree &ntree, +static BaseSocketDeclarationBuilder &build_interface_socket_declaration( + const bNodeTree &tree, const bNodeTreeInterfaceSocket &io_socket, - const eNodeSocketInOut in_out) + const eNodeSocketInOut in_out, + DeclarationListBuilder &b) { - SocketDeclarationPtr dst; - blender::bke::bNodeSocketType *base_typeinfo = blender::bke::node_socket_type_find( io_socket.socket_type); eNodeSocketDatatype datatype = SOCK_CUSTOM; + + const StringRef name = io_socket.name; + const StringRef identifier = io_socket.identifier; + + BaseSocketDeclarationBuilder *decl = nullptr; if (base_typeinfo) { datatype = eNodeSocketDatatype(base_typeinfo->type); switch (datatype) { case SOCK_FLOAT: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->subtype = PropertySubType(value.subtype); - decl->default_value = value.value; - decl->soft_min_value = value.min; - decl->soft_max_value = value.max; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out) + .subtype(PropertySubType(value.subtype)) + .default_value(value.value) + .min(value.min) + .max(value.max); break; } case SOCK_VECTOR: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->subtype = PropertySubType(value.subtype); - decl->default_value = value.value; - decl->soft_min_value = value.min; - decl->soft_max_value = value.max; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out) + .subtype(PropertySubType(value.subtype)) + .default_value(value.value) + .min(value.min) + .max(value.max); break; } case SOCK_RGBA: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->default_value = value.value; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out).default_value(value.value); break; } case SOCK_SHADER: { - std::unique_ptr decl = std::make_unique(); - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out); break; } case SOCK_BOOLEAN: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->default_value = value.value; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out).default_value(value.value); break; } case SOCK_ROTATION: { const auto &value = node_interface::get_socket_data_as( io_socket); - std::unique_ptr decl = std::make_unique(); - decl->default_value = math::EulerXYZ(float3(value.value_euler)); - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out) + .default_value(math::EulerXYZ(float3(value.value_euler))); break; } case SOCK_MATRIX: { - std::unique_ptr decl = std::make_unique(); - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out); break; } case SOCK_INT: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->subtype = PropertySubType(value.subtype); - decl->default_value = value.value; - decl->soft_min_value = value.min; - decl->soft_max_value = value.max; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out) + .subtype(PropertySubType(value.subtype)) + .default_value(value.value) + .min(value.min) + .max(value.max); break; } case SOCK_STRING: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->default_value = value.value; - decl->subtype = PropertySubType(value.subtype); - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out) + .subtype(PropertySubType(value.subtype)) + .default_value(value.value); break; } case SOCK_MENU: { const auto &value = node_interface::get_socket_data_as(io_socket); - std::unique_ptr decl = std::make_unique(); - decl->default_value = value.value; - dst = std::move(decl); + decl = &b.add_socket(name, identifier, in_out).default_value(value.value); break; } case SOCK_OBJECT: { - auto value = std::make_unique(); - value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket); - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .default_value_fn(get_default_id_getter(tree.tree_interface, io_socket)); break; } case SOCK_IMAGE: { - auto value = std::make_unique(); - value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket); - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .default_value_fn(get_default_id_getter(tree.tree_interface, io_socket)); break; } case SOCK_GEOMETRY: - dst = std::make_unique(); + decl = &b.add_socket(name, identifier, in_out); break; case SOCK_COLLECTION: { - auto value = std::make_unique(); - value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket); - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .default_value_fn(get_default_id_getter(tree.tree_interface, io_socket)); break; } case SOCK_TEXTURE: { - auto value = std::make_unique(); - value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket); - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .default_value_fn(get_default_id_getter(tree.tree_interface, io_socket)); break; } case SOCK_MATERIAL: { - auto value = std::make_unique(); - value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket); - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .default_value_fn(get_default_id_getter(tree.tree_interface, io_socket)); break; } case SOCK_CUSTOM: { - auto value = std::make_unique(); - value->init_socket_fn = get_init_socket_fn(ntree.tree_interface, io_socket); - value->idname_ = io_socket.socket_type; - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .idname(io_socket.socket_type) + .init_socket_fn(get_init_socket_fn(tree.tree_interface, io_socket)); break; } } } else { - auto value = std::make_unique(); - value->init_socket_fn = get_init_socket_fn(ntree.tree_interface, io_socket); - value->idname_ = io_socket.socket_type; - dst = std::move(value); + decl = &b.add_socket(name, identifier, in_out) + .idname(io_socket.socket_type) + .init_socket_fn(get_init_socket_fn(tree.tree_interface, io_socket)); } - dst->name = io_socket.name ? io_socket.name : ""; - dst->identifier = io_socket.identifier; - dst->in_out = in_out; - dst->socket_type = datatype; - dst->description = io_socket.description ? io_socket.description : ""; - dst->hide_value = io_socket.flag & NODE_INTERFACE_SOCKET_HIDE_VALUE; - dst->compact = io_socket.flag & NODE_INTERFACE_SOCKET_COMPACT; - return dst; -} - -/* Socket items can be both input and output, generating 2 declarations for 1 item. Count the - * actual declarations generated by panel content to get the true size for UI drawing. */ -static int count_panel_declaration_children(const bNodeTreeInterfacePanel &io_panel) -{ - int num_child_decls = 0; - io_panel.foreach_item([&](const bNodeTreeInterfaceItem &item) { - switch (item.item_type) { - case NODE_INTERFACE_PANEL: - num_child_decls++; - break; - case NODE_INTERFACE_SOCKET: - const bNodeTreeInterfaceSocket &socket = - reinterpret_cast(item); - if (socket.flag & NODE_INTERFACE_SOCKET_INPUT) { - num_child_decls++; - } - if (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) { - num_child_decls++; - } - break; - } - return true; - }); - return num_child_decls; -} - -static PanelDeclarationPtr declaration_for_interface_panel(const bNodeTree & /*ntree*/, - const bNodeTreeInterfacePanel &io_panel) -{ - if (io_panel.items_num == 0) { - return nullptr; - } - - PanelDeclarationPtr dst = std::make_unique(); - dst->identifier = io_panel.identifier; - dst->name = io_panel.name ? io_panel.name : ""; - dst->description = io_panel.description ? io_panel.description : ""; - dst->default_collapsed = (io_panel.flag & NODE_INTERFACE_PANEL_DEFAULT_CLOSED); - dst->num_child_decls = count_panel_declaration_children(io_panel); - return dst; + decl->description(io_socket.description ? io_socket.description : ""); + decl->hide_value(io_socket.flag & NODE_INTERFACE_SOCKET_HIDE_VALUE); + decl->compact(io_socket.flag & NODE_INTERFACE_SOCKET_COMPACT); + return *decl; } static void set_default_input_field(const bNodeTreeInterfaceSocket &input, SocketDeclaration &decl) @@ -464,6 +400,31 @@ static void set_default_input_field(const bNodeTreeInterfaceSocket &input, Socke } } +static void node_group_declare_panel_recursive(DeclarationListBuilder &b, + const bNodeTree &group, + const bNodeTreeInterfacePanel &io_parent_panel) +{ + for (const bNodeTreeInterfaceItem *item : io_parent_panel.items()) { + switch (item->item_type) { + case NODE_INTERFACE_SOCKET: { + const auto &io_socket = node_interface::get_item_as(*item); + const eNodeSocketInOut in_out = (io_socket.flag & NODE_INTERFACE_SOCKET_INPUT) ? SOCK_IN : + SOCK_OUT; + build_interface_socket_declaration(group, io_socket, in_out, b); + break; + } + case NODE_INTERFACE_PANEL: { + const auto &io_panel = node_interface::get_item_as(*item); + auto &panel_b = b.add_panel(StringRef(io_panel.name), io_panel.identifier) + .description(StringRef(io_panel.description)) + .default_closed(io_panel.flag & NODE_INTERFACE_PANEL_DEFAULT_CLOSED); + node_group_declare_panel_recursive(panel_b, group, io_panel); + break; + } + } + } +} + void node_group_declare(NodeDeclarationBuilder &b) { const bNode *node = b.node_or_null(); @@ -484,41 +445,7 @@ void node_group_declare(NodeDeclarationBuilder &b) /* Allow the node group interface to define the socket order. */ r_declaration.use_custom_socket_order = true; - group->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) { - switch (item.item_type) { - case NODE_INTERFACE_SOCKET: { - const bNodeTreeInterfaceSocket &socket = - node_interface::get_item_as(item); - - SocketDeclarationPtr input_decl = (socket.flag & NODE_INTERFACE_SOCKET_INPUT) ? - declaration_for_interface_socket( - *group, socket, SOCK_IN) : - nullptr; - SocketDeclarationPtr output_decl = (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) ? - declaration_for_interface_socket( - *group, socket, SOCK_OUT) : - nullptr; - if (output_decl) { - r_declaration.outputs.append(output_decl.get()); - r_declaration.items.append(std::move(output_decl)); - } - if (input_decl) { - r_declaration.inputs.append(input_decl.get()); - r_declaration.items.append(std::move(input_decl)); - } - break; - } - case NODE_INTERFACE_PANEL: { - const bNodeTreeInterfacePanel &panel = - node_interface::get_item_as(item); - if (PanelDeclarationPtr panel_decl = declaration_for_interface_panel(*group, panel)) { - r_declaration.items.append(std::move(panel_decl)); - } - break; - } - } - return true; - }); + node_group_declare_panel_recursive(b, *group, group->tree_interface.root_panel); if (group->type == NTREE_GEOMETRY) { group->ensure_interface_cache(); @@ -746,26 +673,20 @@ static void group_input_declare(NodeDeclarationBuilder &b) if (node_tree == nullptr) { return; } - NodeDeclaration &r_declaration = b.declaration(); node_tree->tree_interface.foreach_item([&](const bNodeTreeInterfaceItem &item) { switch (item.item_type) { case NODE_INTERFACE_SOCKET: { const bNodeTreeInterfaceSocket &socket = node_interface::get_item_as(item); if (socket.flag & NODE_INTERFACE_SOCKET_INPUT) { - SocketDeclarationPtr socket_decl = declaration_for_interface_socket( - *node_tree, socket, SOCK_OUT); - r_declaration.outputs.append(socket_decl.get()); - r_declaration.items.append(std::move(socket_decl)); + build_interface_socket_declaration(*node_tree, socket, SOCK_OUT, b); } break; } } return true; }); - SocketDeclarationPtr extend_decl = decl::create_extend_declaration(SOCK_OUT); - r_declaration.outputs.append(extend_decl.get()); - r_declaration.items.append(std::move(extend_decl)); + b.add_output("", "__extend__"); } static void group_output_declare(NodeDeclarationBuilder &b) @@ -781,19 +702,14 @@ static void group_output_declare(NodeDeclarationBuilder &b) const bNodeTreeInterfaceSocket &socket = node_interface::get_item_as(item); if (socket.flag & NODE_INTERFACE_SOCKET_OUTPUT) { - SocketDeclarationPtr socket_decl = declaration_for_interface_socket( - *node_tree, socket, SOCK_IN); - r_declaration.inputs.append(socket_decl.get()); - r_declaration.items.append(std::move(socket_decl)); + build_interface_socket_declaration(*node_tree, socket, SOCK_IN, b); } break; } } return true; }); - SocketDeclarationPtr extend_decl = decl::create_extend_declaration(SOCK_IN); - r_declaration.inputs.append(extend_decl.get()); - r_declaration.items.append(std::move(extend_decl)); + b.add_input("", "__extend__"); } static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link) diff --git a/source/blender/nodes/intern/node_declaration.cc b/source/blender/nodes/intern/node_declaration.cc index 2837d95ccd2..bc30dc64af2 100644 --- a/source/blender/nodes/intern/node_declaration.cc +++ b/source/blender/nodes/intern/node_declaration.cc @@ -94,13 +94,18 @@ void NodeDeclarationBuilder::build_remaining_anonymous_attribute_relations() void NodeDeclarationBuilder::finalize() { this->build_remaining_anonymous_attribute_relations(); - BLI_assert(declaration_.is_valid()); +#ifndef NDEBUG + declaration_.assert_valid(); +#endif } NodeDeclarationBuilder::NodeDeclarationBuilder(NodeDeclaration &declaration, const bNodeTree *ntree, const bNode *node) - : declaration_(declaration), ntree_(ntree), node_(node) + : DeclarationListBuilder(*this, declaration.root_items), + declaration_(declaration), + ntree_(ntree), + node_(node) { } @@ -123,20 +128,6 @@ Span NodeDeclaration::sockets(eNodeSocketInOut in_out) cons return outputs; } -void NodeDeclarationBuilder::set_active_panel_builder(const PanelDeclarationBuilder *panel_builder) -{ - if (panel_builders_.is_empty()) { - BLI_assert(panel_builder == nullptr); - return; - } - - BLI_assert(!panel_builder || !panel_builder->is_complete_); - PanelDeclarationBuilder *last_panel_builder = panel_builders_.last().get(); - if (last_panel_builder != panel_builder) { - last_panel_builder->is_complete_ = true; - } -} - namespace anonymous_attribute_lifetime { std::ostream &operator<<(std::ostream &stream, const RelationsInNode &relations) @@ -168,95 +159,47 @@ std::ostream &operator<<(std::ostream &stream, const RelationsInNode &relations) } // namespace anonymous_attribute_lifetime -bool NodeDeclaration::is_valid() const +static void assert_valid_panels_recursive(const NodeDeclaration &node_decl, + const Span items, + Vector &r_flat_inputs, + Vector &r_flat_outputs) +{ + /* Expected item order unless any order is allowed: outputs, inputs, panels. */ + bool found_input = false; + bool found_panel = false; + + for (const ItemDeclaration *item_decl : items) { + if (const auto *socket_decl = dynamic_cast(item_decl)) { + if (socket_decl->in_out == SOCK_IN) { + BLI_assert(node_decl.allow_any_socket_order || !found_panel); + found_input = true; + r_flat_inputs.append(socket_decl); + } + else { + BLI_assert(node_decl.allow_any_socket_order || (!found_input && !found_panel)); + r_flat_outputs.append(socket_decl); + } + } + else if (const auto *panel_decl = dynamic_cast(item_decl)) { + found_panel = true; + assert_valid_panels_recursive(node_decl, panel_decl->items, r_flat_inputs, r_flat_outputs); + } + } +} + +void NodeDeclaration::assert_valid() const { if (!this->use_custom_socket_order) { - /* Skip validation for conventional socket layouts. */ - return true; + /* Skip validation for conventional socket layouts. Those are reordered in drawing code. */ + return; } - /* Validation state for the interface root items as well as any panel content. */ - struct ValidationState { - /* Remaining number of items expected in a panel */ - int remaining_items = 0; - /* Sockets first, followed by panels. */ - NodeTreeInterfaceItemType item_type = NODE_INTERFACE_SOCKET; - /* Output sockets first, followed by input sockets. */ - eNodeSocketInOut socket_in_out = SOCK_OUT; - }; + Vector flat_inputs; + Vector flat_outputs; + assert_valid_panels_recursive(*this, this->root_items, flat_inputs, flat_outputs); - Stack panel_states; - panel_states.push({}); - - for (const ItemDeclarationPtr &item_decl : items) { - BLI_assert(panel_states.size() >= 1); - ValidationState &state = panel_states.peek(); - - if (const SocketDeclaration *socket_decl = dynamic_cast( - item_decl.get())) - { - if (state.item_type != NODE_INTERFACE_SOCKET && !this->allow_any_socket_order) { - std::cout << "Socket added after panel" << std::endl; - return false; - } - - /* Check for consistent outputs.., inputs.. blocks. */ - if (state.socket_in_out == SOCK_OUT && socket_decl->in_out == SOCK_IN) { - /* Start of input sockets. */ - state.socket_in_out = SOCK_IN; - } - if (socket_decl->in_out != state.socket_in_out && !this->allow_any_socket_order) { - std::cout << "Output socket added after input socket" << std::endl; - return false; - } - - /* Item counting for the panels, but ignore for root items. */ - if (panel_states.size() > 1) { - if (state.remaining_items <= 0) { - std::cout << "More sockets than expected in panel" << std::endl; - return false; - } - --state.remaining_items; - /* Panel closed after last item is added. */ - if (state.remaining_items == 0) { - panel_states.pop(); - } - } - } - else if (const PanelDeclaration *panel_decl = dynamic_cast( - item_decl.get())) - { - if (state.item_type == NODE_INTERFACE_SOCKET) { - /* Start of panels section */ - state.item_type = NODE_INTERFACE_PANEL; - } - BLI_assert(state.item_type == NODE_INTERFACE_PANEL); - - if (panel_decl->num_child_decls > 0) { - /* New panel started. */ - panel_states.push({panel_decl->num_child_decls}); - } - } - else if (dynamic_cast(item_decl.get())) { - if (panel_states.size() > 1) { - --state.remaining_items; - if (state.remaining_items == 0) { - panel_states.pop(); - } - } - } - else { - BLI_assert_unreachable(); - return false; - } - } - - /* All panels complete? */ - if (panel_states.size() != 1) { - std::cout << "Incomplete last panel" << std::endl; - return false; - } - return true; + BLI_assert(this->inputs.as_span() == flat_inputs); + BLI_assert(this->outputs.as_span() == flat_outputs); } bool NodeDeclaration::matches(const bNode &node) const @@ -264,7 +207,7 @@ bool NodeDeclaration::matches(const bNode &node) const const bNodeSocket *current_input = static_cast(node.inputs.first); const bNodeSocket *current_output = static_cast(node.outputs.first); const bNodePanelState *current_panel = node.panel_states_array; - for (const ItemDeclarationPtr &item_decl : items) { + for (const ItemDeclarationPtr &item_decl : this->all_items) { if (const SocketDeclaration *socket_decl = dynamic_cast( item_decl.get())) { @@ -358,51 +301,6 @@ bool SocketDeclaration::matches_common_data(const bNodeSocket &socket) const return true; } -PanelDeclarationBuilder &NodeDeclarationBuilder::add_panel(StringRef name, int identifier) -{ - std::unique_ptr panel_decl = std::make_unique(); - std::unique_ptr panel_decl_builder = - std::make_unique(); - panel_decl_builder->decl_ = &*panel_decl; - - panel_decl_builder->node_decl_builder_ = this; - if (identifier >= 0) { - panel_decl->identifier = identifier; - } - else { - /* Use index as identifier. */ - panel_decl->identifier = declaration_.items.size(); - } - panel_decl->name = name; - declaration_.items.append(std::move(panel_decl)); - - PanelDeclarationBuilder &builder_ref = *panel_decl_builder; - panel_builders_.append(std::move(panel_decl_builder)); - set_active_panel_builder(&builder_ref); - - return builder_ref; -} - -void PanelDeclaration::build(bNodePanelState &panel) const -{ - panel = {0}; - panel.identifier = this->identifier; - SET_FLAG_FROM_TEST(panel.flag, this->default_collapsed, NODE_PANEL_COLLAPSED); -} - -bool PanelDeclaration::matches(const bNodePanelState &panel) const -{ - return panel.identifier == this->identifier; -} - -void PanelDeclaration::update_or_build(const bNodePanelState &old_panel, - bNodePanelState &new_panel) const -{ - build(new_panel); - /* Copy existing state to the new panel */ - SET_FLAG_FROM_TEST(new_panel.flag, old_panel.is_collapsed(), NODE_PANEL_COLLAPSED); -} - template static bool socket_type_to_static_decl_type(const eNodeSocketDatatype socket_type, Fn &&fn) { @@ -465,7 +363,7 @@ std::unique_ptr make_declaration_for_socket_type( return decl; } -BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_input( +BaseSocketDeclarationBuilder &DeclarationListBuilder::add_input( const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier) { BaseSocketDeclarationBuilder *decl = nullptr; @@ -480,14 +378,14 @@ BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_input( return *decl; } -BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_input(const eCustomDataType data_type, +BaseSocketDeclarationBuilder &DeclarationListBuilder::add_input(const eCustomDataType data_type, const StringRef name, const StringRef identifier) { return this->add_input(*bke::custom_data_type_to_socket_type(data_type), name, identifier); } -BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_output( +BaseSocketDeclarationBuilder &DeclarationListBuilder::add_output( const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier) { BaseSocketDeclarationBuilder *decl = nullptr; @@ -502,69 +400,61 @@ BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_output( return *decl; } -BaseSocketDeclarationBuilder &NodeDeclarationBuilder::add_output(const eCustomDataType data_type, +BaseSocketDeclarationBuilder &DeclarationListBuilder::add_output(const eCustomDataType data_type, const StringRef name, const StringRef identifier) { return this->add_output(*bke::custom_data_type_to_socket_type(data_type), name, identifier); } -void NodeDeclarationBuilder::add_separator() +void DeclarationListBuilder::add_separator() { - declaration_.items.append(std::make_unique()); + auto decl_ptr = std::make_unique(); + SeparatorDeclaration &decl = *decl_ptr; + this->node_decl_builder.declaration_.all_items.append(std::move(decl_ptr)); + this->items.append(&decl); } -BaseSocketDeclarationBuilder &PanelDeclarationBuilder::add_input( - const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier) +PanelDeclarationBuilder &DeclarationListBuilder::add_panel(const StringRef name, int identifier) { - BaseSocketDeclarationBuilder *decl = nullptr; - socket_type_to_static_decl_type(socket_type, [&](auto type_tag) { - using DeclT = typename decltype(type_tag)::type; - decl = &this->add_input(name, identifier); - }); - if (!decl) { - BLI_assert_unreachable(); - decl = &this->add_input("", ""); + auto panel_decl_ptr = std::make_unique(); + PanelDeclaration &panel_decl = *panel_decl_ptr; + auto panel_decl_builder_ptr = std::make_unique(this->node_decl_builder, + panel_decl); + PanelDeclarationBuilder &panel_decl_builder = *panel_decl_builder_ptr; + + if (identifier >= 0) { + panel_decl.identifier = identifier; } - return *decl; -} - -BaseSocketDeclarationBuilder &PanelDeclarationBuilder::add_input(const eCustomDataType data_type, - const StringRef name, - const StringRef identifier) -{ - return this->add_input(*bke::custom_data_type_to_socket_type(data_type), name, identifier); -} - -BaseSocketDeclarationBuilder &PanelDeclarationBuilder::add_output( - const eNodeSocketDatatype socket_type, const StringRef name, const StringRef identifier) -{ - BaseSocketDeclarationBuilder *decl = nullptr; - socket_type_to_static_decl_type(socket_type, [&](auto type_tag) { - using DeclT = typename decltype(type_tag)::type; - decl = &this->add_output(name, identifier); - }); - if (!decl) { - BLI_assert_unreachable(); - decl = &this->add_output("", ""); + else { + /* Use index as identifier. */ + panel_decl.identifier = this->node_decl_builder.declaration_.all_items.size(); } - return *decl; + panel_decl.name = name; + this->node_decl_builder.declaration_.all_items.append(std::move(panel_decl_ptr)); + this->node_decl_builder.panel_builders_.append(std::move(panel_decl_builder_ptr)); + this->items.append(&panel_decl); + return panel_decl_builder; } -BaseSocketDeclarationBuilder &PanelDeclarationBuilder::add_output(const eCustomDataType data_type, - const StringRef name, - const StringRef identifier) +void PanelDeclaration::build(bNodePanelState &panel) const { - return this->add_output(*bke::custom_data_type_to_socket_type(data_type), name, identifier); + panel = {0}; + panel.identifier = this->identifier; + SET_FLAG_FROM_TEST(panel.flag, this->default_collapsed, NODE_PANEL_COLLAPSED); } -void PanelDeclarationBuilder::add_separator() +bool PanelDeclaration::matches(const bNodePanelState &panel) const { - if (is_complete_) { - BLI_assert_unreachable(); - } - ++this->decl_->num_child_decls; - node_decl_builder_->add_separator(); + return panel.identifier == this->identifier; +} + +void PanelDeclaration::update_or_build(const bNodePanelState &old_panel, + bNodePanelState &new_panel) const +{ + build(new_panel); + /* Copy existing state to the new panel */ + SET_FLAG_FROM_TEST(new_panel.flag, old_panel.is_collapsed(), NODE_PANEL_COLLAPSED); } BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder::supports_field() @@ -603,6 +493,12 @@ BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder::multi_input(bool val return *this; } +BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder::compact(bool value) +{ + decl_base_->compact = value; + return *this; +} + BaseSocketDeclarationBuilder &BaseSocketDeclarationBuilder::reference_pass( const Span input_indices) { diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index ff550e83bc4..ce0e667eb8a 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -422,7 +422,7 @@ static void refresh_node_sockets_and_panels(bNodeTree &ntree, /* Count panels */ int new_num_panels = 0; - for (const ItemDeclarationPtr &item_decl : node_decl.items) { + for (const ItemDeclarationPtr &item_decl : node_decl.all_items) { if (dynamic_cast(item_decl.get())) { ++new_num_panels; } @@ -451,7 +451,7 @@ static void refresh_node_sockets_and_panels(bNodeTree &ntree, VectorSet new_inputs; VectorSet new_outputs; bNodePanelState *new_panel = node.panel_states_array; - for (const ItemDeclarationPtr &item_decl : node_decl.items) { + for (const ItemDeclarationPtr &item_decl : node_decl.all_items) { if (const SocketDeclaration *socket_decl = dynamic_cast( item_decl.get())) { diff --git a/source/blender/nodes/intern/node_socket_declarations.cc b/source/blender/nodes/intern/node_socket_declarations.cc index 542ace7218b..d85cadd4a62 100644 --- a/source/blender/nodes/intern/node_socket_declarations.cc +++ b/source/blender/nodes/intern/node_socket_declarations.cc @@ -830,15 +830,6 @@ bNodeSocket &Custom::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket return socket; } -SocketDeclarationPtr create_extend_declaration(const eNodeSocketInOut in_out) -{ - std::unique_ptr decl = std::make_unique(); - decl->name = ""; - decl->identifier = "__extend__"; - decl->in_out = in_out; - return decl; -} - /** \} */ } // namespace blender::nodes::decl