diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt index 36d04971b14..95c2bb7802b 100644 --- a/source/blender/editors/curves/CMakeLists.txt +++ b/source/blender/editors/curves/CMakeLists.txt @@ -43,6 +43,7 @@ set(LIB PRIVATE bf::gpu PRIVATE bf::intern::clog PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::windowmanager ) diff --git a/source/blender/editors/include/ED_node.hh b/source/blender/editors/include/ED_node.hh index 6c932bb14db..0963263a949 100644 --- a/source/blender/editors/include/ED_node.hh +++ b/source/blender/editors/include/ED_node.hh @@ -12,6 +12,8 @@ #include "BKE_compute_context_cache_fwd.hh" +#include "NOD_geometry_nodes_closure_location.hh" + #include "ED_node_c.hh" struct SpaceNode; @@ -95,6 +97,17 @@ bool node_editor_is_for_geometry_nodes_modifier(const SpaceNode &snode, [[nodiscard]] const ComputeContext *compute_context_for_edittree( const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache); +/** + * Attempts to find a compute context that the closure is evaluated in. If none is found, null is + * returned. If multiple are found, it currently picks the first one it finds which is somewhat + * arbitrary. + */ +[[nodiscard]] const ComputeContext *compute_context_for_closure_evaluation( + const ComputeContext *closure_socket_context, + const bNodeSocket &closure_socket, + bke::ComputeContextCache &compute_context_cache, + const std::optional &source_location); + /** * Creates a compute context for the given zone. It takes e.g. the current inspection index into * account. diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index 86cda299108..4c23729b9cd 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -6,6 +6,7 @@ set(INC ../asset ../include ../../makesrna + ../../nodes ../../../../extern/fmtlib/include # RNA_prototypes.hh ${CMAKE_BINARY_DIR}/source/blender/makesrna diff --git a/source/blender/editors/space_api/CMakeLists.txt b/source/blender/editors/space_api/CMakeLists.txt index a02675813ba..b563e844bde 100644 --- a/source/blender/editors/space_api/CMakeLists.txt +++ b/source/blender/editors/space_api/CMakeLists.txt @@ -43,6 +43,7 @@ set(LIB bf_editor_space_view3d PRIVATE bf::gpu PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::windowmanager ) diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index 66632c909eb..3ac69ab3e85 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -31,6 +31,7 @@ set(LIB PRIVATE bf::dna PRIVATE bf::gpu PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::windowmanager ) diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index b43ba31881f..b4bc2e1bd89 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -42,6 +42,7 @@ set(LIB PRIVATE bf::imbuf::movie PRIVATE bf::intern::clog PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::render PRIVATE bf::windowmanager ) diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index c3dec6753f0..61250e54940 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -10,6 +10,7 @@ #include "BLI_listbase.h" #include "BLI_math_vector.h" +#include "BLI_stack.hh" #include "BLI_string.h" #include "DNA_ID.h" @@ -49,6 +50,7 @@ #include "UI_view2d.hh" #include "DEG_depsgraph.hh" +#include "DEG_depsgraph_query.hh" #include "BLO_read_write.hh" @@ -60,7 +62,8 @@ #include "WM_api.hh" #include "WM_types.hh" -#include "DEG_depsgraph_query.hh" +#include "NOD_node_in_compute_context.hh" +#include "NOD_socket_interface_key.hh" #include "io_utils.hh" @@ -386,8 +389,15 @@ const ComputeContext *compute_context_for_zone(const bke::bNodeTreeZone &zone, parent_compute_context, *zone.output_node, storage.inspection_index); } case GEO_NODE_CLOSURE_OUTPUT: { - /* TODO: Need to find a place where this closure is evaluated. */ - return nullptr; + nodes::ClosureSourceLocation source_location{}; + const bNodeTree &tree = output_node.owner_tree(); + BLI_assert(DEG_is_original_id(&tree.id)); + source_location.orig_node_tree_session_uid = tree.id.session_uid; + source_location.closure_output_node_id = output_node.identifier; + return compute_context_for_closure_evaluation(parent_compute_context, + output_node.output_socket(0), + compute_context_cache, + source_location); } } return nullptr; @@ -444,6 +454,127 @@ static std::optional compute_context_for_tree_path( return current; } +[[nodiscard]] const ComputeContext *compute_context_for_closure_evaluation( + const ComputeContext *closure_socket_context, + const bNodeSocket &closure_socket, + bke::ComputeContextCache &compute_context_cache, + const std::optional &source_location) +{ + using BundlePath = Vector; + + struct SocketToCheck { + nodes::SocketInContext socket; + BundlePath bundle_path; + }; + + Stack sockets_to_check; + Set added_sockets; + + auto add_if_new = [&](const nodes::SocketInContext &socket, BundlePath bundle_path) { + if (added_sockets.add(socket)) { + sockets_to_check.push({socket, std::move(bundle_path)}); + } + }; + + const nodes::SocketInContext start_socket{closure_socket_context, &closure_socket}; + add_if_new(start_socket, {}); + + while (!sockets_to_check.is_empty()) { + const SocketToCheck socket_to_check = sockets_to_check.pop(); + const nodes::SocketInContext socket = socket_to_check.socket; + const BundlePath &bundle_path = socket_to_check.bundle_path; + const nodes::NodeInContext &node = socket.owner_node(); + if (socket->is_input()) { + if (node->is_muted()) { + for (const bNodeLink &link : node->internal_links()) { + if (link.fromsock == socket.socket) { + add_if_new({socket.context, link.tosock}, bundle_path); + } + } + continue; + } + if (node->is_type("GeometryNodeEvaluateClosure")) { + return &compute_context_cache.for_evaluate_closure(socket.context, *node, source_location); + } + if (node->is_group()) { + if (const bNodeTree *group = reinterpret_cast(node->id)) { + group->ensure_topology_cache(); + const ComputeContext &group_compute_context = compute_context_cache.for_group_node( + socket.context, *node, node->owner_tree()); + for (const bNode *input_node : group->group_input_nodes()) { + const bNodeSocket &group_input_socket = input_node->output_socket(socket->index()); + if (group_input_socket.is_directly_linked()) { + add_if_new({&group_compute_context, &group_input_socket}, bundle_path); + } + } + } + continue; + } + if (node->is_group_output()) { + if (const auto *group_context = dynamic_cast( + socket.context)) + { + const bNodeTree *caller_group = group_context->caller_tree(); + const bNode *caller_group_node = group_context->caller_group_node(); + if (caller_group && caller_group_node) { + caller_group->ensure_topology_cache(); + const bNodeSocket &output_socket = caller_group_node->output_socket(socket->index()); + add_if_new({group_context->parent(), &output_socket}, bundle_path); + } + } + continue; + } + if (node->is_type("GeometryNodeCombineBundle")) { + const auto &storage = *static_cast(node->storage); + BundlePath new_bundle_path = bundle_path; + new_bundle_path.append(nodes::SocketInterfaceKey{storage.items[socket->index()].name}); + add_if_new(node.output_socket(0), std::move(new_bundle_path)); + continue; + } + if (node->is_type("GeometryNodeSeparateBundle")) { + if (bundle_path.is_empty()) { + continue; + } + const nodes::SocketInterfaceKey &last_key = bundle_path.last(); + const auto &storage = *static_cast(node->storage); + for (const int output_i : IndexRange(storage.items_num)) { + const nodes::SocketInterfaceKey key{storage.items[output_i].name}; + if (last_key.matches(key)) { + add_if_new(node.output_socket(output_i), bundle_path.as_span().drop_back(1)); + } + } + continue; + } + } + else { + const bke::bNodeTreeZones *zones = node->owner_tree().zones(); + if (!zones) { + continue; + } + const bke::bNodeTreeZone *from_zone = zones->get_zone_by_socket(*socket.socket); + for (const bNodeLink *link : socket->directly_linked_links()) { + if (!link->is_used()) { + continue; + } + bNodeSocket *to_socket = link->tosock; + const bke::bNodeTreeZone *to_zone = zones->get_zone_by_socket(*to_socket); + if (!zones->link_between_zones_is_allowed(from_zone, to_zone)) { + continue; + } + const Vector zones_to_enter = zones->get_zones_to_enter( + from_zone, to_zone); + const ComputeContext *compute_context = compute_context_for_zones( + zones_to_enter, compute_context_cache, socket.context); + if (!compute_context) { + continue; + } + add_if_new({compute_context, to_socket}, bundle_path); + } + } + } + return nullptr; +} + static const ComputeContext *get_node_editor_root_compute_context( const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache) { diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 301d8b19679..0b6f62e2924 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -140,6 +140,7 @@ set(LIB PRIVATE bf::imbuf PRIVATE bf::intern::clog PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::sequencer PRIVATE bf::windowmanager extern_fmtlib diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 6626e6e3182..ae8205b394a 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -118,6 +118,7 @@ set(LIB bf_editor_mask PRIVATE bf::gpu PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::render PRIVATE bf::sequencer PRIVATE bf::windowmanager diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index dfa6fd59728..369366b4d7a 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -41,6 +41,7 @@ set(LIB PRIVATE bf::geometry PRIVATE bf::gpu PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::windowmanager ) diff --git a/source/blender/io/collada/CMakeLists.txt b/source/blender/io/collada/CMakeLists.txt index b7ccb49df34..32cbb4cb2e6 100644 --- a/source/blender/io/collada/CMakeLists.txt +++ b/source/blender/io/collada/CMakeLists.txt @@ -116,6 +116,7 @@ set(LIB PRIVATE bf::dna PRIVATE bf::imbuf PRIVATE bf::intern::guardedalloc + PRIVATE bf::nodes PRIVATE bf::windowmanager )