From f271a48b6bd4e9c44c8f60aa7f0a92264de9cbb8 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sat, 2 Aug 2025 14:09:06 +0200 Subject: [PATCH] Geometry Nodes: improve link-drag-search for bundle and closure nodes This adds support for creating Combine Bundle, Separate Bundle and Evaluate Closure nodes using link drag search in some cases that were not previously supported. Pull Request: https://projects.blender.org/blender/blender/pulls/143835 --- .../blender/nodes/NOD_socket_search_link.hh | 2 + .../geometry/nodes/node_geo_combine_bundle.cc | 34 ++++++++++----- .../nodes/node_geo_evaluate_closure.cc | 41 ++++++++++++++----- .../nodes/node_geo_separate_bundle.cc | 34 ++++++++++----- .../nodes/intern/socket_search_link.cc | 22 ++++++++-- 5 files changed, 98 insertions(+), 35 deletions(-) diff --git a/source/blender/nodes/NOD_socket_search_link.hh b/source/blender/nodes/NOD_socket_search_link.hh index 7c6fda80b6e..da27d64a411 100644 --- a/source/blender/nodes/NOD_socket_search_link.hh +++ b/source/blender/nodes/NOD_socket_search_link.hh @@ -56,6 +56,8 @@ class LinkSearchOpParams { * and connect it to the socket the link drag started from (#socket). */ void connect_available_socket(bNode &new_node, StringRef socket_name); + void connect_available_socket_by_identifier(bNode &new_node, StringRef socket_identifier); + void connect_socket(bNode &new_node, bNodeSocket &new_socket); /** * Like #connect_available_socket, but also calls the node's update function. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc b/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc index 3120e0b11de..b6717ddb220 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_combine_bundle.cc @@ -138,20 +138,32 @@ static void node_geo_exec(GeoNodeExecParams params) static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) { const bNodeSocket &other_socket = params.other_socket(); - if (other_socket.type != SOCK_BUNDLE) { - return; - } if (other_socket.in_out == SOCK_OUT) { - return; + if (!CombineBundleItemsAccessor::supports_socket_type(other_socket.typeinfo->type, + params.node_tree().type)) + { + return; + } + params.add_item("Item", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeCombineBundle"); + const auto *item = + socket_items::add_item_with_socket_type_and_name( + params.node_tree, node, params.socket.typeinfo->type, params.socket.name); + params.update_and_connect_available_socket(node, item->name); + }); } + else { + if (other_socket.type != SOCK_BUNDLE) { + return; + } + params.add_item("Bundle", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeCombineBundle"); + params.connect_available_socket(node, "Bundle"); - params.add_item("Bundle", [](LinkSearchOpParams ¶ms) { - bNode &node = params.add_node("NodeCombineBundle"); - params.connect_available_socket(node, "Bundle"); - - SpaceNode &snode = *CTX_wm_space_node(¶ms.C); - sync_sockets_combine_bundle(snode, node, nullptr); - }); + SpaceNode &snode = *CTX_wm_space_node(¶ms.C); + sync_sockets_combine_bundle(snode, node, nullptr); + }); + } } static void node_blend_write(const bNodeTree & /*tree*/, const bNode &node, BlendWriter &writer) diff --git a/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc b/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc index 916060b4e6e..b6f7b8dd1b3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc @@ -136,20 +136,41 @@ static const bNodeSocket *node_internally_linked_input(const bNodeTree & /*tree* static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) { const bNodeSocket &other_socket = params.other_socket(); - if (other_socket.type != SOCK_CLOSURE) { - return; - } if (other_socket.in_out == SOCK_IN) { + params.add_item("Item", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeEvaluateClosure"); + const auto *item = + socket_items::add_item_with_socket_type_and_name( + params.node_tree, node, params.socket.typeinfo->type, params.socket.name); + params.update_and_connect_available_socket(node, item->name); + }); return; } + if (other_socket.type == SOCK_CLOSURE) { + params.add_item("Closure", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeEvaluateClosure"); + params.connect_available_socket(node, "Closure"); - params.add_item("Closure", [](LinkSearchOpParams ¶ms) { - bNode &node = params.add_node("NodeEvaluateClosure"); - params.connect_available_socket(node, "Closure"); - - SpaceNode &snode = *CTX_wm_space_node(¶ms.C); - sync_sockets_evaluate_closure(snode, node, nullptr); - }); + SpaceNode &snode = *CTX_wm_space_node(¶ms.C); + sync_sockets_evaluate_closure(snode, node, nullptr); + }); + } + if (EvaluateClosureInputItemsAccessor::supports_socket_type(other_socket.typeinfo->type, + params.node_tree().type)) + { + params.add_item( + "Item", + [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeEvaluateClosure"); + const auto *item = + socket_items::add_item_with_socket_type_and_name( + params.node_tree, node, params.socket.typeinfo->type, params.socket.name); + nodes::update_node_declaration_and_sockets(params.node_tree, node); + params.connect_available_socket_by_identifier( + node, EvaluateClosureInputItemsAccessor::socket_identifier_for_item(*item)); + }, + other_socket.type == SOCK_CLOSURE ? -1 : 0); + } } static void node_operators() diff --git a/source/blender/nodes/geometry/nodes/node_geo_separate_bundle.cc b/source/blender/nodes/geometry/nodes/node_geo_separate_bundle.cc index c2b808c54f3..4b6da92c26e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_separate_bundle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_separate_bundle.cc @@ -185,20 +185,32 @@ static void node_geo_exec(GeoNodeExecParams params) static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) { const bNodeSocket &other_socket = params.other_socket(); - if (other_socket.type != SOCK_BUNDLE) { - return; - } if (other_socket.in_out == SOCK_IN) { - return; + if (!SeparateBundleItemsAccessor::supports_socket_type(other_socket.typeinfo->type, + params.node_tree().type)) + { + return; + } + params.add_item("Item", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeSeparateBundle"); + const auto *item = + socket_items::add_item_with_socket_type_and_name( + params.node_tree, node, params.socket.typeinfo->type, params.socket.name); + params.update_and_connect_available_socket(node, item->name); + }); } + else { + if (other_socket.type != SOCK_BUNDLE) { + return; + } + params.add_item("Bundle", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("NodeSeparateBundle"); + params.connect_available_socket(node, "Bundle"); - params.add_item("Bundle", [](LinkSearchOpParams ¶ms) { - bNode &node = params.add_node("NodeSeparateBundle"); - params.connect_available_socket(node, "Bundle"); - - SpaceNode &snode = *CTX_wm_space_node(¶ms.C); - sync_sockets_separate_bundle(snode, node, nullptr); - }); + SpaceNode &snode = *CTX_wm_space_node(¶ms.C); + sync_sockets_separate_bundle(snode, node, nullptr); + }); + } } static void node_blend_write(const bNodeTree & /*tree*/, const bNode &node, BlendWriter &writer) diff --git a/source/blender/nodes/intern/socket_search_link.cc b/source/blender/nodes/intern/socket_search_link.cc index f694ff69dce..5614e3dd4da 100644 --- a/source/blender/nodes/intern/socket_search_link.cc +++ b/source/blender/nodes/intern/socket_search_link.cc @@ -4,6 +4,7 @@ #include +#include "BLI_listbase.h" #include "BLI_set.hh" #include "BKE_context.hh" @@ -72,11 +73,26 @@ void LinkSearchOpParams::connect_available_socket(bNode &new_node, StringRef soc BLI_assert_unreachable(); return; } - bke::node_add_link(node_tree, new_node, *new_node_socket, node, socket); - if (in_out == SOCK_OUT) { + this->connect_socket(new_node, *new_node_socket); +} + +void LinkSearchOpParams::connect_available_socket_by_identifier(bNode &new_node, + const StringRef socket_identifier) +{ + const eNodeSocketInOut in_out = this->socket.in_out == SOCK_IN ? SOCK_OUT : SOCK_IN; + bNodeSocket *new_node_socket = bke::node_find_socket(new_node, in_out, socket_identifier); + BLI_assert(new_node_socket); + this->connect_socket(new_node, *new_node_socket); +} + +void LinkSearchOpParams::connect_socket(bNode &new_node, bNodeSocket &new_socket) +{ + bke::node_add_link(this->node_tree, new_node, new_socket, this->node, this->socket); + if (new_socket.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); + bke::node_socket_move_default_value( + *CTX_data_main(&C), this->node_tree, this->socket, new_socket); } }