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
This commit is contained in:
Jacques Lucke
2024-10-09 15:45:43 +02:00
parent dad7babaae
commit 6ffc585fb8
9 changed files with 320 additions and 543 deletions

View File

@@ -97,7 +97,7 @@ static void handle_node_declaration_items(bContext *C,
else if (const PanelDeclaration *panel_decl = dynamic_cast<const PanelDeclaration *>(
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);

View File

@@ -622,12 +622,12 @@ static Vector<NodeInterfaceItemData> 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<NodeInterfaceItemData> node_build_item_data(bNode &node)
UNUSED_VARS_NDEBUG(input_end, output_end, panel_state_end, panel_runtime_end);
Vector<NodeInterfaceItemData> 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<nodes::PanelDeclaration *>(
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<nodes::PanelDeclaration *>(
item_decl.get());
if (panel_decl == nullptr) {

View File

@@ -811,10 +811,10 @@ static void ui_node_draw_node(
using SocketIterator = blender::Span<bNodeSocket *>::iterator;
using PanelStateIterator = blender::MutableSpan<bNodePanelState>::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;

View File

@@ -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<SocketDeclaration>;
@@ -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<ItemDeclaration *> 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<ItemDeclaration *> &items;
DeclarationListBuilder(NodeDeclarationBuilder &node_decl_builder,
Vector<ItemDeclaration *> &items)
: node_decl_builder(node_decl_builder), items(items)
{
}
template<typename DeclType>
typename DeclType::Builder &add_socket(StringRef name,
StringRef identifier,
eNodeSocketInOut in_out);
template<typename DeclType>
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<PanelDeclaration>;
class NodeDeclaration {
public:
/* Combined list of socket and panel declarations.
* This determines order of sockets in the UI and panel content. */
Vector<ItemDeclarationPtr> items;
/* NOTE: inputs and outputs pointers are owned by the items list. */
/* Contains all items including recursive children.*/
Vector<ItemDeclarationPtr> all_items;
/* Contains only the items in the root. */
Vector<ItemDeclaration *> root_items;
/* All input and output socket declarations. */
Vector<SocketDeclaration *> inputs;
Vector<SocketDeclaration *> outputs;
std::unique_ptr<aal::RelationsInNode> 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<SocketDeclaration *> 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>
typename DeclType::Builder &add_input(StringRef name, StringRef identifier = "");
template<typename DeclType>
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>
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<SocketDeclaration> make_declaration_for_socket_type(
eNodeSocketDatatype socket_type);
/* -------------------------------------------------------------------- */
/** \name #PanelDeclarationBuilder Inline Methods
/** \name #DeclarationListBuilder Inline Methods
* \{ */
template<typename DeclType>
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<DeclType>(name, identifier, "", SOCK_IN);
return this->add_socket<DeclType>(name, identifier, SOCK_IN);
}
template<typename DeclType>
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<DeclType>(name, identifier, SOCK_OUT);
}
template<typename DeclType>
inline typename DeclType::Builder &DeclarationListBuilder::add_socket(StringRef name,
StringRef identifier,
eNodeSocketInOut in_out)
{
static_assert(std::is_base_of_v<SocketDeclaration, DeclType>);
using SocketBuilder = typename DeclType::Builder;
BLI_assert(ELEM(in_out, SOCK_IN, SOCK_OUT));
std::unique_ptr<SocketBuilder> socket_decl_builder_ptr = std::make_unique<SocketBuilder>();
SocketBuilder &socket_decl_builder = *socket_decl_builder_ptr;
this->node_decl_builder.socket_builders_.append(std::move(socket_decl_builder_ptr));
std::unique_ptr<DeclType> socket_decl_ptr = std::make_unique<DeclType>();
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<DeclType>(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<typename DeclType>
inline typename DeclType::Builder &NodeDeclarationBuilder::add_input(StringRef name,
StringRef identifier)
{
set_active_panel_builder(nullptr);
return this->add_socket<DeclType>(name, identifier, "", SOCK_IN);
}
template<typename DeclType>
inline typename DeclType::Builder &NodeDeclarationBuilder::add_output(StringRef name,
StringRef identifier)
{
set_active_panel_builder(nullptr);
return this->add_socket<DeclType>(name, "", identifier, SOCK_OUT);
}
template<typename DeclType>
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<SocketDeclaration, DeclType>);
using Builder = typename DeclType::Builder;
BLI_assert(ELEM(in_out, SOCK_IN, SOCK_OUT));
std::unique_ptr<Builder> socket_decl_builder = std::make_unique<Builder>();
socket_decl_builder->node_decl_builder_ = this;
if (in_out & SOCK_IN) {
std::unique_ptr<DeclType> socket_decl = std::make_unique<DeclType>();
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<DeclType> socket_decl = std::make_unique<DeclType>();
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

View File

@@ -255,11 +255,20 @@ class IDSocketDeclaration : public SocketDeclaration {
bool can_connect(const bNodeSocket &socket) const override;
};
template<typename T> class IDSocketDeclarationBuilder : public SocketDeclarationBuilder<T> {
public:
IDSocketDeclarationBuilder &default_value_fn(std::function<ID *(const bNode &node)> 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<Object>;
using Builder = IDSocketDeclarationBuilder<Object>;
Object();
};
@@ -268,7 +277,7 @@ class Material : public IDSocketDeclaration {
public:
static constexpr eNodeSocketDatatype static_socket_type = SOCK_MATERIAL;
using Builder = SocketDeclarationBuilder<Material>;
using Builder = IDSocketDeclarationBuilder<Material>;
Material();
};
@@ -277,7 +286,7 @@ class Collection : public IDSocketDeclaration {
public:
static constexpr eNodeSocketDatatype static_socket_type = SOCK_COLLECTION;
using Builder = SocketDeclarationBuilder<Collection>;
using Builder = IDSocketDeclarationBuilder<Collection>;
Collection();
};
@@ -286,7 +295,7 @@ class Texture : public IDSocketDeclaration {
public:
static constexpr eNodeSocketDatatype static_socket_type = SOCK_TEXTURE;
using Builder = SocketDeclarationBuilder<Texture>;
using Builder = IDSocketDeclarationBuilder<Texture>;
Texture();
};
@@ -295,7 +304,7 @@ class Image : public IDSocketDeclaration {
public:
static constexpr eNodeSocketDatatype static_socket_type = SOCK_IMAGE;
using Builder = SocketDeclarationBuilder<Image>;
using Builder = IDSocketDeclarationBuilder<Image>;
Image();
};
@@ -358,6 +367,13 @@ class Custom : public SocketDeclaration {
class CustomTypeBuilder : public SocketDeclarationBuilder<Custom> {
public:
CustomTypeBuilder &idname(const char *idname);
CustomTypeBuilder &init_socket_fn(
std::function<void(bNode &node, bNodeSocket &socket, const char *data_path)> 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

View File

@@ -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<bNodeSocketValueFloat>(io_socket);
std::unique_ptr<decl::Float> decl = std::make_unique<decl::Float>();
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<decl::Float>(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<bNodeSocketValueVector>(io_socket);
std::unique_ptr<decl::Vector> decl = std::make_unique<decl::Vector>();
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<decl::Vector>(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<bNodeSocketValueRGBA>(io_socket);
std::unique_ptr<decl::Color> decl = std::make_unique<decl::Color>();
decl->default_value = value.value;
dst = std::move(decl);
decl = &b.add_socket<decl::Color>(name, identifier, in_out).default_value(value.value);
break;
}
case SOCK_SHADER: {
std::unique_ptr<decl::Shader> decl = std::make_unique<decl::Shader>();
dst = std::move(decl);
decl = &b.add_socket<decl::Shader>(name, identifier, in_out);
break;
}
case SOCK_BOOLEAN: {
const auto &value = node_interface::get_socket_data_as<bNodeSocketValueBoolean>(io_socket);
std::unique_ptr<decl::Bool> decl = std::make_unique<decl::Bool>();
decl->default_value = value.value;
dst = std::move(decl);
decl = &b.add_socket<decl::Bool>(name, identifier, in_out).default_value(value.value);
break;
}
case SOCK_ROTATION: {
const auto &value = node_interface::get_socket_data_as<bNodeSocketValueRotation>(
io_socket);
std::unique_ptr<decl::Rotation> decl = std::make_unique<decl::Rotation>();
decl->default_value = math::EulerXYZ(float3(value.value_euler));
dst = std::move(decl);
decl = &b.add_socket<decl::Rotation>(name, identifier, in_out)
.default_value(math::EulerXYZ(float3(value.value_euler)));
break;
}
case SOCK_MATRIX: {
std::unique_ptr<decl::Matrix> decl = std::make_unique<decl::Matrix>();
dst = std::move(decl);
decl = &b.add_socket<decl::Matrix>(name, identifier, in_out);
break;
}
case SOCK_INT: {
const auto &value = node_interface::get_socket_data_as<bNodeSocketValueInt>(io_socket);
std::unique_ptr<decl::Int> decl = std::make_unique<decl::Int>();
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<decl::Int>(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<bNodeSocketValueString>(io_socket);
std::unique_ptr<decl::String> decl = std::make_unique<decl::String>();
decl->default_value = value.value;
decl->subtype = PropertySubType(value.subtype);
dst = std::move(decl);
decl = &b.add_socket<decl::String>(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<bNodeSocketValueMenu>(io_socket);
std::unique_ptr<decl::Menu> decl = std::make_unique<decl::Menu>();
decl->default_value = value.value;
dst = std::move(decl);
decl = &b.add_socket<decl::Menu>(name, identifier, in_out).default_value(value.value);
break;
}
case SOCK_OBJECT: {
auto value = std::make_unique<decl::Object>();
value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
dst = std::move(value);
decl = &b.add_socket<decl::Object>(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<decl::Image>();
value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
dst = std::move(value);
decl = &b.add_socket<decl::Image>(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::Geometry>();
decl = &b.add_socket<decl::Geometry>(name, identifier, in_out);
break;
case SOCK_COLLECTION: {
auto value = std::make_unique<decl::Collection>();
value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
dst = std::move(value);
decl = &b.add_socket<decl::Collection>(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<decl::Texture>();
value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
dst = std::move(value);
decl = &b.add_socket<decl::Texture>(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<decl::Material>();
value->default_value_fn = get_default_id_getter(ntree.tree_interface, io_socket);
dst = std::move(value);
decl = &b.add_socket<decl::Material>(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<decl::Custom>();
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<decl::Custom>(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<decl::Custom>();
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<decl::Custom>(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<const bNodeTreeInterfaceSocket &>(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<PanelDeclaration>();
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<bNodeTreeInterfaceSocket>(*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<bNodeTreeInterfacePanel>(*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<bNodeTreeInterfaceSocket>(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<bNodeTreeInterfacePanel>(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<bNodeTreeInterfaceSocket>(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<decl::Extend>("", "__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<bNodeTreeInterfaceSocket>(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<decl::Extend>("", "__extend__");
}
static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)

View File

@@ -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<SocketDeclaration *> 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<const ItemDeclaration *> items,
Vector<const SocketDeclaration *> &r_flat_inputs,
Vector<const SocketDeclaration *> &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<const SocketDeclaration *>(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<const PanelDeclaration *>(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<const SocketDeclaration *> flat_inputs;
Vector<const SocketDeclaration *> flat_outputs;
assert_valid_panels_recursive(*this, this->root_items, flat_inputs, flat_outputs);
Stack<ValidationState> 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<const SocketDeclaration *>(
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<const PanelDeclaration *>(
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<const SeparatorDeclaration *>(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<bNodeSocket *>(node.inputs.first);
const bNodeSocket *current_output = static_cast<bNodeSocket *>(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<const SocketDeclaration *>(
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<PanelDeclaration> panel_decl = std::make_unique<PanelDeclaration>();
std::unique_ptr<PanelDeclarationBuilder> panel_decl_builder =
std::make_unique<PanelDeclarationBuilder>();
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<typename Fn>
static bool socket_type_to_static_decl_type(const eNodeSocketDatatype socket_type, Fn &&fn)
{
@@ -465,7 +363,7 @@ std::unique_ptr<SocketDeclaration> 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<SeparatorDeclaration>());
auto decl_ptr = std::make_unique<SeparatorDeclaration>();
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<DeclT>(name, identifier);
});
if (!decl) {
BLI_assert_unreachable();
decl = &this->add_input<decl::Float>("", "");
auto panel_decl_ptr = std::make_unique<PanelDeclaration>();
PanelDeclaration &panel_decl = *panel_decl_ptr;
auto panel_decl_builder_ptr = std::make_unique<PanelDeclarationBuilder>(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<DeclT>(name, identifier);
});
if (!decl) {
BLI_assert_unreachable();
decl = &this->add_output<decl::Float>("", "");
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<int> input_indices)
{

View File

@@ -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<const PanelDeclaration *>(item_decl.get())) {
++new_num_panels;
}
@@ -451,7 +451,7 @@ static void refresh_node_sockets_and_panels(bNodeTree &ntree,
VectorSet<bNodeSocket *> new_inputs;
VectorSet<bNodeSocket *> 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<const SocketDeclaration *>(
item_decl.get()))
{

View File

@@ -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::Extend> decl = std::make_unique<decl::Extend>();
decl->name = "";
decl->identifier = "__extend__";
decl->in_out = in_out;
return decl;
}
/** \} */
} // namespace blender::nodes::decl