From 1e3f273b36bc90ee953368429ed5a39d67f6567a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 9 Oct 2023 12:40:09 +0200 Subject: [PATCH 1/9] extract function --- source/blender/nodes/intern/node_socket.cc | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index b8871c5d4db..c8446d1eeb9 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -178,6 +178,20 @@ static void verify_socket_template_list(bNodeTree *ntree, namespace blender::nodes { +static bNodeSocket *get_old_socket_for_declaration(const bNode &node, + Vector &old_sockets, + const SocketDeclaration &socket_decl) +{ + for (const int i : old_sockets.index_range()) { + bNodeSocket &old_socket = *old_sockets[i]; + if (old_socket.identifier == socket_decl.identifier) { + old_sockets.remove_and_reorder(i); + return &old_socket; + } + } + return nullptr; +} + static void refresh_node_socket(bNodeTree &ntree, bNode &node, const SocketDeclaration &socket_decl, @@ -185,15 +199,9 @@ static void refresh_node_socket(bNodeTree &ntree, VectorSet &new_sockets) { /* Try to find a socket that corresponds to the declaration. */ - bNodeSocket *old_socket_with_same_identifier = nullptr; - for (const int i : old_sockets.index_range()) { - bNodeSocket &old_socket = *old_sockets[i]; - if (old_socket.identifier == socket_decl.identifier) { - old_sockets.remove_and_reorder(i); - old_socket_with_same_identifier = &old_socket; - break; - } - } + bNodeSocket *old_socket_with_same_identifier = get_old_socket_for_declaration( + node, old_sockets, socket_decl); + bNodeSocket *new_socket = nullptr; if (old_socket_with_same_identifier == nullptr) { /* Create a completely new socket. */ -- 2.30.2 From d989ccfdc8f491d546aee2e6116c97fdc920088a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 9 Oct 2023 13:03:33 +0200 Subject: [PATCH 2/9] add actual versioning --- source/blender/nodes/intern/node_socket.cc | 57 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index c8446d1eeb9..61ed1a997c9 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -35,6 +35,7 @@ #include "NOD_node_declaration.hh" #include "NOD_socket.hh" +#include "NOD_socket_declarations.hh" #include "FN_field.hh" @@ -178,13 +179,67 @@ static void verify_socket_template_list(bNodeTree *ntree, namespace blender::nodes { +static std::optional decl_to_data_type(const SocketDeclaration &socket_decl) +{ + if (dynamic_cast(&socket_decl)) { + return SOCK_FLOAT; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_INT; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_BOOLEAN; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_VECTOR; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_RGBA; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_ROTATION; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_STRING; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_IMAGE; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_TEXTURE; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_MATERIAL; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_SHADER; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_COLLECTION; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_OBJECT; + } + return std::nullopt; +} + static bNodeSocket *get_old_socket_for_declaration(const bNode &node, Vector &old_sockets, const SocketDeclaration &socket_decl) { + const bool use_prefix_and_type_check = ELEM(node.type, GEO_NODE_SWITCH); + for (const int i : old_sockets.index_range()) { bNodeSocket &old_socket = *old_sockets[i]; - if (old_socket.identifier == socket_decl.identifier) { + if (use_prefix_and_type_check) { + if (BLI_str_startswith(socket_decl.identifier.c_str(), old_socket.identifier)) { + if (old_socket.type == decl_to_data_type(socket_decl)) { + old_sockets.remove_and_reorder(i); + return &old_socket; + } + } + } + else if (old_socket.identifier == socket_decl.identifier) { old_sockets.remove_and_reorder(i); return &old_socket; } -- 2.30.2 From d547e5d977fb3ab44bbc6144ccb04bc638e216c5 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 9 Oct 2023 13:20:55 +0200 Subject: [PATCH 3/9] progress --- source/blender/nodes/intern/node_socket.cc | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 61ed1a997c9..a21584a83e2 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -223,11 +223,38 @@ static std::optional decl_to_data_type(const SocketDeclarat return std::nullopt; } +static bool do_forward_compatible_socket_type_check(const bNode &node) +{ + switch (node.type) { + case GEO_NODE_SWITCH: + case GEO_NODE_ACCUMULATE_FIELD: + case GEO_NODE_CAPTURE_ATTRIBUTE: + case GEO_NODE_ATTRIBUTE_STATISTIC: + case GEO_NODE_BLUR_ATTRIBUTE: + case GEO_NODE_CURVE_SAMPLE_FACTOR: + case GEO_NODE_EVALUATE_AT_INDEX: + case GEO_NODE_EVALUATE_ON_DOMAIN: + case GEO_NODE_INPUT_NAMED_ATTRIBUTE: + case GEO_NODE_RAYCAST: + case GEO_NODE_SAMPLE_INDEX: + case GEO_NODE_SAMPLE_NEAREST_SURFACE: + case GEO_NODE_SAMPLE_UV_SURFACE: + case GEO_NODE_STORE_NAMED_ATTRIBUTE: + case GEO_NODE_VIEWER: + case FN_NODE_COMPARE: + case FN_NODE_RANDOM_VALUE: + case SH_NODE_MIX: + return true; + default: + return false; + } +} + static bNodeSocket *get_old_socket_for_declaration(const bNode &node, Vector &old_sockets, const SocketDeclaration &socket_decl) { - const bool use_prefix_and_type_check = ELEM(node.type, GEO_NODE_SWITCH); + const bool use_prefix_and_type_check = do_forward_compatible_socket_type_check(node); for (const int i : old_sockets.index_range()) { bNodeSocket &old_socket = *old_sockets[i]; -- 2.30.2 From 088fa168e1bdb0693232d59901a8ddccef19b0a4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 10 Oct 2023 12:05:16 +0200 Subject: [PATCH 4/9] progress --- source/blender/blenkernel/BKE_node_runtime.hh | 2 + source/blender/nodes/intern/node_socket.cc | 73 ++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 6a75cc9b418..dac501b7d88 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -296,6 +296,8 @@ class bNodeRuntime : NonCopyable, NonMovable { /** Eagerly maintained cache of the node's index in the tree. */ int index_in_tree = -1; + bool forward_compat_versioning_done = false; + /** Only valid if #topology_cache_is_dirty is false. */ Vector inputs; Vector outputs; diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index a21584a83e2..f64dbf69a86 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -250,23 +250,15 @@ static bool do_forward_compatible_socket_type_check(const bNode &node) } } -static bNodeSocket *get_old_socket_for_declaration(const bNode &node, +static bNodeSocket *get_old_socket_for_declaration(const bNode & /*node*/, Vector &old_sockets, const SocketDeclaration &socket_decl) { - const bool use_prefix_and_type_check = do_forward_compatible_socket_type_check(node); + // const bool use_prefix_and_type_check = do_forward_compatible_socket_type_check(node); for (const int i : old_sockets.index_range()) { bNodeSocket &old_socket = *old_sockets[i]; - if (use_prefix_and_type_check) { - if (BLI_str_startswith(socket_decl.identifier.c_str(), old_socket.identifier)) { - if (old_socket.type == decl_to_data_type(socket_decl)) { - old_sockets.remove_and_reorder(i); - return &old_socket; - } - } - } - else if (old_socket.identifier == socket_decl.identifier) { + if (old_socket.identifier == socket_decl.identifier) { old_sockets.remove_and_reorder(i); return &old_socket; } @@ -365,11 +357,70 @@ static void refresh_node_panel(const PanelDeclaration &panel_decl, } } +static void do_forward_compat_versioning(bNode &node) +{ + switch (node.type) { + case GEO_NODE_SWITCH: { + const NodeSwitch &storage = *static_cast(node.storage); + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (BLI_str_startswith(socket->identifier, "Switch")) { + if (ELEM(storage.input_type, + SOCK_FLOAT, + SOCK_INT, + SOCK_BOOLEAN, + SOCK_VECTOR, + SOCK_RGBA, + SOCK_STRING, + SOCK_ROTATION)) + { + STRNCPY(socket->identifier, "Switch"); + } + else { + STRNCPY(socket->identifier, "Switch_001"); + } + } + else if (BLI_str_startswith(socket->identifier, "False")) { + switch (storage.input_type) { + case SOCK_FLOAT: + STRNCPY(socket->identifier, "False"); + break; + case SOCK_VECTOR: + STRNCPY(socket->identifier, "False_003"); + break; + case SOCK_ROTATION: + STRNCPY(socket->identifier, "False_012"); + break; + } + } + else if (BLI_str_startswith(socket->identifier, "True")) { + switch (storage.input_type) { + case SOCK_FLOAT: + STRNCPY(socket->identifier, "True"); + break; + case SOCK_VECTOR: + STRNCPY(socket->identifier, "True_003"); + break; + case SOCK_ROTATION: + STRNCPY(socket->identifier, "True_012"); + break; + } + } + } + break; + } + } +} + static void refresh_node_sockets_and_panels(bNodeTree &ntree, bNode &node, Span item_decls, const bool do_id_user) { + if (!node.runtime->forward_compat_versioning_done) { + do_forward_compat_versioning(node); + node.runtime->forward_compat_versioning_done = true; + } + /* Count panels */ int new_num_panels = 0; for (const ItemDeclarationPtr &item_decl : item_decls) { -- 2.30.2 From 520aaa0205a1c074e5fe4a31db93d379a39a7d98 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 10 Oct 2023 14:54:56 +0200 Subject: [PATCH 5/9] progress --- source/blender/nodes/intern/node_socket.cc | 209 ++++++++++++++------- 1 file changed, 142 insertions(+), 67 deletions(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index f64dbf69a86..50f70a361e7 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -223,32 +223,32 @@ static std::optional decl_to_data_type(const SocketDeclarat return std::nullopt; } -static bool do_forward_compatible_socket_type_check(const bNode &node) -{ - switch (node.type) { - case GEO_NODE_SWITCH: - case GEO_NODE_ACCUMULATE_FIELD: - case GEO_NODE_CAPTURE_ATTRIBUTE: - case GEO_NODE_ATTRIBUTE_STATISTIC: - case GEO_NODE_BLUR_ATTRIBUTE: - case GEO_NODE_CURVE_SAMPLE_FACTOR: - case GEO_NODE_EVALUATE_AT_INDEX: - case GEO_NODE_EVALUATE_ON_DOMAIN: - case GEO_NODE_INPUT_NAMED_ATTRIBUTE: - case GEO_NODE_RAYCAST: - case GEO_NODE_SAMPLE_INDEX: - case GEO_NODE_SAMPLE_NEAREST_SURFACE: - case GEO_NODE_SAMPLE_UV_SURFACE: - case GEO_NODE_STORE_NAMED_ATTRIBUTE: - case GEO_NODE_VIEWER: - case FN_NODE_COMPARE: - case FN_NODE_RANDOM_VALUE: - case SH_NODE_MIX: - return true; - default: - return false; - } -} +// static bool do_forward_compatible_socket_type_check(const bNode &node) +// { +// switch (node.type) { +// case GEO_NODE_SWITCH: +// case GEO_NODE_ACCUMULATE_FIELD: +// case GEO_NODE_CAPTURE_ATTRIBUTE: +// case GEO_NODE_ATTRIBUTE_STATISTIC: +// case GEO_NODE_BLUR_ATTRIBUTE: +// case GEO_NODE_CURVE_SAMPLE_FACTOR: +// case GEO_NODE_EVALUATE_AT_INDEX: +// case GEO_NODE_EVALUATE_ON_DOMAIN: +// case GEO_NODE_INPUT_NAMED_ATTRIBUTE: +// case GEO_NODE_RAYCAST: +// case GEO_NODE_SAMPLE_INDEX: +// case GEO_NODE_SAMPLE_NEAREST_SURFACE: +// case GEO_NODE_SAMPLE_UV_SURFACE: +// case GEO_NODE_STORE_NAMED_ATTRIBUTE: +// case GEO_NODE_VIEWER: +// case FN_NODE_COMPARE: +// case FN_NODE_RANDOM_VALUE: +// case SH_NODE_MIX: +// return true; +// default: +// return false; +// } +// } static bNodeSocket *get_old_socket_for_declaration(const bNode & /*node*/, Vector &old_sockets, @@ -357,58 +357,133 @@ static void refresh_node_panel(const PanelDeclaration &panel_decl, } } -static void do_forward_compat_versioning(bNode &node) +static const char *get_forward_compatible_identifier(const bNode &node, const bNodeSocket &socket) { switch (node.type) { case GEO_NODE_SWITCH: { const NodeSwitch &storage = *static_cast(node.storage); - LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (BLI_str_startswith(socket->identifier, "Switch")) { - if (ELEM(storage.input_type, - SOCK_FLOAT, - SOCK_INT, - SOCK_BOOLEAN, - SOCK_VECTOR, - SOCK_RGBA, - SOCK_STRING, - SOCK_ROTATION)) - { - STRNCPY(socket->identifier, "Switch"); - } - else { - STRNCPY(socket->identifier, "Switch_001"); - } + const bool use_field_socket = ELEM(storage.input_type, + SOCK_FLOAT, + SOCK_INT, + SOCK_BOOLEAN, + SOCK_VECTOR, + SOCK_VECTOR, + SOCK_RGBA, + SOCK_STRING); + if (BLI_str_startswith(socket.identifier, "Switch")) { + if (use_field_socket) { + return "Switch"; } - else if (BLI_str_startswith(socket->identifier, "False")) { - switch (storage.input_type) { - case SOCK_FLOAT: - STRNCPY(socket->identifier, "False"); - break; - case SOCK_VECTOR: - STRNCPY(socket->identifier, "False_003"); - break; - case SOCK_ROTATION: - STRNCPY(socket->identifier, "False_012"); - break; - } + return "Switch_001"; + } + if (BLI_str_startswith(socket.identifier, "False")) { + switch (storage.input_type) { + case SOCK_FLOAT: + return "False"; + case SOCK_INT: + return "False_001"; + case SOCK_BOOLEAN: + return "False_002"; + case SOCK_VECTOR: + return "False_003"; + case SOCK_RGBA: + return "False_004"; + case SOCK_STRING: + return "False_005"; + case SOCK_GEOMETRY: + return "False_006"; + case SOCK_OBJECT: + return "False_007"; + case SOCK_COLLECTION: + return "False_008"; + case SOCK_TEXTURE: + return "False_009"; + case SOCK_MATERIAL: + return "False_010"; + case SOCK_IMAGE: + return "False_011"; + case SOCK_ROTATION: + return "False_012"; } - else if (BLI_str_startswith(socket->identifier, "True")) { - switch (storage.input_type) { - case SOCK_FLOAT: - STRNCPY(socket->identifier, "True"); - break; - case SOCK_VECTOR: - STRNCPY(socket->identifier, "True_003"); - break; - case SOCK_ROTATION: - STRNCPY(socket->identifier, "True_012"); - break; - } + } + if (BLI_str_startswith(socket.identifier, "True")) { + switch (storage.input_type) { + case SOCK_FLOAT: + return "True"; + case SOCK_INT: + return "True_001"; + case SOCK_BOOLEAN: + return "True_002"; + case SOCK_VECTOR: + return "True_003"; + case SOCK_RGBA: + return "True_004"; + case SOCK_STRING: + return "True_005"; + case SOCK_GEOMETRY: + return "True_006"; + case SOCK_OBJECT: + return "True_007"; + case SOCK_COLLECTION: + return "True_008"; + case SOCK_TEXTURE: + return "True_009"; + case SOCK_MATERIAL: + return "True_010"; + case SOCK_IMAGE: + return "True_011"; + case SOCK_ROTATION: + return "True_012"; + } + } + if (BLI_str_startswith(socket.identifier, "Output")) { + switch (storage.input_type) { + case SOCK_FLOAT: + return "Output"; + case SOCK_INT: + return "Output_001"; + case SOCK_BOOLEAN: + return "Output_002"; + case SOCK_VECTOR: + return "Output_003"; + case SOCK_RGBA: + return "Output_004"; + case SOCK_STRING: + return "Output_005"; + case SOCK_GEOMETRY: + return "Output_006"; + case SOCK_OBJECT: + return "Output_007"; + case SOCK_COLLECTION: + return "Output_008"; + case SOCK_TEXTURE: + return "Output_009"; + case SOCK_MATERIAL: + return "Output_010"; + case SOCK_IMAGE: + return "Output_011"; + case SOCK_ROTATION: + return "Output_012"; } } break; } } + return nullptr; +} + +static void do_forward_compat_versioning(bNode &node) +{ + LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { + if (const char *new_identifier = get_forward_compatible_identifier(node, *socket)) { + STRNCPY(socket->identifier, new_identifier); + } + } + LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { + if (const char *new_identifier = get_forward_compatible_identifier(node, *socket)) { + STRNCPY(socket->identifier, new_identifier); + } + } } static void refresh_node_sockets_and_panels(bNodeTree &ntree, -- 2.30.2 From 047900cc795c5cc2aee0580cd9f3ccd784f75fec Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 10 Oct 2023 15:30:55 +0200 Subject: [PATCH 6/9] add forward compatibility for all nodes --- source/blender/nodes/intern/node_socket.cc | 214 +++++++++++---------- 1 file changed, 112 insertions(+), 102 deletions(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 50f70a361e7..24caff44383 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -357,7 +357,40 @@ static void refresh_node_panel(const PanelDeclaration &panel_decl, } } -static const char *get_forward_compatible_identifier(const bNode &node, const bNodeSocket &socket) +static const char *get_identifier_from_decl(const char *identifier_prefix, + const bNodeSocket &socket, + const Span socket_decls) +{ + if (!BLI_str_startswith(socket.identifier, identifier_prefix)) { + return nullptr; + } + for (const SocketDeclaration *socket_decl : socket_decls) { + if (BLI_str_startswith(socket_decl->identifier.c_str(), identifier_prefix)) { + if (socket.type == decl_to_data_type(*socket_decl)) { + return socket_decl->identifier.c_str(); + } + } + } + return nullptr; +} + +static const char *get_identifier_from_decl(const Span identifier_prefixes, + const bNodeSocket &socket, + const Span socket_decls) +{ + for (const char *identifier_prefix : identifier_prefixes) { + if (const char *identifier = get_identifier_from_decl(identifier_prefix, socket, socket_decls)) + { + return identifier; + } + } + return nullptr; +} + +static const char *get_forward_compatible_identifier( + const bNode &node, + const bNodeSocket &socket, + const Span socket_decls) { switch (node.type) { case GEO_NODE_SWITCH: { @@ -367,120 +400,97 @@ static const char *get_forward_compatible_identifier(const bNode &node, const bN SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, - SOCK_VECTOR, SOCK_RGBA, - SOCK_STRING); + SOCK_STRING, + SOCK_ROTATION); if (BLI_str_startswith(socket.identifier, "Switch")) { if (use_field_socket) { return "Switch"; } return "Switch_001"; } - if (BLI_str_startswith(socket.identifier, "False")) { - switch (storage.input_type) { - case SOCK_FLOAT: - return "False"; - case SOCK_INT: - return "False_001"; - case SOCK_BOOLEAN: - return "False_002"; - case SOCK_VECTOR: - return "False_003"; - case SOCK_RGBA: - return "False_004"; - case SOCK_STRING: - return "False_005"; - case SOCK_GEOMETRY: - return "False_006"; - case SOCK_OBJECT: - return "False_007"; - case SOCK_COLLECTION: - return "False_008"; - case SOCK_TEXTURE: - return "False_009"; - case SOCK_MATERIAL: - return "False_010"; - case SOCK_IMAGE: - return "False_011"; - case SOCK_ROTATION: - return "False_012"; - } - } - if (BLI_str_startswith(socket.identifier, "True")) { - switch (storage.input_type) { - case SOCK_FLOAT: - return "True"; - case SOCK_INT: - return "True_001"; - case SOCK_BOOLEAN: - return "True_002"; - case SOCK_VECTOR: - return "True_003"; - case SOCK_RGBA: - return "True_004"; - case SOCK_STRING: - return "True_005"; - case SOCK_GEOMETRY: - return "True_006"; - case SOCK_OBJECT: - return "True_007"; - case SOCK_COLLECTION: - return "True_008"; - case SOCK_TEXTURE: - return "True_009"; - case SOCK_MATERIAL: - return "True_010"; - case SOCK_IMAGE: - return "True_011"; - case SOCK_ROTATION: - return "True_012"; - } - } - if (BLI_str_startswith(socket.identifier, "Output")) { - switch (storage.input_type) { - case SOCK_FLOAT: - return "Output"; - case SOCK_INT: - return "Output_001"; - case SOCK_BOOLEAN: - return "Output_002"; - case SOCK_VECTOR: - return "Output_003"; - case SOCK_RGBA: - return "Output_004"; - case SOCK_STRING: - return "Output_005"; - case SOCK_GEOMETRY: - return "Output_006"; - case SOCK_OBJECT: - return "Output_007"; - case SOCK_COLLECTION: - return "Output_008"; - case SOCK_TEXTURE: - return "Output_009"; - case SOCK_MATERIAL: - return "Output_010"; - case SOCK_IMAGE: - return "Output_011"; - case SOCK_ROTATION: - return "Output_012"; - } - } - break; + return get_identifier_from_decl({"False", "True", "Output"}, socket, socket_decls); + } + case GEO_NODE_ACCUMULATE_FIELD: { + return get_identifier_from_decl( + {"Value", "Leading", "Trailing", "Total"}, socket, socket_decls); + } + case GEO_NODE_CAPTURE_ATTRIBUTE: { + return get_identifier_from_decl({"Value", "Attribute"}, socket, socket_decls); + } + case GEO_NODE_ATTRIBUTE_STATISTIC: { + return get_identifier_from_decl({"Attribute", + "Mean", + "Median", + "Sum", + "Min", + "Max", + "Range", + "Standard Deviation", + "Variance"}, + socket, + socket_decls); + } + case GEO_NODE_BLUR_ATTRIBUTE: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_SAMPLE_CURVE: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_EVALUATE_AT_INDEX: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_EVALUATE_ON_DOMAIN: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_INPUT_NAMED_ATTRIBUTE: { + return get_identifier_from_decl({"Attribute"}, socket, socket_decls); + } + case GEO_NODE_RAYCAST: { + return get_identifier_from_decl({"Attribute"}, socket, socket_decls); + } + case GEO_NODE_SAMPLE_INDEX: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_SAMPLE_NEAREST_SURFACE: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case FN_NODE_RANDOM_VALUE: { + return get_identifier_from_decl({"Min", "Max", "Value"}, socket, socket_decls); + } + case GEO_NODE_SAMPLE_UV_SURFACE: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_STORE_NAMED_ATTRIBUTE: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case GEO_NODE_VIEWER: { + return get_identifier_from_decl({"Value"}, socket, socket_decls); + } + case SH_NODE_MIX: { + return get_identifier_from_decl({"A", "B", "Result"}, socket, socket_decls); + } + case FN_NODE_COMPARE: { + return get_identifier_from_decl({"A", "B"}, socket, socket_decls); } } + return nullptr; } -static void do_forward_compat_versioning(bNode &node) +static void do_forward_compat_versioning(bNode &node, const NodeDeclaration &node_decl) { LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (const char *new_identifier = get_forward_compatible_identifier(node, *socket)) { + if (const char *new_identifier = get_forward_compatible_identifier( + node, *socket, node_decl.inputs)) + { STRNCPY(socket->identifier, new_identifier); } } LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { - if (const char *new_identifier = get_forward_compatible_identifier(node, *socket)) { + if (const char *new_identifier = get_forward_compatible_identifier( + node, *socket, node_decl.outputs)) + { STRNCPY(socket->identifier, new_identifier); } } @@ -488,17 +498,17 @@ static void do_forward_compat_versioning(bNode &node) static void refresh_node_sockets_and_panels(bNodeTree &ntree, bNode &node, - Span item_decls, + const NodeDeclaration &node_decl, const bool do_id_user) { if (!node.runtime->forward_compat_versioning_done) { - do_forward_compat_versioning(node); + do_forward_compat_versioning(node, node_decl); node.runtime->forward_compat_versioning_done = true; } /* Count panels */ int new_num_panels = 0; - for (const ItemDeclarationPtr &item_decl : item_decls) { + for (const ItemDeclarationPtr &item_decl : node_decl.items) { if (dynamic_cast(item_decl.get())) { ++new_num_panels; } @@ -525,7 +535,7 @@ static void refresh_node_sockets_and_panels(bNodeTree &ntree, VectorSet new_inputs; VectorSet new_outputs; bNodePanelState *new_panel = node.panel_states_array; - for (const ItemDeclarationPtr &item_decl : item_decls) { + for (const ItemDeclarationPtr &item_decl : node_decl.items) { if (const SocketDeclaration *socket_decl = dynamic_cast( item_decl.get())) { @@ -576,7 +586,7 @@ static void refresh_node(bNodeTree &ntree, return; } if (!node_decl.matches(node)) { - refresh_node_sockets_and_panels(ntree, node, node_decl.items, do_id_user); + refresh_node_sockets_and_panels(ntree, node, node_decl, do_id_user); } blender::bke::nodeSocketDeclarationsUpdate(&node); } -- 2.30.2 From 4c3d42b89b8abe40a7ea2e3f151b2a8ecee01f74 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 10 Oct 2023 15:37:25 +0200 Subject: [PATCH 7/9] progress --- source/blender/blenkernel/BKE_node_runtime.hh | 3 +- source/blender/nodes/intern/node_socket.cc | 166 ++++++++---------- 2 files changed, 72 insertions(+), 97 deletions(-) diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index dac501b7d88..c3c1ce2e6eb 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -296,7 +296,8 @@ class bNodeRuntime : NonCopyable, NonMovable { /** Eagerly maintained cache of the node's index in the tree. */ int index_in_tree = -1; - bool forward_compat_versioning_done = false; + /** Used to avoid running forward compatibility code more often than necessary. */ + bool forward_compatible_versioning_done = false; /** Only valid if #topology_cache_is_dirty is false. */ Vector inputs; diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 24caff44383..ad2811098db 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -179,93 +179,6 @@ static void verify_socket_template_list(bNodeTree *ntree, namespace blender::nodes { -static std::optional decl_to_data_type(const SocketDeclaration &socket_decl) -{ - if (dynamic_cast(&socket_decl)) { - return SOCK_FLOAT; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_INT; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_BOOLEAN; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_VECTOR; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_RGBA; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_ROTATION; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_STRING; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_IMAGE; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_TEXTURE; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_MATERIAL; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_SHADER; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_COLLECTION; - } - else if (dynamic_cast(&socket_decl)) { - return SOCK_OBJECT; - } - return std::nullopt; -} - -// static bool do_forward_compatible_socket_type_check(const bNode &node) -// { -// switch (node.type) { -// case GEO_NODE_SWITCH: -// case GEO_NODE_ACCUMULATE_FIELD: -// case GEO_NODE_CAPTURE_ATTRIBUTE: -// case GEO_NODE_ATTRIBUTE_STATISTIC: -// case GEO_NODE_BLUR_ATTRIBUTE: -// case GEO_NODE_CURVE_SAMPLE_FACTOR: -// case GEO_NODE_EVALUATE_AT_INDEX: -// case GEO_NODE_EVALUATE_ON_DOMAIN: -// case GEO_NODE_INPUT_NAMED_ATTRIBUTE: -// case GEO_NODE_RAYCAST: -// case GEO_NODE_SAMPLE_INDEX: -// case GEO_NODE_SAMPLE_NEAREST_SURFACE: -// case GEO_NODE_SAMPLE_UV_SURFACE: -// case GEO_NODE_STORE_NAMED_ATTRIBUTE: -// case GEO_NODE_VIEWER: -// case FN_NODE_COMPARE: -// case FN_NODE_RANDOM_VALUE: -// case SH_NODE_MIX: -// return true; -// default: -// return false; -// } -// } - -static bNodeSocket *get_old_socket_for_declaration(const bNode & /*node*/, - Vector &old_sockets, - const SocketDeclaration &socket_decl) -{ - // const bool use_prefix_and_type_check = do_forward_compatible_socket_type_check(node); - - for (const int i : old_sockets.index_range()) { - bNodeSocket &old_socket = *old_sockets[i]; - if (old_socket.identifier == socket_decl.identifier) { - old_sockets.remove_and_reorder(i); - return &old_socket; - } - } - return nullptr; -} - static void refresh_node_socket(bNodeTree &ntree, bNode &node, const SocketDeclaration &socket_decl, @@ -273,9 +186,15 @@ static void refresh_node_socket(bNodeTree &ntree, VectorSet &new_sockets) { /* Try to find a socket that corresponds to the declaration. */ - bNodeSocket *old_socket_with_same_identifier = get_old_socket_for_declaration( - node, old_sockets, socket_decl); - + bNodeSocket *old_socket_with_same_identifier = nullptr; + for (const int i : old_sockets.index_range()) { + bNodeSocket &old_socket = *old_sockets[i]; + if (old_socket.identifier == socket_decl.identifier) { + old_sockets.remove_and_reorder(i); + old_socket_with_same_identifier = &old_socket; + break; + } + } bNodeSocket *new_socket = nullptr; if (old_socket_with_same_identifier == nullptr) { /* Create a completely new socket. */ @@ -357,6 +276,54 @@ static void refresh_node_panel(const PanelDeclaration &panel_decl, } } +/** + * Not great to have this here, but this is only for forward compatibility, so this code shouldn't + * in the `main` branch. + */ +static std::optional decl_to_data_type(const SocketDeclaration &socket_decl) +{ + if (dynamic_cast(&socket_decl)) { + return SOCK_FLOAT; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_INT; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_BOOLEAN; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_VECTOR; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_RGBA; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_ROTATION; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_STRING; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_IMAGE; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_TEXTURE; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_MATERIAL; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_SHADER; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_COLLECTION; + } + else if (dynamic_cast(&socket_decl)) { + return SOCK_OBJECT; + } + return std::nullopt; +} + static const char *get_identifier_from_decl(const char *identifier_prefix, const bNodeSocket &socket, const Span socket_decls) @@ -387,7 +354,12 @@ static const char *get_identifier_from_decl(const Span identifier_ return nullptr; } -static const char *get_forward_compatible_identifier( +/** + * This is used for forward compatibility. It can change identifiers of sockets created in the + * future to socket identifiers that are known in this version. That only works for a few + * hard-coded sockets of course. + */ +static const char *get_current_socket_identifier_for_future_socket( const bNode &node, const bNodeSocket &socket, const Span socket_decls) @@ -474,21 +446,23 @@ static const char *get_forward_compatible_identifier( return get_identifier_from_decl({"A", "B"}, socket, socket_decls); } } - return nullptr; } +/** + * Try to update identifiers of sockets created in the future to match identifiers that exist now. + */ static void do_forward_compat_versioning(bNode &node, const NodeDeclaration &node_decl) { LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (const char *new_identifier = get_forward_compatible_identifier( + if (const char *new_identifier = get_current_socket_identifier_for_future_socket( node, *socket, node_decl.inputs)) { STRNCPY(socket->identifier, new_identifier); } } LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { - if (const char *new_identifier = get_forward_compatible_identifier( + if (const char *new_identifier = get_current_socket_identifier_for_future_socket( node, *socket, node_decl.outputs)) { STRNCPY(socket->identifier, new_identifier); @@ -501,9 +475,9 @@ static void refresh_node_sockets_and_panels(bNodeTree &ntree, const NodeDeclaration &node_decl, const bool do_id_user) { - if (!node.runtime->forward_compat_versioning_done) { + if (!node.runtime->forward_compatible_versioning_done) { do_forward_compat_versioning(node, node_decl); - node.runtime->forward_compat_versioning_done = true; + node.runtime->forward_compatible_versioning_done = true; } /* Count panels */ -- 2.30.2 From 1933bdd04276c065104598a1d5fe3a0cc4ef3852 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 13 Oct 2023 12:04:40 +0200 Subject: [PATCH 8/9] fix --- source/blender/nodes/intern/node_socket.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index ad2811098db..a3e0415c2ad 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -455,17 +455,21 @@ static const char *get_current_socket_identifier_for_future_socket( static void do_forward_compat_versioning(bNode &node, const NodeDeclaration &node_decl) { LISTBASE_FOREACH (bNodeSocket *, socket, &node.inputs) { - if (const char *new_identifier = get_current_socket_identifier_for_future_socket( - node, *socket, node_decl.inputs)) - { - STRNCPY(socket->identifier, new_identifier); + if (socket->is_available()) { + if (const char *new_identifier = get_current_socket_identifier_for_future_socket( + node, *socket, node_decl.inputs)) + { + STRNCPY(socket->identifier, new_identifier); + } } } LISTBASE_FOREACH (bNodeSocket *, socket, &node.outputs) { - if (const char *new_identifier = get_current_socket_identifier_for_future_socket( - node, *socket, node_decl.outputs)) - { - STRNCPY(socket->identifier, new_identifier); + if (socket->is_available()) { + if (const char *new_identifier = get_current_socket_identifier_for_future_socket( + node, *socket, node_decl.outputs)) + { + STRNCPY(socket->identifier, new_identifier); + } } } } -- 2.30.2 From 4cfebf5d9a291145bd39bed6e2253d31f9178a9b Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 13 Oct 2023 12:15:57 +0200 Subject: [PATCH 9/9] improve comment --- source/blender/nodes/intern/node_socket.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index a3e0415c2ad..38e7d6198d7 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -277,7 +277,7 @@ static void refresh_node_panel(const PanelDeclaration &panel_decl, } /** - * Not great to have this here, but this is only for forward compatibility, so this code shouldn't + * Not great to have this here, but this is only for forward compatibility, so this code shouldn't * in the `main` branch. */ static std::optional decl_to_data_type(const SocketDeclaration &socket_decl) @@ -355,9 +355,16 @@ static const char *get_identifier_from_decl(const Span identifier_ } /** - * This is used for forward compatibility. It can change identifiers of sockets created in the - * future to socket identifiers that are known in this version. That only works for a few - * hard-coded sockets of course. + * Currently, nodes that support different socket types have sockets for all supported types with + * different identifiers (e.g. `Attribute`, `Attribute_001`, `Attribute_002`, ...). In the future, + * we will hopefully have a better way to handle this that does not require all the sockets of + * different types to exist at the same time. Instead we want that there is only a single socket + * that can change its type while the identifier stays the same. + * + * This function prepares us for that future. It returns the identifier that we use for a socket + * now based on the "base socket name" (e.g. `Attribute`) and its socket type. It allows us to + * change the socket identifiers in the future without breaking forward compatibility for the nodes + * handled here. */ static const char *get_current_socket_identifier_for_future_socket( const bNode &node, -- 2.30.2