From beae6a050eb110f4069662efa59f4e4dbfe5fe39 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 12 Jun 2025 11:28:47 +0200 Subject: [PATCH] Geometry Nodes: support creating Evaluate Closure node based on closure Similar to #140187. This allows creating an Evaluate Closure node with the right signature for an existing closure when using link-drag-search. Pull Request: https://projects.blender.org/blender/blender/pulls/140191 --- source/blender/editors/include/ED_node.hh | 8 +++ .../blender/editors/space_node/space_node.cc | 18 ++++++ .../nodes/node_geo_evaluate_closure.cc | 60 +++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/source/blender/editors/include/ED_node.hh b/source/blender/editors/include/ED_node.hh index 75503eb895f..51ef1eee4cd 100644 --- a/source/blender/editors/include/ED_node.hh +++ b/source/blender/editors/include/ED_node.hh @@ -130,6 +130,14 @@ bool node_editor_is_for_geometry_nodes_modifier(const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache, const std::optional &source_location); +/** + * Finds closure output nodes that are linked to the given closure socket. + */ +Vector gather_linked_closure_origin_nodes( + const ComputeContext *closure_socket_context, + const bNodeSocket &closure_socket, + bke::ComputeContextCache &compute_context_cache); + Vector gather_linked_separate_bundle_nodes( const ComputeContext *bundle_socket_context, const bNodeSocket &bundle_socket, diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index d25a9534a2f..5e4f3d5ecbc 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -773,6 +773,24 @@ static Vector find_origin_sockets_through_contexts( return found_origins.extract_vector(); } +Vector gather_linked_closure_origin_nodes( + const ComputeContext *closure_socket_context, + const bNodeSocket &closure_socket, + bke::ComputeContextCache &compute_context_cache) +{ + const Vector origin_sockets = find_origin_sockets_through_contexts( + {closure_socket_context, &closure_socket}, + compute_context_cache, + "GeometryNodeClosureOutput", + true); + Vector closure_origin_nodes; + for (const nodes::SocketInContext &origin_socket : origin_sockets) { + const nodes::NodeInContext &origin_node = origin_socket.owner_node(); + closure_origin_nodes.append(origin_node.node); + } + return closure_origin_nodes; +} + Vector gather_linked_combine_bundle_nodes( const ComputeContext *bundle_socket_context, const bNodeSocket &bundle_socket, 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 4df7244f405..11739d1627b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_evaluate_closure.cc @@ -5,10 +5,13 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "BKE_compute_context_cache.hh" + #include "NOD_geo_closure.hh" #include "NOD_socket_items_blend.hh" #include "NOD_socket_items_ops.hh" #include "NOD_socket_items_ui.hh" +#include "NOD_socket_search_link.hh" #include "BLO_read_write.hh" @@ -117,6 +120,62 @@ static const bNodeSocket *node_internally_linked_input(const bNodeTree & /*tree* return evaluate_closure_node_internally_linked_input(output_socket); } +static void try_initialize_evaluate_closure_node_from_origin_socket(SpaceNode &snode, + bNode &evaluate_closure_node) +{ + snode.edittree->ensure_topology_cache(); + bNodeSocket &closure_socket = evaluate_closure_node.input_socket(0); + + bke::ComputeContextCache compute_context_cache; + const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket( + snode, compute_context_cache, closure_socket); + if (!current_context) { + /* The current tree does not have a known context, e.g. it is pinned but the modifier has been + * removed. */ + return; + } + const Vector closure_origin_nodes = + ed::space_node::gather_linked_closure_origin_nodes( + current_context, closure_socket, compute_context_cache); + if (closure_origin_nodes.is_empty()) { + return; + } + const bNode &closure_node = *closure_origin_nodes[0]; + const NodeGeometryClosureOutput &closure_storage = + *static_cast(closure_node.storage); + + for (const int i : IndexRange(closure_storage.input_items.items_num)) { + const NodeGeometryClosureInputItem &item = closure_storage.input_items.items[i]; + socket_items::add_item_with_socket_type_and_name( + evaluate_closure_node, eNodeSocketDatatype(item.socket_type), item.name); + } + for (const int i : IndexRange(closure_storage.output_items.items_num)) { + const NodeGeometryClosureOutputItem &item = closure_storage.output_items.items[i]; + socket_items::add_item_with_socket_type_and_name( + evaluate_closure_node, eNodeSocketDatatype(item.socket_type), item.name); + } + BKE_ntree_update_tag_node_property(snode.edittree, &evaluate_closure_node); +} + +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) { + return; + } + + params.add_item("Closure", [](LinkSearchOpParams ¶ms) { + bNode &node = params.add_node("GeometryNodeEvaluateClosure"); + params.connect_available_socket(node, "Closure"); + + SpaceNode &snode = *CTX_wm_space_node(¶ms.C); + try_initialize_evaluate_closure_node_from_origin_socket(snode, node); + }); +} + static void node_operators() { socket_items::ops::make_common_operators(); @@ -147,6 +206,7 @@ static void node_register() ntype.insert_link = node_insert_link; ntype.draw_buttons_ex = node_layout_ex; ntype.internally_linked_input = node_internally_linked_input; + ntype.gather_link_search_ops = node_gather_link_searches; ntype.register_operators = node_operators; ntype.blend_write_storage_content = node_blend_write; ntype.blend_data_read_storage_content = node_blend_read;