Blender V5.0
trace_values.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_stack.hh"
6
12#include "NOD_trace_values.hh"
13
16
17#include "ED_node.hh"
18
19namespace blender::nodes {
20
22{
23 return socket->is_input() && socket->index() == 0 &&
24 socket.owner_node()->is_type("NodeEvaluateClosure");
25}
26
28{
29 return socket->owner_node().is_type("NodeClosureOutput") && socket->is_output();
30}
31
32static bool use_link_for_tracing(const bNodeLink &link)
33{
34 if (!link.is_used()) {
35 return false;
36 }
37 const bNodeTree &tree = link.fromnode->owner_tree();
38 if (tree.typeinfo->validate_link &&
39 !tree.typeinfo->validate_link(eNodeSocketDatatype(link.fromsock->type),
41 {
42 return false;
43 }
44 return true;
45}
46
48 SocketInContext start_socket,
49 bke::ComputeContextCache &compute_context_cache,
50 FunctionRef<bool(const SocketInContext &)> handle_possible_origin_socket_fn,
51 bool find_all);
52
54 const SocketInContext start_socket,
55 bke::ComputeContextCache &compute_context_cache,
56 const FunctionRef<bool(const SocketInContext &)> handle_possible_target_socket_fn,
57 const bool find_all)
58{
59 using BundlePath = Vector<std::string, 0>;
60
61 struct SocketToCheck {
62 SocketInContext socket;
63 BundlePath bundle_path;
64 };
65
66 Stack<SocketToCheck> sockets_to_check;
67 Set<SocketInContext> added_sockets;
68
69 auto add_if_new = [&](const SocketInContext &socket, BundlePath bundle_path) {
70 if (added_sockets.add(socket)) {
71 sockets_to_check.push({socket, std::move(bundle_path)});
72 }
73 };
74
75 add_if_new(start_socket, {});
76
77 VectorSet<SocketInContext> found_targets;
78
79 while (!sockets_to_check.is_empty()) {
80 const SocketToCheck socket_to_check = sockets_to_check.pop();
81 const SocketInContext socket = socket_to_check.socket;
82 const BundlePath &bundle_path = socket_to_check.bundle_path;
83 const NodeInContext &node = socket.owner_node();
84 if (socket->is_input()) {
85 if (node->is_muted()) {
86 for (const bNodeLink &link : node->internal_links()) {
87 if (link.fromsock == socket.socket) {
88 add_if_new({socket.context, link.tosock}, bundle_path);
89 }
90 }
91 continue;
92 }
93 if (bundle_path.is_empty() && handle_possible_target_socket_fn(socket)) {
94 found_targets.add(socket);
95 if (!find_all) {
96 break;
97 }
98 continue;
99 }
100 if (node->is_reroute()) {
101 add_if_new(node.output_socket(0), bundle_path);
102 continue;
103 }
104 if (node->is_group()) {
105 if (const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id)) {
106 group->ensure_topology_cache();
107 const ComputeContext &group_compute_context = compute_context_cache.for_group_node(
108 socket.context, node->identifier, &node->owner_tree());
109 for (const bNode *input_node : group->group_input_nodes()) {
110 if (const bNodeSocket *group_input_socket = input_node->output_by_identifier(
111 socket->identifier))
112 {
113 if (group_input_socket->is_directly_linked()) {
114 add_if_new({&group_compute_context, group_input_socket}, bundle_path);
115 }
116 }
117 }
118 }
119 continue;
120 }
121 if (node->is_group_output()) {
122 if (const auto *group_context = dynamic_cast<const bke::GroupNodeComputeContext *>(
123 socket.context))
124 {
125 const bNodeTree *caller_group = group_context->tree();
126 const bNode *caller_group_node = group_context->node();
127 if (caller_group && caller_group_node) {
128 caller_group->ensure_topology_cache();
129 if (const bNodeSocket *output_socket = caller_group_node->output_by_identifier(
130 socket->identifier))
131 {
132 add_if_new({group_context->parent(), output_socket}, bundle_path);
133 }
134 }
135 }
136 continue;
137 }
138 if (node->is_type("NodeCombineBundle")) {
139 const auto &storage = *static_cast<const NodeCombineBundle *>(node->storage);
140 BundlePath new_bundle_path = bundle_path;
141 new_bundle_path.append(storage.items[socket->index()].name);
142 add_if_new(node.output_socket(0), std::move(new_bundle_path));
143 continue;
144 }
145 if (node->is_type("NodeSeparateBundle")) {
146 if (bundle_path.is_empty()) {
147 continue;
148 }
149 const StringRef last_key = bundle_path.last();
150 const auto &storage = *static_cast<const NodeSeparateBundle *>(node->storage);
151 for (const int output_i : IndexRange(storage.items_num)) {
152 if (last_key == storage.items[output_i].name) {
153 add_if_new(node.output_socket(output_i), bundle_path.as_span().drop_back(1));
154 }
155 }
156 continue;
157 }
158 if (node->is_type("NodeClosureOutput")) {
159 const auto &closure_storage = *static_cast<const NodeClosureOutput *>(node->storage);
160 const StringRef key = closure_storage.output_items.items[socket->index()].name;
162 node.output_socket(0), compute_context_cache, is_evaluate_closure_node_input, true);
163 for (const auto &target_socket : target_sockets) {
164 const NodeInContext evaluate_node = target_socket.owner_node();
165 const auto &evaluate_storage = *static_cast<const NodeEvaluateClosure *>(
166 evaluate_node->storage);
167 for (const int i : IndexRange(evaluate_storage.output_items.items_num)) {
168 const NodeEvaluateClosureOutputItem &item = evaluate_storage.output_items.items[i];
169 if (key == item.name) {
170 add_if_new(evaluate_node.output_socket(i), bundle_path);
171 }
172 }
173 }
174 continue;
175 }
176 if (node->is_type("NodeEvaluateClosure")) {
177 if (socket->index() == 0) {
178 continue;
179 }
180 const auto &evaluate_storage = *static_cast<const NodeEvaluateClosure *>(node->storage);
181 const StringRef key = evaluate_storage.input_items.items[socket->index() - 1].name;
183 node.input_socket(0), compute_context_cache, is_closure_zone_output_socket, true);
184 for (const SocketInContext origin_socket : origin_sockets) {
185 const bNodeTree &closure_tree = origin_socket->owner_tree();
186 const bke::bNodeTreeZones *closure_tree_zones = closure_tree.zones();
187 if (!closure_tree_zones) {
188 continue;
189 }
190 const auto &closure_output_node = origin_socket.owner_node();
191 const bke::bNodeTreeZone *closure_zone = closure_tree_zones->get_zone_by_node(
192 closure_output_node->identifier);
193 if (!closure_zone) {
194 continue;
195 }
196 const bNode *closure_input_node = closure_zone->input_node();
197 if (!closure_input_node) {
198 continue;
199 }
200 const bke::EvaluateClosureComputeContext &closure_context =
201 compute_context_cache.for_evaluate_closure(
202 node.context,
203 node->identifier,
204 &node->owner_tree(),
205 ClosureSourceLocation{&closure_tree,
206 closure_output_node->identifier,
207 origin_socket.context_hash(),
208 origin_socket.context});
209 if (closure_context.is_recursive()) {
210 continue;
211 }
212 const auto &closure_output_storage = *static_cast<const NodeClosureOutput *>(
213 closure_output_node->storage);
214 for (const int i : IndexRange(closure_output_storage.input_items.items_num)) {
215 const NodeClosureInputItem &item = closure_output_storage.input_items.items[i];
216 if (key == item.name) {
217 add_if_new({&closure_context, &closure_input_node->output_socket(i)}, bundle_path);
218 }
219 }
220 }
221 continue;
222 }
223 if (node->is_type("GeometryNodeSimulationInput")) {
224 const ComputeContext &simulation_compute_context =
225 compute_context_cache.for_simulation_zone(socket.context, *node);
226 add_if_new({&simulation_compute_context, &node->output_socket(socket->index() + 1)},
227 bundle_path);
228 continue;
229 }
230 if (node->is_type("GeometryNodeSimulationOutput")) {
231 const int output_index = socket->index();
232 if (output_index >= 1) {
233 BLI_assert(dynamic_cast<const bke::SimulationZoneComputeContext *>(socket.context));
234 add_if_new({socket.context->parent(), &node->output_socket(output_index - 1)},
235 bundle_path);
236 }
237 continue;
238 }
239 if (node->is_type("GeometryNodeRepeatInput")) {
240 const int index = socket->index();
241 if (index >= 1) {
242 const ComputeContext &repeat_compute_context = compute_context_cache.for_repeat_zone(
243 socket.context, *node, 0);
244 add_if_new({&repeat_compute_context, &node->output_socket(index)}, bundle_path);
245 const auto &storage = *static_cast<NodeGeometryRepeatInput *>(node->storage);
246 if (const bNode *repeat_output_node = node->owner_tree().node_by_id(
247 storage.output_node_id))
248 {
249 add_if_new({socket.context, &repeat_output_node->output_socket(index - 1)},
250 bundle_path);
251 }
252 }
253 continue;
254 }
255 if (node->is_type("GeometryNodeRepeatOutput")) {
256 BLI_assert(dynamic_cast<const bke::RepeatZoneComputeContext *>(socket.context));
257 add_if_new({socket.context->parent(), &node->output_socket(socket->index())}, bundle_path);
258 continue;
259 }
260 for (const bNodeSocket *output_socket : node->output_sockets()) {
261 const SocketDeclaration *output_decl = output_socket->runtime->declaration;
262 if (!output_decl) {
263 continue;
264 }
265 if (const decl::Bundle *bundle_decl = dynamic_cast<const decl::Bundle *>(output_decl)) {
266 if (bundle_decl->pass_through_input_index == socket->index()) {
267 add_if_new({socket.context, output_socket}, bundle_path);
268 }
269 }
270 }
271 }
272 else {
273 const bke::bNodeTreeZones *zones = node->owner_tree().zones();
274 if (!zones) {
275 continue;
276 }
277 const bke::bNodeTreeZone *from_zone = zones->get_zone_by_socket(*socket.socket);
278 for (const bNodeLink *link : socket->directly_linked_links()) {
279 if (!use_link_for_tracing(*link)) {
280 continue;
281 }
282 bNodeSocket *to_socket = link->tosock;
283 const bke::bNodeTreeZone *to_zone = zones->get_zone_by_socket(*to_socket);
284 if (!zones->link_between_zones_is_allowed(from_zone, to_zone)) {
285 continue;
286 }
287 const Vector<const bke::bNodeTreeZone *> zones_to_enter = zones->get_zones_to_enter(
288 from_zone, to_zone);
290 zones_to_enter, compute_context_cache, socket.context);
291 if (!compute_context) {
292 continue;
293 }
294 add_if_new({compute_context, to_socket}, bundle_path);
295 }
296 }
297 }
298 return found_targets.extract_vector();
299}
300
302 const ComputeContext *closure_socket_context,
303 const bNodeSocket &closure_socket,
304 bke::ComputeContextCache &compute_context_cache,
305 const std::optional<ClosureSourceLocation> &source_location)
306{
308 {closure_socket_context, &closure_socket},
309 compute_context_cache,
311 false);
312 if (target_sockets.is_empty()) {
313 return nullptr;
314 }
315 const SocketInContext target_socket = target_sockets[0];
316 const NodeInContext target_node = target_socket.owner_node();
317 return &compute_context_cache.for_evaluate_closure(target_socket.context,
318 target_node->identifier,
319 &target_socket->owner_tree(),
320 source_location);
321}
322
324 const SocketInContext start_socket,
325 bke::ComputeContextCache &compute_context_cache,
326 const FunctionRef<bool(const SocketInContext &)> handle_possible_origin_socket_fn,
327 const bool find_all)
328{
329 using BundlePath = Vector<std::string, 0>;
330
331 struct SocketToCheck {
332 SocketInContext socket;
333 BundlePath bundle_path;
334 };
335
336 Stack<SocketToCheck> sockets_to_check;
337 Set<SocketInContext> added_sockets;
338
339 auto add_if_new = [&](const SocketInContext &socket, BundlePath bundle_path) {
340 if (added_sockets.add(socket)) {
341 sockets_to_check.push({socket, std::move(bundle_path)});
342 }
343 };
344
345 add_if_new(start_socket, {});
346
347 VectorSet<SocketInContext> found_origins;
348
349 while (!sockets_to_check.is_empty()) {
350 const SocketToCheck socket_to_check = sockets_to_check.pop();
351 const SocketInContext socket = socket_to_check.socket;
352 const BundlePath &bundle_path = socket_to_check.bundle_path;
353 const NodeInContext &node = socket.owner_node();
354 const SocketDeclaration *socket_decl = socket->runtime->declaration;
355 if (socket->is_input()) {
356 if (bundle_path.is_empty() && handle_possible_origin_socket_fn(socket)) {
357 found_origins.add(socket);
358 if (!find_all) {
359 break;
360 }
361 continue;
362 }
363 const bke::bNodeTreeZones *zones = node->owner_tree().zones();
364 if (!zones) {
365 continue;
366 }
367 const bke::bNodeTreeZone *to_zone = zones->get_zone_by_socket(*socket.socket);
368 for (const bNodeLink *link : socket->directly_linked_links()) {
369 if (!use_link_for_tracing(*link)) {
370 continue;
371 }
372 const bNodeSocket *from_socket = link->fromsock;
373 const bke::bNodeTreeZone *from_zone = zones->get_zone_by_socket(*from_socket);
374 if (!zones->link_between_zones_is_allowed(from_zone, to_zone)) {
375 continue;
376 }
377 const ComputeContext *compute_context = socket.context;
378 for (const bke::bNodeTreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone)
379 {
380 if (const auto *evaluate_closure_context =
381 dynamic_cast<const bke::EvaluateClosureComputeContext *>(compute_context))
382 {
383 const std::optional<nodes::ClosureSourceLocation> &source_location =
384 evaluate_closure_context->closure_source_location();
385 /* This is expected to be available during value tracing. */
386 BLI_assert(source_location);
387 BLI_assert(source_location->compute_context);
388 compute_context = source_location->compute_context;
389 }
390 else {
391 compute_context = compute_context->parent();
392 }
393 }
394 add_if_new({compute_context, from_socket}, bundle_path);
395 }
396 }
397 else {
398 if (node->is_muted()) {
399 for (const bNodeLink &link : node->internal_links()) {
400 if (link.tosock == socket.socket) {
401 add_if_new({socket.context, link.fromsock}, bundle_path);
402 }
403 }
404 continue;
405 }
406 if (bundle_path.is_empty() && handle_possible_origin_socket_fn(socket)) {
407 found_origins.add(socket);
408 if (!find_all) {
409 break;
410 }
411 continue;
412 }
413 if (node->is_reroute()) {
414 add_if_new(node.input_socket(0), bundle_path);
415 continue;
416 }
417 if (node->is_group()) {
418 if (const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id)) {
419 group->ensure_topology_cache();
420 if (const bNode *group_output_node = group->group_output_node()) {
421 const ComputeContext &group_compute_context = compute_context_cache.for_group_node(
422 socket.context, node->identifier, &node->owner_tree());
423 if (const bNodeSocket *group_output_socket = group_output_node->input_by_identifier(
424 socket->identifier))
425 {
426 add_if_new({&group_compute_context, group_output_socket}, bundle_path);
427 }
428 }
429 }
430 continue;
431 }
432 if (node->is_group_input()) {
433 if (const auto *group_context = dynamic_cast<const bke::GroupNodeComputeContext *>(
434 socket.context))
435 {
436 const bNodeTree *caller_group = group_context->tree();
437 const bNode *caller_group_node = group_context->node();
438 if (caller_group && caller_group_node) {
439 caller_group->ensure_topology_cache();
440 if (const bNodeSocket *input_socket = caller_group_node->input_by_identifier(
441 socket->identifier))
442 {
443 add_if_new({group_context->parent(), input_socket}, bundle_path);
444 }
445 }
446 }
447 continue;
448 }
449 if (node->is_type("NodeJoinBundle")) {
450 add_if_new(node.input_socket(0), bundle_path);
451 continue;
452 }
453 if (node->is_type("NodeEvaluateClosure")) {
454 const auto &evaluate_storage = *static_cast<const NodeEvaluateClosure *>(node->storage);
455 const StringRef key = evaluate_storage.output_items.items[socket->index()].name;
457 node.input_socket(0), compute_context_cache, is_closure_zone_output_socket, true);
458 for (const SocketInContext origin_socket : origin_sockets) {
459 const bNodeTree &closure_tree = origin_socket->owner_tree();
460 const NodeInContext closure_output_node = origin_socket.owner_node();
461 const auto &closure_storage = *static_cast<const NodeClosureOutput *>(
462 closure_output_node->storage);
463 const bke::EvaluateClosureComputeContext &closure_context =
464 compute_context_cache.for_evaluate_closure(
465 node.context,
466 node->identifier,
467 &node->owner_tree(),
468 ClosureSourceLocation{&closure_tree,
469 closure_output_node->identifier,
470 origin_socket.context_hash(),
471 origin_socket.context});
472 if (closure_context.is_recursive()) {
473 continue;
474 }
475 for (const int i : IndexRange(closure_storage.output_items.items_num)) {
476 const NodeClosureOutputItem &item = closure_storage.output_items.items[i];
477 if (key == item.name) {
478 add_if_new({&closure_context, &closure_output_node->input_socket(i)}, bundle_path);
479 }
480 }
481 }
482 continue;
483 }
484 if (node->is_type("NodeClosureInput")) {
485 const auto &input_storage = *static_cast<const NodeClosureInput *>(node->storage);
486 const bNode *closure_output_node = node->owner_tree().node_by_id(
487 input_storage.output_node_id);
488 if (!closure_output_node) {
489 continue;
490 }
491 const auto &output_storage = *static_cast<const NodeClosureOutput *>(
492 closure_output_node->storage);
493 const StringRef key = output_storage.input_items.items[socket->index()].name;
494 const bNodeSocket &closure_output_socket = closure_output_node->output_socket(0);
496 {socket.context, &closure_output_socket},
497 compute_context_cache,
499 true);
500 for (const SocketInContext &target_socket : target_sockets) {
501 const NodeInContext target_node = target_socket.owner_node();
502 const auto &evaluate_storage = *static_cast<const NodeEvaluateClosure *>(
503 target_node.node->storage);
504 for (const int i : IndexRange(evaluate_storage.input_items.items_num)) {
505 const NodeEvaluateClosureInputItem &item = evaluate_storage.input_items.items[i];
506 if (key == item.name) {
507 add_if_new(target_node.input_socket(i + 1), bundle_path);
508 }
509 }
510 }
511 continue;
512 }
513 if (node->is_type("NodeCombineBundle")) {
514 if (bundle_path.is_empty()) {
515 continue;
516 }
517 const StringRef last_key = bundle_path.last();
518 const auto &storage = *static_cast<const NodeCombineBundle *>(node->storage);
519 for (const int input_i : IndexRange(storage.items_num)) {
520 if (last_key == storage.items[input_i].name) {
521 add_if_new(node.input_socket(input_i), bundle_path.as_span().drop_back(1));
522 }
523 }
524 continue;
525 }
526 if (node->is_type("NodeSeparateBundle")) {
527 const auto &storage = *static_cast<const NodeSeparateBundle *>(node->storage);
528 BundlePath new_bundle_path = bundle_path;
529 new_bundle_path.append(storage.items[socket->index()].name);
530 add_if_new(node.input_socket(0), std::move(new_bundle_path));
531 continue;
532 }
533 if (node->is_type("GeometryNodeSimulationInput")) {
534 const int output_index = socket->index();
535 if (output_index >= 1) {
536 BLI_assert(dynamic_cast<const bke::SimulationZoneComputeContext *>(socket.context));
537 add_if_new({socket.context->parent(), &node->input_socket(output_index - 1)},
538 bundle_path);
539 }
540 continue;
541 }
542 if (node->is_type("GeometryNodeSimulationOutput")) {
543 const ComputeContext &simulation_compute_context =
544 compute_context_cache.for_simulation_zone(socket.context, *node);
545 add_if_new({&simulation_compute_context, &node->input_socket(socket->index() + 1)},
546 bundle_path);
547 continue;
548 }
549 if (node->is_type("GeometryNodeRepeatInput")) {
550 const int index = socket->index();
551 if (index >= 1) {
552 BLI_assert(dynamic_cast<const bke::RepeatZoneComputeContext *>(socket.context));
553 add_if_new({socket.context->parent(), &node->input_socket(index)}, bundle_path);
554 }
555 continue;
556 }
557 if (node->is_type("GeometryNodeRepeatOutput")) {
558 const int index = socket->index();
559 const ComputeContext &repeat_compute_context = compute_context_cache.for_repeat_zone(
560 socket.context, *node, 0);
561 add_if_new({&repeat_compute_context, &node->input_socket(index)}, bundle_path);
563 if (const bNode *repeat_input_node = zone_type.get_corresponding_input(node->owner_tree(),
564 *node))
565 {
566 add_if_new({socket.context, &repeat_input_node->input_socket(index + 1)}, bundle_path);
567 }
568 continue;
569 }
570 if (socket_decl) {
571 if (const decl::Bundle *bundle_decl = dynamic_cast<const decl::Bundle *>(socket_decl)) {
572 if (bundle_decl->pass_through_input_index) {
573 const int input_index = *bundle_decl->pass_through_input_index;
574 add_if_new(node.input_socket(input_index), bundle_path);
575 }
576 }
577 }
578 }
579 }
580
581 return found_origins.extract_vector();
582}
583
585 const ComputeContext *bundle_socket_context,
586 const bNodeSocket &bundle_socket,
587 bke::ComputeContextCache &compute_context_cache)
588{
591 {bundle_socket_context, &bundle_socket},
592 compute_context_cache,
593 [&](const SocketInContext &socket) {
594 const bNode &node = socket->owner_node();
595 if (socket->is_input() && node.is_type("NodeSeparateBundle")) {
596 const auto &storage = *static_cast<const NodeSeparateBundle *>(node.storage);
597 result.items.append({BundleSignature::from_separate_bundle_node(node, false),
599 socket});
600 return true;
601 }
602 return false;
603 },
604 true);
605 return result;
606}
607
609 const ComputeContext *bundle_socket_context,
610 const bNodeSocket &bundle_socket,
611 bke::ComputeContextCache &compute_context_cache)
612{
615 {bundle_socket_context, &bundle_socket},
616 compute_context_cache,
617 [&](const SocketInContext &socket) {
618 const NodeInContext node = socket.owner_node();
619 if (socket->is_output()) {
620 if (node->is_type("NodeCombineBundle")) {
621 const auto &storage = *static_cast<const NodeCombineBundle *>(node->storage);
622 result.items.append({BundleSignature::from_combine_bundle_node(*node, false),
624 socket});
625 return true;
626 }
627 }
628 if (node->is_type("NodeJoinBundle")) {
629 const SocketInContext input_socket = node.input_socket(0);
630 BundleSignature joined_signature;
631 bool is_signature_definition = true;
632 for (const bNodeLink *link : input_socket->directly_linked_links()) {
633 if (!link->is_used()) {
634 continue;
635 }
636 const bNodeSocket *socket_from = link->fromsock;
638 node.context, *socket_from, compute_context_cache);
639 for (const LinkedBundleSignatures::Item &sub_signature : sub_signatures.items) {
640 if (!sub_signature.is_signature_definition) {
641 is_signature_definition = false;
642 }
643 for (const BundleSignature::Item &item : sub_signature.signature.items) {
644 joined_signature.items.add(item);
645 }
646 }
647 }
648 result.items.append({joined_signature, is_signature_definition, socket});
649 return true;
650 }
651 return false;
652 },
653 true);
654 return result;
655}
656
658 const ComputeContext *closure_socket_context,
659 const bNodeSocket &closure_socket,
660 bke::ComputeContextCache &compute_context_cache)
661{
664 {closure_socket_context, &closure_socket},
665 compute_context_cache,
666 [&](const SocketInContext &socket) {
667 const bNode &node = socket->owner_node();
668 if (is_evaluate_closure_node_input(socket)) {
669 const auto &storage = *static_cast<const NodeEvaluateClosure *>(node.storage);
670 result.items.append({ClosureSignature::from_evaluate_closure_node(node, false),
672 socket});
673 return true;
674 }
675 return false;
676 },
677 true);
678 return result;
679}
680
682 const ComputeContext *closure_socket_context,
683 const bNodeSocket &closure_socket,
684 bke::ComputeContextCache &compute_context_cache)
685{
688 {closure_socket_context, &closure_socket},
689 compute_context_cache,
690 [&](const SocketInContext &socket) {
691 const bNode &node = socket->owner_node();
692 if (is_closure_zone_output_socket(socket)) {
693 const auto &storage = *static_cast<const NodeClosureOutput *>(node.storage);
694 result.items.append({ClosureSignature::from_closure_output_node(node, false),
695 bool(storage.flag & NODE_CLOSURE_FLAG_DEFINE_SIGNATURE),
696 socket});
697 return true;
698 }
699 return false;
700 },
701 true);
702 return result;
703}
704
705std::optional<NodeInContext> find_origin_index_menu_switch(
706 const SocketInContext &src_socket, bke::ComputeContextCache &compute_context_cache)
707{
708 std::optional<NodeInContext> result;
710 src_socket,
711 compute_context_cache,
712 [&](const SocketInContext &socket) {
713 if (socket->is_input()) {
714 return false;
715 }
716 const NodeInContext node = socket.owner_node();
717 if (!node->is_type("GeometryNodeMenuSwitch")) {
718 return false;
719 }
720 const auto &storage = *static_cast<const NodeMenuSwitch *>(node->storage);
721 if (storage.data_type != SOCK_INT) {
722 return false;
723 }
724 result = socket.owner_node();
725 return true;
726 },
727 false);
728 return result;
729}
730
731} // namespace blender::nodes
#define BLI_assert(a)
Definition BLI_assert.h:46
@ NODE_CLOSURE_FLAG_DEFINE_SIGNATURE
@ NODE_SEPARATE_BUNDLE_FLAG_DEFINE_SIGNATURE
eNodeSocketDatatype
@ SOCK_INT
@ NODE_COMBINE_BUNDLE_FLAG_DEFINE_SIGNATURE
@ NODE_EVALUATE_CLOSURE_FLAG_DEFINE_SIGNATURE
const ComputeContext * parent() const
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_stack.hh:308
void push(const T &value)
Definition BLI_stack.hh:213
bool is_empty() const
const EvaluateClosureComputeContext & for_evaluate_closure(const ComputeContext *parent, int32_t node_id, const bNodeTree *tree=nullptr, const std::optional< nodes::ClosureSourceLocation > &closure_source_location=std::nullopt)
const GroupNodeComputeContext & for_group_node(const ComputeContext *parent, int32_t node_id, const bNodeTree *tree=nullptr)
const RepeatZoneComputeContext & for_repeat_zone(const ComputeContext *parent, int32_t output_node_id, int iteration)
const SimulationZoneComputeContext & for_simulation_zone(const ComputeContext *parent, int output_node_id)
const bNode * input_node() const
Vector< const bNodeTreeZone * > get_zones_to_enter(const bNodeTreeZone *outer_zone, const bNodeTreeZone *inner_zone) const
bool link_between_zones_is_allowed(const bNodeTreeZone *from_zone, const bNodeTreeZone *to_zone) const
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
const bNodeTreeZone * get_zone_by_socket(const bNodeSocket &socket) const
static ClosureSignature from_evaluate_closure_node(const bNode &node, bool allow_auto_structure_type)
static ClosureSignature from_closure_output_node(const bNode &node, bool allow_auto_structure_type)
KDTree_3d * tree
const bNodeZoneType * zone_type_by_node_type(const int node_type)
const ComputeContext * compute_context_for_zones(const Span< const bke::bNodeTreeZone * > zones, bke::ComputeContextCache &compute_context_cache, const ComputeContext *parent_compute_context)
static Vector< SocketInContext > find_origin_sockets_through_contexts(SocketInContext start_socket, bke::ComputeContextCache &compute_context_cache, FunctionRef< bool(const SocketInContext &)> handle_possible_origin_socket_fn, bool find_all)
static bool is_evaluate_closure_node_input(const SocketInContext &socket)
static bool use_link_for_tracing(const bNodeLink &link)
LinkedBundleSignatures gather_linked_target_bundle_signatures(const ComputeContext *bundle_socket_context, const bNodeSocket &bundle_socket, bke::ComputeContextCache &compute_context_cache)
LinkedClosureSignatures gather_linked_target_closure_signatures(const ComputeContext *closure_socket_context, const bNodeSocket &closure_socket, bke::ComputeContextCache &compute_context_cache)
const ComputeContext * compute_context_for_closure_evaluation(const ComputeContext *closure_socket_context, const bNodeSocket &closure_socket, bke::ComputeContextCache &compute_context_cache, const std::optional< ClosureSourceLocation > &source_location)
LinkedBundleSignatures gather_linked_origin_bundle_signatures(const ComputeContext *bundle_socket_context, const bNodeSocket &bundle_socket, bke::ComputeContextCache &compute_context_cache)
LinkedClosureSignatures gather_linked_origin_closure_signatures(const ComputeContext *closure_socket_context, const bNodeSocket &closure_socket, bke::ComputeContextCache &compute_context_cache)
std::optional< NodeInContext > find_origin_index_menu_switch(const SocketInContext &src_socket, bke::ComputeContextCache &compute_context_cache)
static Vector< SocketInContext > find_target_sockets_through_contexts(const SocketInContext start_socket, bke::ComputeContextCache &compute_context_cache, const FunctionRef< bool(const SocketInContext &)> handle_possible_target_socket_fn, const bool find_all)
static bool is_closure_zone_output_socket(const SocketInContext &socket)
bNodeSocketRuntimeHandle * runtime
char identifier[64]
struct ID * id
int16_t type_legacy
void * storage
int32_t identifier
static BundleSignature from_separate_bundle_node(const bNode &node, bool allow_auto_structure_type)
CustomIDVectorSet< Item, ItemKeyGetter > items
static BundleSignature from_combine_bundle_node(const bNode &node, bool allow_auto_structure_type)
SocketInContext input_socket(int index) const
SocketInContext output_socket(int index) const
i
Definition text_draw.cc:230