Compare commits

...

47 Commits

Author SHA1 Message Date
ea2db47a0b Use null for root tree for node tree change propagation 2023-01-10 16:49:57 -05:00
eaa17cfae2 Merge branch 'master' into temp-nodes-group-declarations 2023-01-10 16:41:44 -05:00
082449b737 Add missing tag for socket declaration node sockets update 2023-01-09 23:22:59 -05:00
b1bbd33ed6 Merge branch 'master' into temp-nodes-group-declarations 2023-01-09 17:48:39 -05:00
96609ade04 Merge branch 'master' into temp-nodes-group-declarations 2023-01-09 16:35:40 -05:00
844b3ed472 Fix various issues in socket declaration updating/building/comparison 2023-01-02 16:06:54 -05:00
392f4481a7 Remove redundant node declaration allocation 2023-01-02 16:06:37 -05:00
612c0ae3c8 Correct flag used for compact sockets 2023-01-02 14:57:32 -05:00
1847b63d27 Fix crash when creating a group 2023-01-02 14:54:04 -05:00
dd32b8fc97 Merge branch 'master' into temp-nodes-group-declarations 2023-01-02 14:03:24 -05:00
06b5ceb0c4 Fixes to group creation 2022-12-29 16:31:19 -05:00
ef89ba2b34 Merge branch 'master' into temp-nodes-group-declarations 2022-12-29 15:40:18 -05:00
399fc4af2a Merge branch 'master' into temp-nodes-group-declarations 2022-12-29 14:12:26 -05:00
92a16d0193 Merge branch 'master' into temp-nodes-group-declarations 2022-12-29 13:30:23 -05:00
e76e8fe87a Various cleanups, making the diff smaller 2022-12-27 16:40:58 -05:00
0c87d9b8f7 Merge branch 'master' into temp-nodes-group-declarations 2022-12-27 12:04:36 -05:00
d5b2979ad5 Cleanup: Fix typos 2022-12-27 10:52:44 -05:00
b60fc1c4c8 Merge branch 'master' into temp-nodes-group-declarations 2022-12-27 10:50:26 -05:00
4052267be7 Copy over "collapsed" flag 2022-12-22 16:01:24 -05:00
60210762e0 Handle property subtypes 2022-12-22 15:58:25 -05:00
13d984cfaa Add "Custom" socket declaration
I didn't test this yet
2022-12-22 15:18:07 -05:00
195a271bab Add more early return checks to geometry node group declaration 2022-12-22 15:04:27 -05:00
ddee26288d Simplify declaration functions for "extend" socket 2022-12-22 14:42:33 -05:00
af5a9b5748 Improve comments in various places 2022-12-22 14:42:17 -05:00
109f18df71 Fix clang format differences 2022-12-22 14:41:44 -05:00
450693ea6b Make function static again 2022-12-22 14:41:31 -05:00
f06635bfde Improve comment for dynamic declaration callback 2022-12-22 14:41:16 -05:00
21a8d7c69b Fix shader socket declaration
Copy and paste error. All tests pass now
2022-12-22 14:39:53 -05:00
1ffe27c438 Fix updating of input and output nodes when creating group 2022-12-22 11:51:20 -05:00
86b9b61371 Merge branch 'master' into temp-nodes-group-declarations 2022-12-22 10:42:37 -05:00
a2992774ac Only rebuild declaration when it is dynamic 2022-12-21 13:00:04 -06:00
cc57344527 Merge branch 'master' into temp-nodes-group-declarations 2022-12-21 12:58:57 -06:00
e4139476bf Merge branch 'master' into temp-nodes-group-declarations 2022-12-20 14:50:24 -06:00
80a3bed01a Don't connect between two extend sockets 2022-12-19 21:10:15 -06:00
439761d15c Remove theoretically unnecessary optimization 2022-12-19 20:51:57 -06:00
7b4dcec3ec Various fixes 2022-12-19 16:59:55 -06:00
f4d52d060b Merge branch 'master' into temp-nodes-group-declarations 2022-12-19 16:02:50 -06:00
a90642816c Some progress 2022-12-16 16:42:19 -06:00
8a27da7b3b Merge branch 'master' into temp-nodes-group-declarations 2022-12-16 14:50:08 -06:00
c174184385 Merge branch 'master' into temp-nodes-group-declarations 2022-12-16 11:32:09 -06:00
660e240acf Basic startup works 2022-12-15 17:43:08 -06:00
f509bd37b1 Fix build errors 2022-12-15 17:18:34 -06:00
542bff5e94 Declarations for group input and output nodes 2022-12-15 16:44:08 -06:00
d82166833a Merge branch 'master' into temp-nodes-group-declarations 2022-12-15 16:22:26 -06:00
64297ec8ad Cleanup 2022-12-15 16:17:16 -06:00
510155ed5c Merge branch 'master' into temp-nodes-group-declarations 2022-12-15 15:06:34 -06:00
59b1eb145d Start of refactoring to use declaration for group nodes 2022-12-14 18:42:04 -06:00
22 changed files with 510 additions and 370 deletions

View File

@@ -104,6 +104,7 @@ namespace nodes {
class DNode;
class NodeMultiFunctionBuilder;
class GeoNodeExecParams;
class NodeDeclaration;
class NodeDeclarationBuilder;
class GatherLinkSearchOpParams;
} // namespace nodes
@@ -118,6 +119,9 @@ using CPPTypeHandle = blender::CPPType;
using NodeMultiFunctionBuildFunction = void (*)(blender::nodes::NodeMultiFunctionBuilder &builder);
using NodeGeometryExecFunction = void (*)(blender::nodes::GeoNodeExecParams params);
using NodeDeclareFunction = void (*)(blender::nodes::NodeDeclarationBuilder &builder);
using NodeDeclareDynamicFunction = void (*)(const bNodeTree &tree,
const bNode &node,
blender::nodes::NodeDeclaration &r_declaration);
using SocketGetCPPValueFunction = void (*)(const struct bNodeSocket &socket, void *r_value);
using SocketGetGeometryNodesCPPValueFunction = void (*)(const struct bNodeSocket &socket,
void *r_value);
@@ -137,6 +141,7 @@ typedef void *NodeGetCompositorShaderNodeFunction;
typedef void *NodeMultiFunctionBuildFunction;
typedef void *NodeGeometryExecFunction;
typedef void *NodeDeclareFunction;
typedef void *NodeDeclareDynamicFunction;
typedef void *NodeGatherSocketLinkOperationsFunction;
typedef void *SocketGetCPPTypeFunction;
typedef void *SocketGetGeometryNodesCPPTypeFunction;
@@ -173,11 +178,6 @@ typedef struct bNodeSocketType {
struct bNode *node,
struct bNodeSocket *sock,
const char *data_path);
void (*interface_verify_socket)(struct bNodeTree *ntree,
const struct bNodeSocket *interface_socket,
struct bNode *node,
struct bNodeSocket *sock,
const char *data_path);
void (*interface_from_socket)(struct bNodeTree *ntree,
struct bNodeSocket *interface_socket,
const struct bNode *node,
@@ -306,8 +306,8 @@ typedef struct bNodeType {
const struct bNodeTree *nodetree,
const char **r_disabled_hint);
/* optional handling of link insertion */
void (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
/* optional handling of link insertion. Returns false if the link shouldn't be created. */
bool (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
void (*free_self)(struct bNodeType *ntype);
@@ -344,8 +344,13 @@ typedef struct bNodeType {
/* Declares which sockets the node has. */
NodeDeclareFunction declare;
/* Different nodes of this type can have different declarations. */
bool declaration_is_dynamic;
/**
* Declare which sockets the node has for declarations that aren't static per node type.
* In other words, defining this callback means that different nodes of this type can have
* different declarations and different sockets.
*/
NodeDeclareDynamicFunction declare_dynamic;
/* Declaration to be used when it is not dynamic. */
NodeDeclarationHandle *fixed_declaration;

View File

@@ -1378,7 +1378,7 @@ void nodeRegisterType(bNodeType *nt)
BLI_assert(nt->idname[0] != '\0');
BLI_assert(nt->poll != nullptr);
if (nt->declare && !nt->declaration_is_dynamic) {
if (nt->declare && !nt->declare_dynamic) {
if (nt->fixed_declaration == nullptr) {
nt->fixed_declaration = new blender::nodes::NodeDeclaration();
blender::nodes::build_node_declaration(*nt, *nt->fixed_declaration);
@@ -2990,7 +2990,7 @@ void node_free_node(bNodeTree *ntree, bNode *node)
MEM_freeN(node->prop);
}
if (node->typeinfo->declaration_is_dynamic) {
if (node->typeinfo->declare_dynamic) {
delete node->runtime->declaration;
}
@@ -3602,7 +3602,7 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree * /*ntree*/, bNode *node)
if (node->typeinfo->declare == nullptr) {
return false;
}
if (node->typeinfo->declaration_is_dynamic) {
if (node->typeinfo->declare_dynamic) {
node->runtime->declaration = new blender::nodes::NodeDeclaration();
blender::nodes::build_node_declaration(*node->typeinfo, *node->runtime->declaration);
}

View File

@@ -22,6 +22,7 @@
#include "MOD_nodes.h"
#include "NOD_node_declaration.hh"
#include "NOD_socket.h"
#include "NOD_texture.h"
#include "DEG_depsgraph_query.h"
@@ -538,7 +539,6 @@ class NodeTreeMainUpdater {
void update_individual_nodes(bNodeTree &ntree)
{
Vector<bNode *> group_inout_nodes;
for (bNode *node : ntree.all_nodes()) {
nodeDeclarationEnsure(&ntree, node);
if (this->should_update_individual_node(ntree, *node)) {
@@ -549,18 +549,9 @@ class NodeTreeMainUpdater {
if (ntype.updatefunc) {
ntype.updatefunc(&ntree, node);
}
}
if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
group_inout_nodes.append(node);
}
}
/* The update function of group input/output nodes may add new interface sockets. When that
* happens, all the input/output nodes have to be updated again. In the future it would be
* better to move this functionality out of the node update function into the operator that's
* supposed to create the new interface socket. */
if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE) {
for (bNode *node : group_inout_nodes) {
node->typeinfo->updatefunc(&ntree, node);
if (ntype.declare_dynamic) {
nodes::update_node_declaration_and_sockets(ntree, *node);
}
}
}
}
@@ -575,22 +566,8 @@ class NodeTreeMainUpdater {
}
if (ntree.runtime->changed_flag & NTREE_CHANGED_LINK) {
ntree.ensure_topology_cache();
/* Node groups currently always rebuilt their sockets when they are updated.
* So avoid calling the update method when no new link was added to it. */
if (node.type == NODE_GROUP_INPUT) {
if (node.output_sockets().last()->is_directly_linked()) {
return true;
}
}
else if (node.type == NODE_GROUP_OUTPUT) {
if (node.input_sockets().last()->is_directly_linked()) {
return true;
}
}
else {
/* Currently we have no way to tell if a node needs to be updated when a link changed. */
return true;
}
/* Currently we have no way to tell if a node needs to be updated when a link changed. */
return true;
}
if (ntree.runtime->changed_flag & NTREE_CHANGED_INTERFACE) {
if (ELEM(node.type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {

View File

@@ -13,6 +13,7 @@
#include "BKE_node_tree_update.h"
#include "BKE_screen.h"
#include "NOD_socket.h"
#include "NOD_socket_search_link.hh"
#include "BLT_translation.h"
@@ -198,7 +199,7 @@ static void search_link_ops_for_asset_metadata(const bNodeTree &node_tree,
DEG_relations_tag_update(&bmain);
/* Create the inputs and outputs on the new node. */
node.typeinfo->group_update_func(&params.node_tree, &node);
nodes::update_node_declaration_and_sockets(params.node_tree, node);
bNodeSocket *new_node_socket = bke::node_find_enabled_socket(
node, in_out, socket_property->name);

View File

@@ -933,9 +933,9 @@ static void node_group_make_insert_selected(const bContext &C,
}
nodeRebuildIDVector(&ntree);
node_group_update(&ntree, gnode);
node_group_input_update(&group, input_node);
node_group_output_update(&group, output_node);
/* Update input and output node first, since the group node declaration can depend on them. */
nodes::update_node_declaration_and_sockets(group, *input_node);
nodes::update_node_declaration_and_sockets(group, *output_node);
/* move nodes in the group to the center */
for (bNode *node : nodes_to_move) {
@@ -956,6 +956,7 @@ static void node_group_make_insert_selected(const bContext &C,
nodeRemLink(&ntree, link);
}
/* Handle links to the new group inputs. */
for (const auto item : input_links.items()) {
const char *interface_identifier = item.value.interface_socket->identifier;
bNodeSocket *input_socket = node_group_input_find_socket(input_node, interface_identifier);
@@ -969,23 +970,17 @@ static void node_group_make_insert_selected(const bContext &C,
link->fromnode = input_node;
link->fromsock = input_socket;
}
/* Add a new link outside of the group. */
bNodeSocket *group_node_socket = node_group_find_input_socket(gnode, interface_identifier);
nodeAddLink(&ntree, item.value.from_node, item.key, gnode, group_node_socket);
}
/* Handle links to new group outputs. */
for (const OutputLinkInfo &info : output_links) {
/* Create a new link inside of the group. */
const char *io_identifier = info.interface_socket->identifier;
bNodeSocket *output_sock = node_group_output_find_socket(output_node, io_identifier);
nodeAddLink(&group, info.link->fromnode, info.link->fromsock, output_node, output_sock);
/* Reconnect the link to the group node instead of the node now inside the group. */
info.link->fromnode = gnode;
info.link->fromsock = node_group_find_output_socket(gnode, io_identifier);
}
/* Handle new links inside the group. */
for (const NewInternalLinkInfo &info : new_internal_links) {
const char *io_identifier = info.interface_socket->identifier;
if (info.socket->in_out == SOCK_IN) {
@@ -997,6 +992,25 @@ static void node_group_make_insert_selected(const bContext &C,
nodeAddLink(&group, info.node, info.socket, output_node, output_socket);
}
}
bke::node_field_inferencing::update_field_inferencing(group);
nodes::update_node_declaration_and_sockets(ntree, *gnode);
/* Add new links to inputs outside of the group. */
for (const auto item : input_links.items()) {
const char *interface_identifier = item.value.interface_socket->identifier;
bNodeSocket *group_node_socket = node_group_find_input_socket(gnode, interface_identifier);
nodeAddLink(&ntree, item.value.from_node, item.key, gnode, group_node_socket);
}
/* Add new links to outputs outside the group. */
for (const OutputLinkInfo &info : output_links) {
/* Reconnect the link to the group node instead of the node now inside the group. */
info.link->fromnode = gnode;
info.link->fromsock = node_group_find_output_socket(gnode, info.interface_socket->identifier);
}
ED_node_tree_propagate_change(&C, bmain, nullptr);
}
static bNode *node_group_make_from_nodes(const bContext &C,
@@ -1051,8 +1065,6 @@ static int node_group_make_exec(bContext *C, wmOperator *op)
}
}
ED_node_tree_propagate_change(C, bmain, nullptr);
WM_event_add_notifier(C, NC_NODE | NA_ADDED, nullptr);
/* We broke relations in node tree, need to rebuild them in the graphs. */
@@ -1105,7 +1117,6 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
const char *node_idname = node_group_idname(C);
Main *bmain = CTX_data_main(C);
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
@@ -1137,7 +1148,6 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
nodeSetActive(ntree, gnode);
ED_node_tree_push(snode, ngroup, gnode);
ED_node_tree_propagate_change(C, bmain, nullptr);
return OPERATOR_FINISHED;
}

View File

@@ -902,10 +902,14 @@ static void add_dragged_links_to_tree(bContext &C, bNodeLinkDrag &nldrag)
/* Before actually adding the link let nodes perform special link insertion handling. */
bNodeLink *new_link = MEM_new<bNodeLink>(__func__, link);
if (link.fromnode->typeinfo->insert_link) {
link.fromnode->typeinfo->insert_link(&ntree, link.fromnode, new_link);
if (!link.fromnode->typeinfo->insert_link(&ntree, link.fromnode, new_link)) {
continue;
}
}
if (link.tonode->typeinfo->insert_link) {
link.tonode->typeinfo->insert_link(&ntree, link.tonode, new_link);
if (!link.tonode->typeinfo->insert_link(&ntree, link.tonode, new_link)) {
continue;
}
}
/* Add link to the node tree. */

View File

@@ -1738,7 +1738,7 @@ static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
RNA_parameter_list_free(&list);
}
static void rna_Node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static bool rna_Node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
{
extern FunctionRNA rna_Node_insert_link_func;
@@ -1754,6 +1754,7 @@ static void rna_Node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
node->typeinfo->rna_ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
return true;
}
static void rna_Node_init(const bContext *C, PointerRNA *ptr)
@@ -3386,9 +3387,6 @@ static StructRNA *rna_NodeCustomGroup_register(Main *bmain,
return NULL;
}
/* this updates the group node instance from the tree's interface */
nt->group_update_func = node_group_update;
nodeRegisterType(nt);
/* update while blender is running */
@@ -3412,7 +3410,6 @@ static StructRNA *rna_GeometryNodeCustomGroup_register(Main *bmain,
return NULL;
}
nt->group_update_func = node_group_update;
nt->type = NODE_CUSTOM_GROUP;
register_node_type_geo_custom_group(nt);
@@ -3441,7 +3438,6 @@ static StructRNA *rna_ShaderNodeCustomGroup_register(Main *bmain,
return NULL;
}
nt->group_update_func = node_group_update;
nt->type = NODE_CUSTOM_GROUP;
register_node_type_sh_custom_group(nt);
@@ -3467,7 +3463,6 @@ static StructRNA *rna_CompositorNodeCustomGroup_register(Main *bmain,
return NULL;
}
nt->group_update_func = node_group_update;
nt->type = NODE_CUSTOM_GROUP;
register_node_type_cmp_custom_group(nt);

View File

@@ -17,16 +17,24 @@ extern "C" {
struct bNodeSocket *node_group_find_input_socket(struct bNode *groupnode, const char *identifier);
struct bNodeSocket *node_group_find_output_socket(struct bNode *groupnode, const char *identifier);
/** Make sure all group node in ntree, which use ngroup, are sync'd. */
void node_group_update(struct bNodeTree *ntree, struct bNode *node);
struct bNodeSocket *node_group_input_find_socket(struct bNode *node, const char *identifier);
struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char *identifier);
void node_group_input_update(struct bNodeTree *ntree, struct bNode *node);
void node_group_output_update(struct bNodeTree *ntree, struct bNode *node);
void node_internal_links_create(struct bNodeTree *ntree, struct bNode *node);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace blender::nodes {
void node_group_declare_dynamic(const bNodeTree &node_tree,
const bNode &node,
NodeDeclaration &r_declaration);
} // namespace blender::nodes
#endif

View File

@@ -160,6 +160,7 @@ class SocketDeclaration {
InputSocketFieldType input_field_type = InputSocketFieldType::None;
OutputFieldDependency output_field_dependency;
private:
/** The priority of the input for determining the domain of the node. See
* realtime_compositor::InputDescriptor for more information. */
int compositor_domain_priority_ = 0;
@@ -461,6 +462,11 @@ class NodeDeclaration {
Vector<SocketDeclarationPtr> outputs;
std::unique_ptr<aal::RelationsInNode> anonymous_attribute_relations_;
/** Leave the sockets in place, even if they don't match the declaration. Used for dynamic
* declarations when the information used to build the declaration is missing, but might become
* available again in the future. */
bool skip_updating_sockets = false;
friend NodeDeclarationBuilder;
bool matches(const bNode &node) const;
@@ -523,6 +529,9 @@ void id_or_index(const bNode &node, void *r_value);
} // namespace implicit_field_inputs
void build_node_declaration(const bNodeType &typeinfo, NodeDeclaration &r_declaration);
void build_node_declaration_dynamic(const bNodeTree &node_tree,
const bNode &node,
NodeDeclaration &r_declaration);
template<typename SocketDecl>
typename SocketDeclarationBuilder<SocketDecl>::Self &SocketDeclarationBuilder<

View File

@@ -36,3 +36,13 @@ void register_standard_node_socket_types(void);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace blender::nodes {
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node);
} // namespace blender::nodes
#endif

View File

@@ -104,6 +104,7 @@ class Bool : public SocketDeclaration {
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
bool matches(const bNodeSocket &socket) const override;
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
bool can_connect(const bNodeSocket &socket) const override;
};
@@ -124,6 +125,7 @@ class Color : public SocketDeclaration {
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
bool matches(const bNodeSocket &socket) const override;
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
bool can_connect(const bNodeSocket &socket) const override;
};
@@ -144,6 +146,7 @@ class String : public SocketDeclaration {
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
bool matches(const bNodeSocket &socket) const override;
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
bool can_connect(const bNodeSocket &socket) const override;
};
@@ -216,6 +219,34 @@ class Shader : public SocketDeclaration {
class ShaderBuilder : public SocketDeclarationBuilder<Shader> {
};
class ExtendBuilder;
class Extend : public SocketDeclaration {
private:
friend ExtendBuilder;
public:
using Builder = ExtendBuilder;
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
bool matches(const bNodeSocket &socket) const override;
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
bool can_connect(const bNodeSocket &socket) const override;
};
class ExtendBuilder : public SocketDeclarationBuilder<Extend> {
};
class Custom : public SocketDeclaration {
public:
const char *idname_;
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
bool matches(const bNodeSocket &socket) const override;
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
bool can_connect(const bNodeSocket &socket) const override;
};
/* -------------------------------------------------------------------- */
/** \name #FloatBuilder Inline Methods
* \{ */

View File

@@ -32,7 +32,7 @@ void register_node_type_cmp_group()
node_type_size(&ntype, 140, 60, 400);
ntype.labelfunc = node_group_label;
ntype.group_update_func = node_group_update;
ntype.declare_dynamic = blender::nodes::node_group_declare_dynamic;
nodeRegisterType(&ntype);
}

View File

@@ -3,11 +3,41 @@
#include "BKE_node.h"
#include "NOD_geometry.h"
#include "NOD_node_declaration.hh"
#include "NOD_common.h"
#include "node_common.h"
#include "node_geometry_util.hh"
namespace blender::nodes {
static void node_declare(const bNodeTree &node_tree,
const bNode &node,
NodeDeclaration &r_declaration)
{
const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id);
if (!group) {
return;
}
node_group_declare_dynamic(node_tree, node, r_declaration);
if (!node.id) {
return;
}
if (ID_IS_LINKED(&group->id) && (group->id.tag & LIB_TAG_MISSING)) {
return;
}
const FieldInferencingInterface &field_interface = *group->runtime->field_inferencing_interface;
for (const int i : r_declaration.inputs.index_range()) {
r_declaration.inputs[i]->input_field_type = field_interface.inputs[i];
}
for (const int i : r_declaration.outputs.index_range()) {
r_declaration.outputs[i]->output_field_dependency = field_interface.outputs[i];
}
}
} // namespace blender::nodes
void register_node_type_geo_group()
{
static bNodeType ntype;
@@ -23,7 +53,7 @@ void register_node_type_geo_group()
node_type_size(&ntype, 140, 60, 400);
ntype.labelfunc = node_group_label;
ntype.group_update_func = node_group_update;
ntype.declare_dynamic = blender::nodes::node_declare;
nodeRegisterType(&ntype);
}

View File

@@ -30,7 +30,11 @@
#include "MEM_guardedalloc.h"
#include "NOD_common.h"
#include "NOD_node_declaration.hh"
#include "NOD_register.hh"
#include "NOD_socket.h"
#include "NOD_socket_declarations.hh"
#include "NOD_socket_declarations_geometry.hh"
#include "node_common.h"
#include "node_util.h"
@@ -120,124 +124,124 @@ bool nodeGroupPoll(const bNodeTree *nodetree,
return true;
}
static void add_new_socket_from_interface(bNodeTree &node_tree,
bNode &node,
const bNodeSocket &interface_socket,
const eNodeSocketInOut in_out)
{
bNodeSocket *socket = nodeAddSocket(&node_tree,
&node,
in_out,
interface_socket.idname,
interface_socket.identifier,
interface_socket.name);
namespace blender::nodes {
if (interface_socket.typeinfo->interface_init_socket) {
interface_socket.typeinfo->interface_init_socket(
&node_tree, &interface_socket, &node, socket, "interface");
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &io_socket)
{
SocketDeclarationPtr dst;
switch (io_socket.type) {
case SOCK_FLOAT: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueFloat>();
std::unique_ptr<decl::Float> decl = std::make_unique<decl::Float>();
decl->subtype = PropertySubType(io_socket.typeinfo->subtype);
decl->default_value = value.value;
decl->soft_min_value = value.min;
decl->soft_max_value = value.max;
dst = std::move(decl);
break;
}
case SOCK_VECTOR: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueVector>();
std::unique_ptr<decl::Vector> decl = std::make_unique<decl::Vector>();
decl->subtype = PropertySubType(io_socket.typeinfo->subtype);
decl->default_value = value.value;
decl->soft_min_value = value.min;
decl->soft_max_value = value.max;
dst = std::move(decl);
break;
}
case SOCK_RGBA: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueRGBA>();
std::unique_ptr<decl::Color> decl = std::make_unique<decl::Color>();
decl->default_value = value.value;
dst = std::move(decl);
break;
}
case SOCK_SHADER: {
std::unique_ptr<decl::Shader> decl = std::make_unique<decl::Shader>();
dst = std::move(decl);
break;
}
case SOCK_BOOLEAN: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueBoolean>();
std::unique_ptr<decl::Bool> decl = std::make_unique<decl::Bool>();
decl->default_value = value.value;
dst = std::move(decl);
break;
}
case SOCK_INT: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueInt>();
std::unique_ptr<decl::Int> decl = std::make_unique<decl::Int>();
decl->subtype = PropertySubType(io_socket.typeinfo->subtype);
decl->default_value = value.value;
decl->soft_min_value = value.min;
decl->soft_max_value = value.max;
dst = std::move(decl);
break;
}
case SOCK_STRING: {
const auto &value = *io_socket.default_value_typed<bNodeSocketValueString>();
std::unique_ptr<decl::String> decl = std::make_unique<decl::String>();
decl->default_value = value.value;
dst = std::move(decl);
break;
}
case SOCK_OBJECT:
dst = std::make_unique<decl::Object>();
break;
case SOCK_IMAGE:
dst = std::make_unique<decl::Image>();
break;
case SOCK_GEOMETRY:
dst = std::make_unique<decl::Geometry>();
break;
case SOCK_COLLECTION:
dst = std::make_unique<decl::Collection>();
break;
case SOCK_TEXTURE:
dst = std::make_unique<decl::Texture>();
break;
case SOCK_MATERIAL:
dst = std::make_unique<decl::Material>();
break;
case SOCK_CUSTOM:
std::unique_ptr<decl::Custom> decl = std::make_unique<decl::Custom>();
decl->idname_ = io_socket.idname;
dst = std::move(decl);
break;
}
dst->name = io_socket.name;
dst->identifier = io_socket.identifier;
dst->in_out = eNodeSocketInOut(io_socket.in_out);
dst->description = io_socket.description;
dst->hide_value = io_socket.flag & SOCK_HIDE_VALUE;
dst->compact = io_socket.flag & SOCK_COMPACT;
return dst;
}
void node_group_declare_dynamic(const bNodeTree & /*node_tree*/,
const bNode &node,
NodeDeclaration &r_declaration)
{
const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id);
if (!group) {
return;
}
if (ID_IS_LINKED(&group->id) && (group->id.tag & LIB_TAG_MISSING)) {
r_declaration.skip_updating_sockets = true;
return;
}
r_declaration.skip_updating_sockets = false;
LISTBASE_FOREACH (const bNodeSocket *, input, &group->inputs) {
r_declaration.inputs.append(declaration_for_interface_socket(*input));
}
LISTBASE_FOREACH (const bNodeSocket *, output, &group->outputs) {
r_declaration.outputs.append(declaration_for_interface_socket(*output));
}
}
static void update_socket_to_match_interface(bNodeTree &node_tree,
bNode &node,
bNodeSocket &socket_to_update,
const bNodeSocket &interface_socket)
{
strcpy(socket_to_update.name, interface_socket.name);
const int mask = SOCK_HIDE_VALUE;
socket_to_update.flag = (socket_to_update.flag & ~mask) | (interface_socket.flag & mask);
/* Update socket type if necessary */
if (socket_to_update.typeinfo != interface_socket.typeinfo) {
nodeModifySocketType(&node_tree, &node, &socket_to_update, interface_socket.idname);
}
if (interface_socket.typeinfo->interface_verify_socket) {
interface_socket.typeinfo->interface_verify_socket(
&node_tree, &interface_socket, &node, &socket_to_update, "interface");
}
}
/**
* Used for group nodes and group input/output nodes to update the list of input or output sockets
* on a node to match the provided interface. Assumes that \a verify_lb is the node's matching
* input or output socket list, depending on whether the node is a group input/output or a group
* node.
*/
static void group_verify_socket_list(bNodeTree &node_tree,
bNode &node,
const ListBase &interface_sockets,
ListBase &verify_lb,
const eNodeSocketInOut in_out,
const bool ensure_extend_socket_exists)
{
ListBase old_sockets = verify_lb;
Vector<bNodeSocket *> ordered_old_sockets = old_sockets;
BLI_listbase_clear(&verify_lb);
LISTBASE_FOREACH (const bNodeSocket *, interface_socket, &interface_sockets) {
bNodeSocket *matching_socket = find_matching_socket(old_sockets, interface_socket->identifier);
if (matching_socket) {
/* If a socket with the same identifier exists in the previous socket list, update it
* with the correct name, type, etc. Then move it from the old list to the new one. */
update_socket_to_match_interface(node_tree, node, *matching_socket, *interface_socket);
BLI_remlink(&old_sockets, matching_socket);
BLI_addtail(&verify_lb, matching_socket);
}
else {
/* If there was no socket with the same identifier already, simply create a new socket
* based on the interface socket, which will already add it to the new list. */
add_new_socket_from_interface(node_tree, node, *interface_socket, in_out);
}
}
if (ensure_extend_socket_exists) {
bNodeSocket *last_socket = static_cast<bNodeSocket *>(old_sockets.last);
if (last_socket != nullptr && STREQ(last_socket->identifier, "__extend__")) {
BLI_remlink(&old_sockets, last_socket);
BLI_addtail(&verify_lb, last_socket);
}
else {
nodeAddSocket(&node_tree, &node, in_out, "NodeSocketVirtual", "__extend__", "");
}
}
/* Remove leftover sockets that didn't match the node group's interface. */
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, unused_socket, &old_sockets) {
nodeRemoveSocket(&node_tree, &node, unused_socket);
}
{
/* Check if new sockets match the old sockets. */
int index;
LISTBASE_FOREACH_INDEX (bNodeSocket *, new_socket, &verify_lb, index) {
if (index < ordered_old_sockets.size()) {
if (ordered_old_sockets[index] != new_socket) {
BKE_ntree_update_tag_interface(&node_tree);
break;
}
}
}
}
}
void node_group_update(struct bNodeTree *ntree, struct bNode *node)
{
/* check inputs and outputs, and remove or insert them */
if (node->id == nullptr) {
nodeRemoveAllSockets(ntree, node);
}
else if (ID_IS_LINKED(node->id) && (node->id->tag & LIB_TAG_MISSING)) {
/* Missing data-block, leave sockets unchanged so that when it comes back
* the links remain valid. */
}
else {
bNodeTree *ngroup = (bNodeTree *)node->id;
group_verify_socket_list(*ntree, *node, ngroup->inputs, node->inputs, SOCK_IN, false);
group_verify_socket_list(*ntree, *node, ngroup->outputs, node->outputs, SOCK_OUT, false);
}
}
} // namespace blender::nodes
/** \} */
@@ -419,16 +423,6 @@ bool BKE_node_is_connected_to_output(const bNodeTree *ntree, const bNode *node)
/** \name Node #GROUP_INPUT / #GROUP_OUTPUT
* \{ */
static bool is_group_extension_socket(const bNode *node, const bNodeSocket *socket)
{
return socket->type == SOCK_CUSTOM && ELEM(node->type, NODE_GROUP_OUTPUT, NODE_GROUP_INPUT);
}
static void node_group_input_init(bNodeTree *ntree, bNode *node)
{
node_group_input_update(ntree, node);
}
bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
{
bNodeSocket *sock;
@@ -440,59 +434,83 @@ bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
return nullptr;
}
void node_group_input_update(bNodeTree *ntree, bNode *node)
namespace blender::nodes {
static SocketDeclarationPtr extend_declaration(const eNodeSocketInOut in_out)
{
bNodeSocket *extsock = (bNodeSocket *)node->outputs.last;
/* Adding a tree socket and verifying will remove the extension socket!
* This list caches the existing links from the extension socket
* so they can be recreated after verification. */
Vector<bNodeLink> temp_links;
/* find links from the extension socket and store them */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (nodeLinkIsHidden(link)) {
continue;
}
if (link->fromsock == extsock) {
temp_links.append(*link);
nodeRemLink(ntree, link);
}
}
/* find valid link to expose */
bNodeLink *exposelink = nullptr;
for (bNodeLink &link : temp_links) {
/* XXX Multiple sockets can be connected to the extension socket at once,
* in that case the arbitrary first link determines name and type.
* This could be improved by choosing the "best" type among all links,
* whatever that means.
*/
if (!is_group_extension_socket(link.tonode, link.tosock)) {
exposelink = &link;
break;
}
}
if (exposelink) {
bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(
ntree, exposelink->tonode, exposelink->tosock);
node_group_input_update(ntree, node);
bNodeSocket *newsock = node_group_input_find_socket(node, gsock->identifier);
/* redirect links from the extension socket */
for (bNodeLink &link : temp_links) {
bNodeLink *newlink = nodeAddLink(ntree, node, newsock, link.tonode, link.tosock);
if (newlink->tosock->flag & SOCK_MULTI_INPUT) {
newlink->multi_input_socket_index = link.multi_input_socket_index;
}
}
}
group_verify_socket_list(*ntree, *node, ntree->inputs, node->outputs, SOCK_OUT, true);
std::unique_ptr<decl::Extend> decl = std::make_unique<decl::Extend>();
decl->name = "";
decl->identifier = "__extend__";
decl->in_out = in_out;
return decl;
}
static void group_input_declare_dynamic(const bNodeTree &node_tree,
const bNode & /*node*/,
NodeDeclaration &r_declaration)
{
LISTBASE_FOREACH (const bNodeSocket *, input, &node_tree.inputs) {
r_declaration.outputs.append(declaration_for_interface_socket(*input));
r_declaration.outputs.last()->in_out = SOCK_OUT;
}
r_declaration.outputs.append(extend_declaration(SOCK_OUT));
}
static void group_output_declare_dynamic(const bNodeTree &node_tree,
const bNode & /*node*/,
NodeDeclaration &r_declaration)
{
LISTBASE_FOREACH (const bNodeSocket *, input, &node_tree.outputs) {
r_declaration.inputs.append(declaration_for_interface_socket(*input));
r_declaration.inputs.last()->in_out = SOCK_IN;
}
r_declaration.inputs.append(extend_declaration(SOCK_IN));
}
static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
{
BLI_assert(link->tonode != node);
BLI_assert(link->tosock->in_out == SOCK_IN);
if (link->fromsock->identifier != StringRef("__extend__")) {
return true;
}
if (link->tosock->identifier == StringRef("__extend__")) {
/* Don't connect to other "extend" sockets. */
return false;
}
const bNodeSocket *io_socket = ntreeAddSocketInterfaceFromSocket(
ntree, link->tonode, link->tosock);
if (!io_socket) {
return false;
}
update_node_declaration_and_sockets(*ntree, *node);
link->fromsock = node_group_input_find_socket(node, io_socket->identifier);
return true;
}
static bool group_output_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
{
BLI_assert(link->fromnode != node);
BLI_assert(link->fromsock->in_out == SOCK_OUT);
if (link->tosock->identifier != StringRef("__extend__")) {
return true;
}
if (link->fromsock->identifier == StringRef("__extend__")) {
/* Don't connect to other "extend" sockets. */
return false;
}
const bNodeSocket *io_socket = ntreeAddSocketInterfaceFromSocket(
ntree, link->fromnode, link->fromsock);
if (!io_socket) {
return false;
}
update_node_declaration_and_sockets(*ntree, *node);
link->tosock = node_group_output_find_socket(node, io_socket->identifier);
return true;
}
} // namespace blender::nodes
void register_node_type_group_input()
{
/* used for all tree types, needs dynamic allocation */
@@ -501,17 +519,12 @@ void register_node_type_group_input()
node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE);
node_type_size(ntype, 140, 80, 400);
ntype->initfunc = node_group_input_init;
ntype->updatefunc = node_group_input_update;
ntype->declare_dynamic = blender::nodes::group_input_declare_dynamic;
ntype->insert_link = blender::nodes::group_input_insert_link;
nodeRegisterType(ntype);
}
static void node_group_output_init(bNodeTree *ntree, bNode *node)
{
node_group_output_update(ntree, node);
}
bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
{
bNodeSocket *sock;
@@ -523,57 +536,6 @@ bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
return nullptr;
}
void node_group_output_update(bNodeTree *ntree, bNode *node)
{
bNodeSocket *extsock = (bNodeSocket *)node->inputs.last;
/* Adding a tree socket and verifying will remove the extension socket!
* This list caches the existing links to the extension socket
* so they can be recreated after verification. */
Vector<bNodeLink> temp_links;
/* find links to the extension socket and store them */
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (nodeLinkIsHidden(link)) {
continue;
}
if (link->tosock == extsock) {
temp_links.append(*link);
nodeRemLink(ntree, link);
}
}
/* find valid link to expose */
bNodeLink *exposelink = nullptr;
for (bNodeLink &link : temp_links) {
/* XXX Multiple sockets can be connected to the extension socket at once,
* in that case the arbitrary first link determines name and type.
* This could be improved by choosing the "best" type among all links,
* whatever that means.
*/
if (!is_group_extension_socket(link.fromnode, link.fromsock)) {
exposelink = &link;
break;
}
}
if (exposelink) {
/* XXX what if connecting virtual to virtual socket?? */
bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(
ntree, exposelink->fromnode, exposelink->fromsock);
node_group_output_update(ntree, node);
bNodeSocket *newsock = node_group_output_find_socket(node, gsock->identifier);
/* redirect links to the extension socket */
for (bNodeLink &link : temp_links) {
nodeAddLink(ntree, link.fromnode, link.fromsock, node, newsock);
}
}
group_verify_socket_list(*ntree, *node, ntree->outputs, node->inputs, SOCK_IN, true);
}
void register_node_type_group_output()
{
/* used for all tree types, needs dynamic allocation */
@@ -582,8 +544,8 @@ void register_node_type_group_output()
node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE);
node_type_size(ntype, 140, 80, 400);
ntype->initfunc = node_group_output_init;
ntype->updatefunc = node_group_output_update;
ntype->declare_dynamic = blender::nodes::group_output_declare_dynamic;
ntype->insert_link = blender::nodes::group_output_insert_link;
ntype->no_muting = true;

View File

@@ -16,6 +16,15 @@ void build_node_declaration(const bNodeType &typeinfo, NodeDeclaration &r_declar
node_decl_builder.finalize();
}
void build_node_declaration_dynamic(const bNodeTree &node_tree,
const bNode &node,
NodeDeclaration &r_declaration)
{
r_declaration.inputs.clear();
r_declaration.outputs.clear();
node.typeinfo->declare_dynamic(node_tree, node, r_declaration);
}
void NodeDeclarationBuilder::finalize()
{
if (is_function_node_) {

View File

@@ -19,6 +19,7 @@
#include "BKE_lib_id.h"
#include "BKE_node.h"
#include "BKE_node_runtime.hh"
#include "BKE_node_tree_update.h"
#include "DNA_collection_types.h"
#include "DNA_material_types.h"
@@ -171,6 +172,8 @@ static void verify_socket_template_list(bNodeTree *ntree,
}
}
namespace blender::nodes {
static void refresh_socket_list(bNodeTree &ntree,
bNode &node,
ListBase &sockets,
@@ -232,6 +235,7 @@ static void refresh_socket_list(bNodeTree &ntree,
}
}
new_sockets.add_new(new_socket);
BKE_ntree_update_tag_socket_new(&ntree, new_socket);
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, old_socket, &sockets) {
if (!new_sockets.contains(old_socket)) {
@@ -249,10 +253,29 @@ static void refresh_node(bNodeTree &ntree,
blender::nodes::NodeDeclaration &node_decl,
bool do_id_user)
{
refresh_socket_list(ntree, node, node.inputs, node_decl.inputs, do_id_user);
refresh_socket_list(ntree, node, node.outputs, node_decl.outputs, do_id_user);
if (node_decl.skip_updating_sockets) {
return;
}
if (!node_decl.matches(node)) {
refresh_socket_list(ntree, node, node.inputs, node_decl.inputs, do_id_user);
refresh_socket_list(ntree, node, node.outputs, node_decl.outputs, do_id_user);
}
nodeSocketDeclarationsUpdate(&node);
}
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
{
if (node.typeinfo->declare_dynamic) {
if (!node.runtime->declaration) {
node.runtime->declaration = new NodeDeclaration();
}
build_node_declaration_dynamic(ntree, node, *node.runtime->declaration);
}
refresh_node(ntree, node, *node.runtime->declaration, true);
}
} // namespace blender::nodes
void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
{
bNodeType *ntype = node->typeinfo;
@@ -261,10 +284,7 @@ void node_verify_sockets(bNodeTree *ntree, bNode *node, bool do_id_user)
}
if (ntype->declare != nullptr) {
nodeDeclarationEnsureOnOutdatedNode(ntree, node);
if (!node->runtime->declaration->matches(*node)) {
refresh_node(*ntree, *node, *node->runtime->declaration, do_id_user);
}
nodeSocketDeclarationsUpdate(node);
refresh_node(*ntree, *node, *node->runtime->declaration, do_id_user);
return;
}
/* Don't try to match socket lists when there are no templates.
@@ -499,52 +519,6 @@ static void standard_node_socket_interface_init_socket(bNodeTree * /*ntree*/,
node_socket_copy_default_value(sock, interface_socket);
}
/* copies settings that are not changed for each socket instance */
static void standard_node_socket_interface_verify_socket(bNodeTree * /*ntree*/,
const bNodeSocket *interface_socket,
bNode * /*node*/,
bNodeSocket *sock,
const char * /*data_path*/)
{
/* sanity check */
if (sock->type != interface_socket->typeinfo->type) {
return;
}
/* make sure both exist */
if (!interface_socket->default_value) {
return;
}
node_socket_init_default_value(sock);
switch (interface_socket->typeinfo->type) {
case SOCK_FLOAT: {
bNodeSocketValueFloat *toval = (bNodeSocketValueFloat *)sock->default_value;
const bNodeSocketValueFloat *fromval = (const bNodeSocketValueFloat *)
interface_socket->default_value;
toval->min = fromval->min;
toval->max = fromval->max;
break;
}
case SOCK_INT: {
bNodeSocketValueInt *toval = (bNodeSocketValueInt *)sock->default_value;
const bNodeSocketValueInt *fromval = (const bNodeSocketValueInt *)
interface_socket->default_value;
toval->min = fromval->min;
toval->max = fromval->max;
break;
}
case SOCK_VECTOR: {
bNodeSocketValueVector *toval = (bNodeSocketValueVector *)sock->default_value;
const bNodeSocketValueVector *fromval = (const bNodeSocketValueVector *)
interface_socket->default_value;
toval->min = fromval->min;
toval->max = fromval->max;
break;
}
}
}
static void standard_node_socket_interface_from_socket(bNodeTree * /*ntree*/,
bNodeSocket *stemp,
const bNode * /*node*/,
@@ -592,7 +566,6 @@ static bNodeSocketType *make_standard_socket_type(int type, int subtype)
stype->interface_init_socket = standard_node_socket_interface_init_socket;
stype->interface_from_socket = standard_node_socket_interface_from_socket;
stype->interface_verify_socket = standard_node_socket_interface_verify_socket;
stype->use_link_limits_of_type = true;
stype->input_link_limit = 1;

View File

@@ -234,6 +234,14 @@ bool Vector::matches(const bNodeSocket &socket) const
if (socket.typeinfo->subtype != this->subtype) {
return false;
}
const bNodeSocketValueVector &value = *static_cast<const bNodeSocketValueVector *>(
socket.default_value);
if (value.min != this->soft_min_value) {
return false;
}
if (value.max != this->soft_max_value) {
return false;
}
return true;
}
@@ -257,6 +265,8 @@ bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket
this->set_common_flags(socket);
bNodeSocketValueVector &value = *(bNodeSocketValueVector *)socket.default_value;
value.subtype = this->subtype;
value.min = this->soft_min_value;
value.max = this->soft_max_value;
STRNCPY(socket.name, this->name.c_str());
return socket;
}
@@ -301,6 +311,17 @@ bool Bool::can_connect(const bNodeSocket &socket) const
return basic_types_can_connect(*this, socket);
}
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);
STRNCPY(socket.name, this->name.c_str());
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -346,6 +367,17 @@ bool Color::can_connect(const bNodeSocket &socket) const
return basic_types_can_connect(*this, socket);
}
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);
STRNCPY(socket.name, this->name.c_str());
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -382,6 +414,17 @@ bool String::can_connect(const bNodeSocket &socket) const
return sockets_can_connect(*this, socket) && socket.type == SOCK_STRING;
}
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);
}
this->set_common_flags(socket);
STRNCPY(socket.name, this->name.c_str());
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -542,4 +585,77 @@ bool Shader::can_connect(const bNodeSocket &socket) const
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Extend
* \{ */
bNodeSocket &Extend::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *nodeAddSocket(&ntree,
&node,
this->in_out,
"NodeSocketVirtual",
this->identifier.c_str(),
this->name.c_str());
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 = *nodeAddSocket(
&ntree, &node, this->in_out, idname_, this->identifier.c_str(), this->name.c_str());
return socket;
}
bool Custom::matches(const bNodeSocket &socket) const
{
if (!this->matches_common_data(socket)) {
return false;
}
if (socket.type != SOCK_CUSTOM) {
return false;
}
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
{
return socket;
}
/** \} */
} // namespace blender::nodes::decl

View File

@@ -324,19 +324,19 @@ static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree,
return nullptr;
}
void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
bool node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
{
bNodeSocket *socket = link->tosock;
if (node != link->tonode) {
return;
return true;
}
/* If we're not at the link limit of the target socket, we can skip
* trying to move existing links to another socket. */
const int to_link_limit = nodeSocketLinkLimit(socket);
if (socket->runtime->total_inputs + 1 < to_link_limit) {
return;
return true;
}
LISTBASE_FOREACH_MUTABLE (bNodeLink *, to_link, &ntree->links) {
@@ -345,16 +345,17 @@ void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link)
if (new_socket && new_socket != socket) {
/* Attempt to redirect the existing link to the new socket. */
to_link->tosock = new_socket;
return;
return true;
}
if (new_socket == nullptr) {
/* No possible replacement, remove the existing link. */
nodeRemLink(ntree, to_link);
return;
return true;
}
}
}
return true;
}
/** \} */

View File

@@ -74,7 +74,7 @@ void node_combsep_color_label(const ListBase *sockets, NodeCombSepColorMode mode
* already linked (and if its not an Multi Input Socket), we try to find a replacement socket for
* the link that we try to overwrite and connect that previous link to the new socket.
*/
void node_insert_link_default(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
bool node_insert_link_default(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void node_socket_set_float(struct bNodeTree *ntree,

View File

@@ -132,9 +132,8 @@ void search_link_ops_for_basic_node(GatherLinkSearchOpParams &params)
return;
}
if (node_type.declaration_is_dynamic) {
/* Dynamic declarations (whatever they end up being) aren't supported
* by this function, but still avoid a crash in release builds. */
if (node_type.declare_dynamic) {
/* Dynamic declarations aren't supported here, but avoid crashing in release builds. */
BLI_assert_unreachable();
return;
}

View File

@@ -95,7 +95,7 @@ void register_node_type_sh_group()
node_type_size(&ntype, 140, 60, 400);
ntype.labelfunc = node_group_label;
ntype.group_update_func = node_group_update;
ntype.declare_dynamic = blender::nodes::node_group_declare_dynamic;
ntype.gpu_fn = gpu_group_execute;
nodeRegisterType(&ntype);

View File

@@ -157,7 +157,7 @@ void register_node_type_tex_group(void)
node_type_size(&ntype, 140, 60, 400);
ntype.labelfunc = node_group_label;
ntype.group_update_func = node_group_update;
ntype.declare_dynamic = blender::nodes::node_group_declare_dynamic;
ntype.init_exec_fn = group_initexec;
ntype.free_exec_fn = group_freeexec;
ntype.exec_fn = group_execute;