Files
test2/source/blender/nodes/intern/node_socket_declarations.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

979 lines
28 KiB
C++
Raw Permalink Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "NOD_socket_declarations.hh"
#include "NOD_socket_declarations_geometry.hh"
2024-01-15 12:44:04 -05:00
#include "BKE_lib_id.hh"
#include "BKE_node_runtime.hh"
#include "BLI_math_vector.h"
Nodes: initial support for built-in menu sockets So far, only node group were able to have menu input sockets. Built-in nodes did not support them. Currently, all menus of built-in nodes are stored on the node instead of on the sockets. This limits their flexibility because it's not possible to expose these inputs. This patch adds initial support for having menu inputs in built-in nodes. For testing purposes, it also changes a couple built-in nodes to use an input socket instead of a node property: Points to Volume, Transform Geometry, Triangulate, Volume to Mesh and Match String. ### Compatibility Forward and backward compatibility is maintained where possible (it's not possible when the menu input is linked in 5.0). The overall compatibility approach is the same as what was done for the compositor with two differences: there are no wrapper RNA properties (not necessary for 5.0, those were removed for the compositor already too), no need to version animation (animation on the menu properties was already disabled). This also makes menu sockets not animatable in general which is kind of brittle (e.g. doesn't properly update when the menu definition changes). To animate a menu it's better to animate an integer and to drive an index switch with it. ### Which nodes to update? Many existing menu properties can become sockets, but it's currently not the intention to convert all of them. In some cases, converting them might restrict future improvements too much. This mainly affects Math nodes. Other existing nodes should be updated but are a bit more tricky to update for different reasons: * We don't support dynamic output visibility yet. This is something I'll need to look into at some point. * They are shared with shader/compositor nodes, which may be more limited in what can become a socket. * There may be performance implications unless extra special cases are implemented, especially for multi-function nodes. * Some nodes use socket renaming instead of dynamic socket visibility which isn't something we support more generally yet. ### Implementation The core implementation is fairly straight forward. The heavy lifting is done by the existing socket visibility inferencing. There is a new simple API that allows individual nodes to implement custom input-usage-rules based on other inputs in a decentralized way. In most cases, the nodes to update just have a single menu, so there is a new node-declaration utility that links a socket to a specific value of the menu input. This internally handles the usage inferencing as well as making the socket available when using link-drag-search. In the modified nodes, I also had to explicitly set the "main input" now which is used when inserting the node in a link. The automatic behavior doesn't work currently when the first input is a menu. This is something we'll have to solve more generally at some point but is out of scope for this patch. Pull Request: https://projects.blender.org/blender/blender/pulls/140705
2025-07-16 08:31:59 +02:00
#include "BLI_string.h"
#include "BLI_string_utf8.h"
namespace blender::nodes::decl {
/**
* \note This function only deals with declarations, not the field status of existing nodes. If the
* field status of existing nodes was stored on the sockets, an improvement would be to check the
* existing socket's current status instead of the declaration.
*/
static bool field_types_are_compatible(const SocketDeclaration &input,
const SocketDeclaration &output)
{
if (output.output_field_dependency.field_type() == OutputSocketFieldType::FieldSource) {
if (input.input_field_type == InputSocketFieldType::None) {
return false;
}
}
return true;
}
static bool sockets_can_connect(const SocketDeclaration &socket_decl,
const bNodeSocket &other_socket)
{
/* Input sockets cannot connect to input sockets, outputs cannot connect to outputs. */
if (socket_decl.in_out == other_socket.in_out) {
return false;
}
if (other_socket.runtime->declaration) {
if (socket_decl.in_out == SOCK_IN) {
if (!field_types_are_compatible(socket_decl, *other_socket.runtime->declaration)) {
return false;
}
}
else {
if (!field_types_are_compatible(*other_socket.runtime->declaration, socket_decl)) {
return false;
}
}
}
return true;
}
static bool basic_types_can_connect(const SocketDeclaration & /*socket_decl*/,
const bNodeSocket &other_socket)
{
return ELEM(other_socket.type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA);
}
static void modify_subtype_except_for_storage(bNodeSocket &socket, int new_subtype)
{
const StringRefNull idname = *bke::node_static_socket_type(socket.type, new_subtype);
STRNCPY_UTF8(socket.idname, idname.c_str());
bke::bNodeSocketType *socktype = bke::node_socket_type_find(idname);
socket.typeinfo = socktype;
}
static void modify_subtype_except_for_storage(bNodeSocket &socket, int subtype, int dimensions)
{
const StringRefNull idname = *bke::node_static_socket_type(socket.type, subtype, dimensions);
STRNCPY_UTF8(socket.idname, idname.c_str());
bke::bNodeSocketType *socktype = bke::node_socket_type_find(idname);
socket.typeinfo = socktype;
}
2021-10-05 11:10:25 +11:00
/* -------------------------------------------------------------------- */
/** \name #Float
* \{ */
bNodeSocket &Float::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_FLOAT,
this->subtype,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
value.value = this->default_value;
return socket;
}
bool Float::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_FLOAT) {
return false;
}
if (socket.typeinfo->subtype != this->subtype) {
return false;
}
bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value;
if (value.min != this->soft_min_value) {
return false;
}
if (value.max != this->soft_max_value) {
return false;
}
return true;
}
bool Float::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
if (this->in_out == SOCK_OUT && socket.type == SOCK_ROTATION) {
return true;
}
return basic_types_can_connect(*this, socket);
}
bNodeSocket &Float::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_FLOAT) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
if (socket.typeinfo->subtype != this->subtype) {
modify_subtype_except_for_storage(socket, this->subtype);
}
this->set_common_flags(socket);
bNodeSocketValueFloat &value = *(bNodeSocketValueFloat *)socket.default_value;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
value.subtype = this->subtype;
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Int
* \{ */
bNodeSocket &Int::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_INT,
this->subtype,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
value.value = this->default_value;
return socket;
}
bool Int::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_INT) {
return false;
}
if (socket.typeinfo->subtype != this->subtype) {
return false;
}
bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value;
if (value.min != this->soft_min_value) {
return false;
}
if (value.max != this->soft_max_value) {
return false;
}
return true;
}
bool Int::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
return basic_types_can_connect(*this, socket);
}
bNodeSocket &Int::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_INT) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
if (socket.typeinfo->subtype != this->subtype) {
modify_subtype_except_for_storage(socket, this->subtype);
}
this->set_common_flags(socket);
bNodeSocketValueInt &value = *(bNodeSocketValueInt *)socket.default_value;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
value.subtype = this->subtype;
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Vector
* \{ */
bNodeSocket &Vector::build(bNodeTree &ntree, bNode &node) const
{
const StringRefNull idname = *bke::node_static_socket_type(
SOCK_VECTOR, this->subtype, this->dimensions);
bNodeSocket &socket = *bke::node_add_socket(
ntree, node, this->in_out, idname, this->identifier.c_str(), this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value;
std::copy_n(&this->default_value[0], this->dimensions, value.value);
value.dimensions = this->dimensions;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
return socket;
}
bool Vector::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_VECTOR) {
return false;
}
if (socket.typeinfo->subtype != this->subtype) {
return false;
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
const bNodeSocketValueVector &value = *static_cast<const bNodeSocketValueVector *>(
socket.default_value);
if (value.dimensions != this->dimensions) {
return false;
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
if (value.min != this->soft_min_value) {
return false;
}
if (value.max != this->soft_max_value) {
return false;
}
return true;
}
bool Vector::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
if (socket.type == SOCK_ROTATION) {
return true;
}
return basic_types_can_connect(*this, socket);
}
bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_VECTOR) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
if (socket.typeinfo->subtype != this->subtype) {
modify_subtype_except_for_storage(socket, this->subtype, this->dimensions);
}
this->set_common_flags(socket);
bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value;
if (value.dimensions != this->dimensions) {
modify_subtype_except_for_storage(socket, this->subtype, this->dimensions);
}
value.subtype = this->subtype;
value.dimensions = this->dimensions;
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
value.min = this->soft_min_value;
value.max = this->soft_max_value;
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Bool
* \{ */
bNodeSocket &Bool::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_BOOLEAN,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueBoolean &value = *(bNodeSocketValueBoolean *)socket.default_value;
value.value = this->default_value;
return socket;
}
bool Bool::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_BOOLEAN) {
return false;
}
return true;
}
bool Bool::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
return basic_types_can_connect(*this, socket);
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
bNodeSocket &Bool::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_BOOLEAN) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Color
* \{ */
bNodeSocket &Color::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_RGBA,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueRGBA &value = *(bNodeSocketValueRGBA *)socket.default_value;
copy_v4_v4(value.value, this->default_value);
return socket;
}
bool Color::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_RGBA) {
return false;
}
return true;
}
bool Color::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
return basic_types_can_connect(*this, socket);
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
bNodeSocket &Color::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_RGBA) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Rotation
* \{ */
bNodeSocket &Rotation::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_ROTATION,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
bNodeSocketValueRotation &value = *static_cast<bNodeSocketValueRotation *>(socket.default_value);
copy_v3_v3(value.value_euler, float3(this->default_value));
return socket;
}
bool Rotation::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_ROTATION) {
return false;
}
return true;
}
bool Rotation::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
if (this->in_out == SOCK_IN) {
return ELEM(socket.type, SOCK_ROTATION, SOCK_FLOAT, SOCK_VECTOR, SOCK_MATRIX);
}
return ELEM(socket.type, SOCK_ROTATION, SOCK_VECTOR, SOCK_MATRIX);
}
bNodeSocket &Rotation::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_ROTATION) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Matrix
* \{ */
bNodeSocket &Matrix::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_MATRIX,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
return socket;
}
bool Matrix::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_MATRIX) {
return false;
}
return true;
}
bool Matrix::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
if (this->in_out == SOCK_IN) {
return ELEM(socket.type, SOCK_MATRIX, SOCK_FLOAT, SOCK_VECTOR, SOCK_MATRIX);
}
return ELEM(socket.type, SOCK_MATRIX, SOCK_VECTOR, SOCK_MATRIX);
}
bNodeSocket &Matrix::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_MATRIX) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
/** \} */
2021-10-05 11:10:25 +11:00
/* -------------------------------------------------------------------- */
/** \name #String
* \{ */
bNodeSocket &String::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_STRING,
this->subtype,
this->identifier.c_str(),
this->name.c_str());
STRNCPY(((bNodeSocketValueString *)socket.default_value)->value, this->default_value.c_str());
this->set_common_flags(socket);
return socket;
}
bool String::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_STRING) {
return false;
}
if (socket.typeinfo->subtype != this->subtype) {
return false;
}
return true;
}
bool String::can_connect(const bNodeSocket &socket) const
{
return sockets_can_connect(*this, socket) && socket.type == SOCK_STRING;
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
bNodeSocket &String::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_STRING) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
}
if (socket.typeinfo->subtype != this->subtype) {
modify_subtype_except_for_storage(socket, this->subtype);
}
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
this->set_common_flags(socket);
bNodeSocketValueString &value = *(bNodeSocketValueString *)socket.default_value;
value.subtype = this->subtype;
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
return socket;
}
StringBuilder &StringBuilder::path_filter(std::optional<std::string> filter)
{
BLI_assert(decl_->subtype == PROP_FILEPATH);
decl_->path_filter = std::move(filter);
return *this;
}
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Menu
* \{ */
bNodeSocket &Menu::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_MENU,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
((bNodeSocketValueMenu *)socket.default_value)->value = this->default_value.value;
Geometry Nodes: Menu Switch Node This patch adds support for _Menu Switch_ nodes and enum definitions in node trees more generally. The design is based on the outcome of the [2022 Nodes Workshop](https://code.blender.org/2022/11/geometry-nodes-workshop-2022/#menu-switch). The _Menu Switch_ node is an advanced version of the _Switch_ node which has a customizable **menu input socket** instead of a simple boolean. The _items_ of this menu are owned by the node itself. Each item has a name and description and unique identifier that is used internally. A menu _socket_ represents a concrete value out of the list of items. To enable selection of an enum value for unconnected sockets the menu is presented as a dropdown list like built-in enums. When the socket is connected a shared pointer to the enum definition is propagated along links and stored in socket default values. This allows node groups to expose a menu from an internal menu switch as a parameter. The enum definition is a runtime copy of the enum items in DNA that allows sharing. A menu socket can have multiple connections, which can lead to ambiguity. If two or more different menu source nodes are connected to a socket it gets marked as _undefined_. Any connection to an undefined menu socket is invalid as a hint to users that there is a problem. A warning/error is also shown on nodes with undefined menu sockets. At runtime the value of a menu socket is the simple integer identifier. This can also be a field in geometry nodes. The identifier is unique within each enum definition, and it is persistent even when items are added, removed, or changed. Changing the name of an item does not affect the internal identifier, so users can rename enum items without breaking existing input values. This also persists if, for example, a linked node group is temporarily unavailable. Pull Request: https://projects.blender.org/blender/blender/pulls/113445
2024-01-26 12:40:01 +01:00
this->set_common_flags(socket);
return socket;
}
bool Menu::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_MENU) {
return false;
}
return true;
}
bool Menu::can_connect(const bNodeSocket &socket) const
{
return sockets_can_connect(*this, socket) && socket.type == SOCK_MENU;
}
bNodeSocket &Menu::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_MENU) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
}
this->set_common_flags(socket);
return socket;
}
Nodes: initial support for built-in menu sockets So far, only node group were able to have menu input sockets. Built-in nodes did not support them. Currently, all menus of built-in nodes are stored on the node instead of on the sockets. This limits their flexibility because it's not possible to expose these inputs. This patch adds initial support for having menu inputs in built-in nodes. For testing purposes, it also changes a couple built-in nodes to use an input socket instead of a node property: Points to Volume, Transform Geometry, Triangulate, Volume to Mesh and Match String. ### Compatibility Forward and backward compatibility is maintained where possible (it's not possible when the menu input is linked in 5.0). The overall compatibility approach is the same as what was done for the compositor with two differences: there are no wrapper RNA properties (not necessary for 5.0, those were removed for the compositor already too), no need to version animation (animation on the menu properties was already disabled). This also makes menu sockets not animatable in general which is kind of brittle (e.g. doesn't properly update when the menu definition changes). To animate a menu it's better to animate an integer and to drive an index switch with it. ### Which nodes to update? Many existing menu properties can become sockets, but it's currently not the intention to convert all of them. In some cases, converting them might restrict future improvements too much. This mainly affects Math nodes. Other existing nodes should be updated but are a bit more tricky to update for different reasons: * We don't support dynamic output visibility yet. This is something I'll need to look into at some point. * They are shared with shader/compositor nodes, which may be more limited in what can become a socket. * There may be performance implications unless extra special cases are implemented, especially for multi-function nodes. * Some nodes use socket renaming instead of dynamic socket visibility which isn't something we support more generally yet. ### Implementation The core implementation is fairly straight forward. The heavy lifting is done by the existing socket visibility inferencing. There is a new simple API that allows individual nodes to implement custom input-usage-rules based on other inputs in a decentralized way. In most cases, the nodes to update just have a single menu, so there is a new node-declaration utility that links a socket to a specific value of the menu input. This internally handles the usage inferencing as well as making the socket available when using link-drag-search. In the modified nodes, I also had to explicitly set the "main input" now which is used when inserting the node in a link. The automatic behavior doesn't work currently when the first input is a menu. This is something we'll have to solve more generally at some point but is out of scope for this patch. Pull Request: https://projects.blender.org/blender/blender/pulls/140705
2025-07-16 08:31:59 +02:00
MenuBuilder &MenuBuilder::static_items(const EnumPropertyItem *items)
{
/* Using a global map ensures that the same runtime data is used for the same static items.
* This is necessary because otherwise each node would have a different (incompatible) menu
* definition. */
static Mutex mutex;
static Map<const EnumPropertyItem *, ImplicitSharingPtr<bke::RuntimeNodeEnumItems>>
items_by_enum_ptr;
std::lock_guard lock{mutex};
decl_->items = items_by_enum_ptr.lookup_or_add_cb(items, [&]() {
bke::RuntimeNodeEnumItems *runtime_items = new bke::RuntimeNodeEnumItems();
for (const EnumPropertyItem *item = items; item->identifier; item++) {
bke::RuntimeNodeEnumItem runtime_item;
runtime_item.name = item->name;
runtime_item.description = item->description;
runtime_item.identifier = item->value;
runtime_items->items.append(std::move(runtime_item));
}
return ImplicitSharingPtr<bke::RuntimeNodeEnumItems>(runtime_items);
});
return *this;
}
2021-10-05 11:10:25 +11:00
/** \} */
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
/* -------------------------------------------------------------------- */
/** \name #Bundle
* \{ */
bNodeSocket &Bundle::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_BUNDLE,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
return socket;
}
bool Bundle::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_BUNDLE) {
return false;
}
return true;
}
bool Bundle::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
return ELEM(socket.type, SOCK_BUNDLE);
}
bNodeSocket &Bundle::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_BUNDLE) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
BundleBuilder &BundleBuilder::pass_through_input_index(const std::optional<int> index)
{
BLI_assert(this->is_output());
decl_->pass_through_input_index = std::move(index);
return *this;
}
Geometry Nodes: add Closures and Bundles behind experimental feature flag This implements bundles and closures which are described in more detail in this blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/ tl;dr: * Bundles are containers that allow storing multiple socket values in a single value. Each value in the bundle is identified by a name. Bundles can be nested. * Closures are functions that are created with the Closure Zone and can be evaluated with the Evaluate Closure node. To use the patch, the `Bundle and Closure Nodes` experimental feature has to be enabled. This is necessary, because these features are not fully done yet and still need iterations to improve the workflow before they can be officially released. These iterations are easier to do in `main` than in a separate branch though. That's because this patch is quite large and somewhat prone to merge conflicts. Also other work we want to do, depends on this. This adds the following new nodes: * Combine Bundle: can pack multiple values into one. * Separate Bundle: extracts values from a bundle. * Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node. * Evaluate Closure: evaluates the passed in closure. Things that will be added soon after this lands: * Fields in bundles and closures. The way this is done changes with #134811, so I rather implement this once both are in `main`. * UI features for keeping sockets in sync (right now there are warnings only). One bigger issue is the limited support for lazyness. For example, all inputs of a Combine Bundle node will be evaluated, even if they are not all needed. The same is true for all captured values of a closure. This is a deeper limitation that needs to be resolved at some point. This will likely be done after an initial version of this patch is done. Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Closure
* \{ */
bNodeSocket &Closure::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_static_socket(ntree,
node,
this->in_out,
SOCK_CLOSURE,
PROP_NONE,
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
return socket;
}
bool Closure::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_CLOSURE) {
return false;
}
return true;
}
bool Closure::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
return ELEM(socket.type, SOCK_CLOSURE);
}
bNodeSocket &Closure::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_CLOSURE) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
/** \} */
2021-10-05 11:10:25 +11:00
/* -------------------------------------------------------------------- */
/** \name #IDSocketDeclaration
* \{ */
bNodeSocket &IDSocketDeclaration::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_socket(
ntree, node, this->in_out, this->idname, this->identifier.c_str(), this->name.c_str());
if (this->default_value_fn) {
ID *id = this->default_value_fn(node);
/* Assumes that all ID sockets like #bNodeSocketValueObject and #bNodeSocketValueImage have the
* ID pointer at the start of the struct. */
*static_cast<ID **>(socket.default_value) = id;
id_us_plus(id);
}
this->set_common_flags(socket);
return socket;
}
bool IDSocketDeclaration::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (!STREQ(socket.idname, this->idname)) {
return false;
}
return true;
}
bool IDSocketDeclaration::can_connect(const bNodeSocket &socket) const
{
return sockets_can_connect(*this, socket) && STREQ(socket.idname, this->idname);
}
bNodeSocket &IDSocketDeclaration::update_or_build(bNodeTree &ntree,
bNode &node,
bNodeSocket &socket) const
{
if (StringRef(socket.idname) != this->idname) {
BLI_assert(socket.in_out == this->in_out);
return this->build(ntree, node);
}
this->set_common_flags(socket);
return socket;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Geometry
* \{ */
bNodeSocket &Geometry::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_socket(ntree,
node,
this->in_out,
"NodeSocketGeometry",
this->identifier.c_str(),
this->name.c_str());
this->set_common_flags(socket);
return socket;
}
bool Geometry::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_GEOMETRY) {
return false;
}
return true;
}
bool Geometry::can_connect(const bNodeSocket &socket) const
{
return sockets_can_connect(*this, socket) && socket.type == SOCK_GEOMETRY;
}
Span<bke::GeometryComponent::Type> Geometry::supported_types() const
{
return supported_types_;
}
bool Geometry::only_realized_data() const
{
return only_realized_data_;
}
bool Geometry::only_instances() const
{
return only_instances_;
}
GeometryBuilder &GeometryBuilder::supported_type(bke::GeometryComponent::Type supported_type)
{
decl_->supported_types_ = {supported_type};
return *this;
}
GeometryBuilder &GeometryBuilder::supported_type(
blender::Vector<bke::GeometryComponent::Type> supported_types)
{
decl_->supported_types_ = supported_types;
return *this;
}
GeometryBuilder &GeometryBuilder::only_realized_data(bool value)
{
decl_->only_realized_data_ = value;
return *this;
}
GeometryBuilder &GeometryBuilder::only_instances(bool value)
{
decl_->only_instances_ = value;
return *this;
}
2021-10-05 11:10:25 +11:00
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Shader
* \{ */
bNodeSocket &Shader::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_socket(
ntree, node, this->in_out, "NodeSocketShader", this->identifier.c_str(), this->name.c_str());
this->set_common_flags(socket);
return socket;
}
bool Shader::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_SHADER) {
return false;
}
return true;
}
bool Shader::can_connect(const bNodeSocket &socket) const
{
if (!sockets_can_connect(*this, socket)) {
return false;
}
/* Basic types can convert to shaders, but not the other way around. */
if (this->in_out == SOCK_IN) {
return ELEM(
socket.type, SOCK_VECTOR, SOCK_RGBA, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_SHADER);
}
return socket.type == SOCK_SHADER;
}
/** \} */
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
/* -------------------------------------------------------------------- */
/** \name #Extend
* \{ */
bNodeSocket &Extend::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_socket(ntree,
node,
this->in_out,
"NodeSocketVirtual",
this->identifier.c_str(),
this->name.c_str());
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
return socket;
}
bool Extend::matches(const bNodeSocket &socket) const
{
if (socket.identifier != this->identifier) {
return false;
}
return true;
}
bool Extend::can_connect(const bNodeSocket & /*socket*/) const
{
return false;
}
bNodeSocket &Extend::update_or_build(bNodeTree & /*ntree*/,
bNode & /*node*/,
bNodeSocket &socket) const
{
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Custom
* \{ */
bNodeSocket &Custom::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *bke::node_add_socket(
ntree, node, this->in_out, idname_, this->identifier.c_str(), this->name.c_str());
Nodes: Panels integration with blend files and UI Part 3/3 of #109135, #110272 Switch to new node group interfaces and deprecate old DNA and API. This completes support for panels in node drawing and in node group interface declarations in particular. The new node group interface DNA and RNA code has been added in parts 1 and 2 (#110885, #110952) but has not be enabled yet. This commit completes the integration by * enabling the new RNA API * using the new API in UI * read/write new interfaces from blend files * add versioning for backward compatibility * add forward-compatible writing code to reconstruct old interfaces All places accessing node group interface declarations should now be using the new API. A runtime cache has been added that allows simple linear access to socket inputs and outputs even when a panel hierarchy is used. Old DNA has been deprecated and should only be accessed for versioning (inputs/outputs renamed to inputs_legacy/outputs_legacy to catch errors). Versioning code ensures both backward and forward compatibility of existing files. The API for old interfaces is removed. The new API is very similar but is defined on the `ntree.interface` instead of the `ntree` directly. Breaking change notifications and detailed instructions for migrating will be added. A python test has been added for the node group API functions. This includes new functionality such as creating panels and moving items between different levels. This patch does not yet contain panel representations in the modifier UI. This has been tested in a separate branch and will be added with a later PR (#108565). Pull Request: https://projects.blender.org/blender/blender/pulls/111348
2023-08-30 12:37:21 +02:00
if (this->init_socket_fn) {
this->init_socket_fn(node, socket, "interface");
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
return socket;
}
bool Custom::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_CUSTOM) {
return false;
}
if (socket.typeinfo->idname != idname_) {
return false;
}
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
return true;
}
bool Custom::can_connect(const bNodeSocket &socket) const
{
return sockets_can_connect(*this, socket) && STREQ(socket.idname, idname_);
}
bNodeSocket &Custom::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
{
if (socket.typeinfo->idname != idname_) {
return this->build(ntree, node);
}
this->set_common_flags(socket);
Nodes: Use dynamic declarations for group nodes Since a year and a half ago we've been switching to a new way to represent what sockets a node should have called "declarations" that's easier to use, clearer, and more flexible for upcoming features like dynamic socket counts or generic type sockets. All builtin nodes with a static set of sockets have switched, but one missing area has been group nodes and group input/output nodes. These nodes have **dynamic** declarations which change based on their properties or the group they're inside of. This patch addresses that, in preparation for using the same dynamic declaration feature for simulation nodes. Generally there shouldn't be user-visible differences, but one benefit is that user-created socket descriptions are now visible directly in the node editor for group nodes and group input/output nodes. The commit contains a few changes: - Add a node type callback for building dynamic declarations with different arguments - Add an `Extend` socket declaration for the "virtual" sockets used for connecting new links - A similar `Custom` socket declaration is used for addon-defined socket - Simplify the node update loop to use the declaration to build update sockets - Replace the "group update" functions with the declaration building - Move the node group input/output link creation to link drag operator - Make the field status part of group node declarations (not for group input/output nodes though) - Some fixes for declarations to make them update and build properly Differential Revision: https://developer.blender.org/D16850
2023-01-16 15:47:10 -06:00
return socket;
}
/** \} */
} // namespace blender::nodes::decl