diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 3ea662f3d16..2b61ad82ff0 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -735,6 +735,18 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree, bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique); +/** + * Move socket default from \a src (input socket) to locations specified by \a dst (output socket). + * Result value moved in specific location. (potentially multiple group nodes socket values, if \a + * dst is a group input node). + * \note Conceptually, the effect should be such that the evaluation of + * this graph again returns the value in src. + */ +void node_socket_move_default_value(Main &bmain, + bNodeTree &tree, + bNodeSocket &src, + bNodeSocket &dst); + /** * Free the node itself. * diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index e613af558f8..4862a770f19 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -2403,6 +2403,94 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree, return node_dst; } +static void for_each_node_group_instance(Main &bmain, + const bNodeTree &node_group, + const Span tree_types_to_lookup, + const FunctionRef func) +{ + LISTBASE_FOREACH (bNodeTree *, other_group, &bmain.nodetrees) { + if (!tree_types_to_lookup.contains(other_group->type)) { + continue; + } + if (other_group == &node_group) { + continue; + } + + other_group->ensure_topology_cache(); + for (bNode *node : other_group->group_nodes()) { + if (node->id == &node_group.id) { + func(*node); + } + } + } +} + +void node_socket_move_default_value(Main &bmain, + bNodeTree &tree, + bNodeSocket &src, + bNodeSocket &dst) +{ + tree.ensure_topology_cache(); + + bNode &dst_node = dst.owner_node(); + bNode &src_node = src.owner_node(); + + if (src.is_multi_input()) { + /* Multi input sockets no have value. */ + return; + } + if (ELEM(NODE_REROUTE, dst_node.type, src_node.type)) { + /* Reroute node can't have ownership of socket value directly. */ + return; + } + if (dst.type != src.type) { + /* It could be possible to support conversion in future. */ + return; + } + + ID **src_socket_value = nullptr; + Vector dst_values; + switch (dst.type) { + case SOCK_IMAGE: { + Image **tmp_socket_value = &src.default_value_typed()->value; + src_socket_value = reinterpret_cast(tmp_socket_value); + if (*src_socket_value == nullptr) { + break; + } + + switch (dst_node.type) { + case GEO_NODE_IMAGE: { + dst_values.append(&dst_node.id); + break; + } + case NODE_GROUP_INPUT: { + for_each_node_group_instance(bmain, tree, {NTREE_GEOMETRY}, [&](bNode &node_group) { + bNodeSocket &socket = node_group.input_by_identifier(dst.identifier); + Image **tmp_dst_value = &socket.default_value_typed()->value; + dst_values.append(reinterpret_cast(tmp_dst_value)); + }); + break; + } + default: { + break; + } + } + break; + } + default: { + break; + } + } + + for (ID **dst_value : dst_values) { + *dst_value = *src_socket_value; + id_us_plus(*dst_value); + } + + id_us_min(*src_socket_value); + *src_socket_value = nullptr; +} + bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool use_unique) { Map socket_map; diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index 58f6dc18447..ae0261a57b9 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -114,6 +114,9 @@ static void add_group_input_node_fn(nodes::LinkSearchOpParams ¶ms) /* Unhide the socket for the new input in the new node and make a connection to it. */ socket->flag &= ~SOCK_HIDDEN; nodeAddLink(¶ms.node_tree, &group_input, socket, ¶ms.node, ¶ms.socket); + + bke::node_socket_move_default_value( + *CTX_data_main(¶ms.C), params.node_tree, params.socket, *socket); } static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms, diff --git a/source/blender/nodes/intern/socket_search_link.cc b/source/blender/nodes/intern/socket_search_link.cc index 06ca17b43b5..75a9f24ad53 100644 --- a/source/blender/nodes/intern/socket_search_link.cc +++ b/source/blender/nodes/intern/socket_search_link.cc @@ -2,6 +2,7 @@ #include "BLI_set.hh" +#include "BKE_context.h" #include "BKE_node.h" #include "UI_interface.h" @@ -55,6 +56,11 @@ void LinkSearchOpParams::connect_available_socket(bNode &new_node, StringRef soc return; } nodeAddLink(&node_tree, &new_node, new_node_socket, &node, &socket); + if (in_out == SOCK_OUT) { + /* If the old socket already contained a value, then transfer it to a new one, from + * which this value will get there. */ + bke::node_socket_move_default_value(*CTX_data_main(&C), node_tree, socket, *new_node_socket); + } } bNode &LinkSearchOpParams::add_node(StringRef idname)