Blender V5.0
sync_sockets.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 <fmt/format.h>
6
7#include "DNA_node_types.h"
8#include "DNA_space_types.h"
9
10#include "RNA_access.hh"
11
12#include "WM_api.hh"
13
15#include "BKE_context.hh"
16#include "BKE_main.hh"
19#include "BKE_node_runtime.hh"
21#include "BKE_report.hh"
22#include "BKE_workspace.hh"
23
24#include "ED_node.hh"
25#include "ED_screen.hh"
26
27#include "BLI_listbase.h"
28
29#include "BLT_translation.hh"
30
31#include "NOD_geo_bundle.hh"
32#include "NOD_geo_closure.hh"
33#include "NOD_socket_items.hh"
34#include "NOD_sync_sockets.hh"
35#include "NOD_trace_values.hh"
36
37namespace blender::nodes {
38
45
48 std::optional<nodes::BundleSignature> source_signature;
49};
50
53 std::optional<nodes::ClosureSignature> source_signature;
54};
55
57 const SpaceNode &snode,
58 const bNode &separate_bundle_node,
59 const bNodeSocket *src_bundle_socket = nullptr)
60{
61 BLI_assert(separate_bundle_node.is_type("NodeSeparateBundle"));
62 snode.edittree->ensure_topology_cache();
63 if (!src_bundle_socket) {
64 src_bundle_socket = &separate_bundle_node.input_socket(0);
65 }
66 BLI_assert(src_bundle_socket->type == SOCK_BUNDLE);
67
68 bke::ComputeContextCache compute_context_cache;
70 snode, compute_context_cache, *src_bundle_socket);
71 if (!current_context) {
73 }
75 current_context, *src_bundle_socket, compute_context_cache);
76 if (linked_signatures.items.is_empty()) {
78 }
79 std::optional<BundleSignature> merged_signature = linked_signatures.get_merged_signature();
80 if (!merged_signature.has_value()) {
82 }
83 if (!linked_signatures.has_type_definition()) {
84 merged_signature->set_auto_structure_types();
85 }
86 const nodes::BundleSignature &current_signature =
87 nodes::BundleSignature::from_separate_bundle_node(separate_bundle_node, true);
88 if (*merged_signature != current_signature) {
89 return {NodeSyncState::CanBeSynced, std::move(merged_signature)};
90 }
91 return {NodeSyncState::Synced};
92}
93
95 const SpaceNode &snode,
96 const bNode &combine_bundle_node,
97 const bNodeSocket *src_bundle_socket = nullptr)
98{
99 BLI_assert(combine_bundle_node.is_type("NodeCombineBundle"));
100 snode.edittree->ensure_topology_cache();
101 if (!src_bundle_socket) {
102 src_bundle_socket = &combine_bundle_node.output_socket(0);
103 }
104 BLI_assert(src_bundle_socket->type == SOCK_BUNDLE);
105
106 bke::ComputeContextCache compute_context_cache;
108 snode, compute_context_cache, *src_bundle_socket);
109 if (!current_context) {
111 }
113 current_context, *src_bundle_socket, compute_context_cache);
114 if (linked_signatures.items.is_empty()) {
116 }
117 std::optional<BundleSignature> merged_signature = linked_signatures.get_merged_signature();
118 if (!merged_signature.has_value()) {
120 }
121 if (!linked_signatures.has_type_definition()) {
122 merged_signature->set_auto_structure_types();
123 }
124 const nodes::BundleSignature &current_signature =
125 nodes::BundleSignature::from_combine_bundle_node(combine_bundle_node, true);
126 if (*merged_signature != current_signature) {
127 return {NodeSyncState::CanBeSynced, std::move(merged_signature)};
128 }
129 return {NodeSyncState::Synced};
130}
131
133 const SpaceNode &snode,
134 const bNode &closure_output_node,
135 const bNodeSocket *src_closure_socket = nullptr)
136{
137 snode.edittree->ensure_topology_cache();
138 if (!src_closure_socket) {
139 src_closure_socket = &closure_output_node.output_socket(0);
140 }
141 BLI_assert(src_closure_socket->type == SOCK_CLOSURE);
142
143 bke::ComputeContextCache compute_context_cache;
145 snode, compute_context_cache, *src_closure_socket);
146 if (!current_context) {
148 }
150 current_context, *src_closure_socket, compute_context_cache);
151 if (linked_signatures.items.is_empty()) {
153 }
154 std::optional<ClosureSignature> merged_signature = linked_signatures.get_merged_signature();
155 if (!merged_signature.has_value()) {
157 }
158 if (!linked_signatures.has_type_definition()) {
159 merged_signature->set_auto_structure_types();
160 }
161 const nodes::ClosureSignature &current_signature =
162 nodes::ClosureSignature::from_closure_output_node(closure_output_node, true);
163 if (*merged_signature != current_signature) {
164 return {NodeSyncState::CanBeSynced, merged_signature};
165 }
166 return {NodeSyncState::Synced};
167}
168
170 const SpaceNode &snode,
171 const bNode &evaluate_closure_node,
172 const bNodeSocket *src_closure_socket = nullptr)
173{
174 snode.edittree->ensure_topology_cache();
175 if (!src_closure_socket) {
176 src_closure_socket = &evaluate_closure_node.input_socket(0);
177 }
178 BLI_assert(src_closure_socket->type == SOCK_CLOSURE);
179
180 bke::ComputeContextCache compute_context_cache;
182 snode, compute_context_cache, *src_closure_socket);
183 if (!current_context) {
185 }
187 current_context, *src_closure_socket, compute_context_cache);
188 if (linked_signatures.items.is_empty()) {
190 }
191 std::optional<ClosureSignature> merged_signature = linked_signatures.get_merged_signature();
192 if (!merged_signature.has_value()) {
194 }
195 if (!linked_signatures.has_type_definition()) {
196 merged_signature->set_auto_structure_types();
197 }
198 const nodes::ClosureSignature &current_signature =
199 nodes::ClosureSignature::from_evaluate_closure_node(evaluate_closure_node, true);
200 if (*merged_signature != current_signature) {
201 return {NodeSyncState::CanBeSynced, merged_signature};
202 }
203 return {NodeSyncState::Synced};
204}
205
207 bNode &separate_bundle_node,
208 ReportList *reports,
209 const bNodeSocket *src_bundle_socket)
210{
212 snode, separate_bundle_node, src_bundle_socket);
213 switch (sync_state.state) {
215 return;
217 BKE_report(reports, RPT_INFO, "No bundle signature found");
218 return;
220 BKE_report(reports, RPT_INFO, "Found conflicting bundle signatures");
221 return;
223 break;
224 }
225
226 auto &storage = *static_cast<NodeSeparateBundle *>(separate_bundle_node.storage);
227
228 Map<std::string, int> old_identifiers;
229 for (const int i : IndexRange(storage.items_num)) {
230 const NodeSeparateBundleItem &item = storage.items[i];
231 old_identifiers.add_new(StringRef(item.name), item.identifier);
232 }
233
235 for (const nodes::BundleSignature::Item &item : sync_state.source_signature->items) {
237 nodes ::SeparateBundleItemsAccessor>(
238 *snode.edittree, separate_bundle_node, item.type->type, item.key.c_str());
239 new_item.structure_type = int(item.structure_type);
240 if (const std::optional<int> old_identifier = old_identifiers.lookup_try(item.key)) {
241 new_item.identifier = *old_identifier;
242 }
243 }
244 BKE_ntree_update_tag_node_property(snode.edittree, &separate_bundle_node);
245}
246
248 bNode &combine_bundle_node,
249 ReportList *reports,
250 const bNodeSocket *src_bundle_socket)
251{
253 snode, combine_bundle_node, src_bundle_socket);
254 switch (sync_state.state) {
256 return;
258 BKE_report(reports, RPT_INFO, "No bundle signature found");
259 return;
261 BKE_report(reports, RPT_INFO, "Found conflicting bundle signatures");
262 return;
264 break;
265 }
266
267 auto &storage = *static_cast<NodeCombineBundle *>(combine_bundle_node.storage);
268
269 Map<std::string, int> old_identifiers;
270 for (const int i : IndexRange(storage.items_num)) {
271 const NodeCombineBundleItem &item = storage.items[i];
272 old_identifiers.add_new(StringRef(item.name), item.identifier);
273 }
274
276 for (const nodes::BundleSignature::Item &item : sync_state.source_signature->items) {
278 nodes ::CombineBundleItemsAccessor>(
279 *snode.edittree, combine_bundle_node, item.type->type, item.key.c_str());
280 new_item.structure_type = int(item.structure_type);
281 if (const std::optional<int> old_identifier = old_identifiers.lookup_try(item.key)) {
282 new_item.identifier = *old_identifier;
283 }
284 }
285
286 BKE_ntree_update_tag_node_property(snode.edittree, &combine_bundle_node);
287}
288
290 bNode &evaluate_closure_node,
291 ReportList *reports,
292 const bNodeSocket *src_closure_socket)
293{
295 snode, evaluate_closure_node, src_closure_socket);
296 switch (sync_state.state) {
298 return;
300 BKE_report(reports, RPT_INFO, "No closure signature found");
301 return;
303 BKE_report(reports, RPT_INFO, "Found conflicting closure signatures");
304 return;
306 break;
307 }
308
309 auto &storage = *static_cast<NodeEvaluateClosure *>(evaluate_closure_node.storage);
310
311 Map<std::string, int> old_input_identifiers;
312 Map<std::string, int> old_output_identifiers;
313 for (const int i : IndexRange(storage.input_items.items_num)) {
314 const NodeEvaluateClosureInputItem &item = storage.input_items.items[i];
315 old_input_identifiers.add_new(StringRef(item.name), item.identifier);
316 }
317 for (const int i : IndexRange(storage.output_items.items_num)) {
318 const NodeEvaluateClosureOutputItem &item = storage.output_items.items[i];
319 old_output_identifiers.add_new(StringRef(item.name), item.identifier);
320 }
321
324
325 for (const nodes::ClosureSignature::Item &item : sync_state.source_signature->inputs) {
329 *snode.edittree, evaluate_closure_node, item.type->type, item.key.c_str());
330 new_item.structure_type = int(item.structure_type);
331 if (const std::optional<int> old_identifier = old_input_identifiers.lookup_try(item.key)) {
332 new_item.identifier = *old_identifier;
333 }
334 }
335 for (const nodes::ClosureSignature::Item &item : sync_state.source_signature->outputs) {
339 *snode.edittree, evaluate_closure_node, item.type->type, item.key.c_str());
340 new_item.structure_type = int(item.structure_type);
341 if (const std::optional<int> old_identifier = old_output_identifiers.lookup_try(item.key)) {
342 new_item.identifier = *old_identifier;
343 }
344 }
345 BKE_ntree_update_tag_node_property(snode.edittree, &evaluate_closure_node);
346}
347
349 bNode &closure_input_node,
350 bNode &closure_output_node,
351 ReportList *reports,
352 const bNodeSocket *src_closure_socket)
353{
355 snode, closure_output_node, src_closure_socket);
356 switch (sync_state.state) {
358 return;
360 BKE_report(reports, RPT_INFO, "No closure signature found");
361 return;
363 BKE_report(reports, RPT_INFO, "Found conflicting closure signatures");
364 return;
366 break;
367 }
368 const nodes::ClosureSignature &signature = *sync_state.source_signature;
369
370 auto &storage = *static_cast<NodeClosureOutput *>(closure_output_node.storage);
371
372 Map<std::string, int> old_input_identifiers;
373 Map<std::string, int> old_output_identifiers;
374 for (const int i : IndexRange(storage.input_items.items_num)) {
375 const NodeClosureInputItem &item = storage.input_items.items[i];
376 old_input_identifiers.add_new(StringRef(item.name), item.identifier);
377 }
378 for (const int i : IndexRange(storage.output_items.items_num)) {
379 const NodeClosureOutputItem &item = storage.output_items.items[i];
380 old_output_identifiers.add_new(StringRef(item.name), item.identifier);
381 }
382
385
386 for (const nodes::ClosureSignature::Item &item : signature.inputs) {
387 NodeClosureInputItem &new_item =
389 *snode.edittree, closure_output_node, item.type->type, item.key.c_str());
390 new_item.structure_type = int(item.structure_type);
391 if (const std::optional<int> old_identifier = old_input_identifiers.lookup_try(item.key)) {
392 new_item.identifier = *old_identifier;
393 }
394 }
395 for (const nodes::ClosureSignature::Item &item : signature.outputs) {
398 *snode.edittree, closure_output_node, item.type->type, item.key.c_str());
399 new_item.structure_type = int(item.structure_type);
400 if (const std::optional<int> old_identifier = old_output_identifiers.lookup_try(item.key)) {
401 new_item.identifier = *old_identifier;
402 }
403 }
404 BKE_ntree_update_tag_node_property(snode.edittree, &closure_input_node);
405 BKE_ntree_update_tag_node_property(snode.edittree, &closure_output_node);
406
407 nodes::update_node_declaration_and_sockets(*snode.edittree, closure_input_node);
408 nodes::update_node_declaration_and_sockets(*snode.edittree, closure_output_node);
409
410 /* Create internal zone links for newly created sockets. */
411 snode.edittree->ensure_topology_cache();
413 for (const int input_i : signature.inputs.index_range()) {
414 const nodes::ClosureSignature::Item &input_item = signature.inputs[input_i];
415 if (old_input_identifiers.contains(input_item.key)) {
416 continue;
417 }
418 for (const int output_i : signature.outputs.index_range()) {
419 const nodes::ClosureSignature::Item &output_item = signature.outputs[output_i];
420 if (old_output_identifiers.contains(output_item.key)) {
421 continue;
422 }
423 if (input_item.key == output_item.key) {
424 internal_links.append({&closure_input_node.output_socket(input_i),
425 &closure_output_node.input_socket(output_i)});
426 }
427 };
428 }
429 for (auto &&[from_socket, to_socket] : internal_links) {
430 if (!snode.edittree->typeinfo->validate_link ||
431 snode.edittree->typeinfo->validate_link(from_socket->typeinfo->type,
432 to_socket->typeinfo->type))
433 {
435 *snode.edittree, closure_input_node, *from_socket, closure_output_node, *to_socket);
436 }
437 }
438}
439
440static std::string get_bundle_sync_tooltip(const nodes::BundleSignature &old_signature,
441 const nodes::BundleSignature &new_signature)
442{
443 Vector<StringRef> added_items;
444 Vector<StringRef> removed_items;
445 Vector<StringRef> changed_items;
446 bool order_changed = false;
447
448 for (const int new_item_i : new_signature.items.index_range()) {
449 const BundleSignature::Item &new_item = new_signature.items[new_item_i];
450 const int old_item_i = old_signature.items.index_of_try_as(new_item.key);
451 if (old_item_i == -1) {
452 added_items.append(new_item.key);
453 }
454 else {
455 const BundleSignature::Item &old_item = old_signature.items[old_item_i];
456 if (new_item != old_item) {
457 changed_items.append(new_item.key);
458 }
459 if (old_item_i != new_item_i) {
460 order_changed = true;
461 }
462 }
463 }
464 for (const nodes::BundleSignature::Item &old_item : old_signature.items) {
465 if (!new_signature.items.contains_as(old_item.key)) {
466 removed_items.append(old_item.key);
467 }
468 }
469
470 fmt::memory_buffer string_buffer;
471 auto buf = fmt::appender(string_buffer);
472 if (!added_items.is_empty()) {
473 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Add"), fmt::join(added_items, ", "));
474 }
475 if (!removed_items.is_empty()) {
476 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Remove"), fmt::join(removed_items, ", "));
477 }
478 if (!changed_items.is_empty()) {
479 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Change"), fmt::join(changed_items, ", "));
480 }
481 if (order_changed) {
482 fmt::format_to(buf, "\u2022 {}", TIP_("Reorder"));
483 }
484 fmt::format_to(buf, "\n{}", TIP_("Update based on linked bundle signature"));
485
486 return fmt::to_string(string_buffer);
487}
488
489static std::string get_closure_sync_tooltip(const nodes::ClosureSignature &old_signature,
490 const nodes::ClosureSignature &new_signature)
491{
492 Vector<StringRef> added_inputs;
493 Vector<StringRef> removed_inputs;
494 Vector<StringRef> changed_inputs;
495 bool input_order = false;
496
497 Vector<StringRef> added_outputs;
498 Vector<StringRef> removed_outputs;
499 Vector<StringRef> changed_outputs;
500 bool output_order = false;
501
502 for (const int new_item_i : new_signature.inputs.index_range()) {
503 const nodes::ClosureSignature::Item &new_item = new_signature.inputs[new_item_i];
504 const int old_item_i = old_signature.inputs.index_of_try_as(new_item.key);
505 if (old_item_i == -1) {
506 added_inputs.append(new_item.key);
507 }
508 else {
509 const nodes::ClosureSignature::Item &old_item = old_signature.inputs[old_item_i];
510 if (new_item != old_item) {
511 changed_inputs.append(new_item.key);
512 }
513 if (old_item_i != new_item_i) {
514 input_order = true;
515 }
516 }
517 }
518 for (const nodes::ClosureSignature::Item &old_item : old_signature.inputs) {
519 if (!new_signature.inputs.contains_as(old_item.key)) {
520 removed_inputs.append(old_item.key);
521 }
522 }
523 for (const int new_item_i : new_signature.outputs.index_range()) {
524 const nodes::ClosureSignature::Item &new_item = new_signature.outputs[new_item_i];
525 const int old_item_i = old_signature.outputs.index_of_try_as(new_item.key);
526 if (old_item_i == -1) {
527 added_outputs.append(new_item.key);
528 }
529 else {
530 const nodes::ClosureSignature::Item &old_item = old_signature.outputs[old_item_i];
531 if (new_item != old_item) {
532 changed_outputs.append(new_item.key);
533 }
534 if (old_item_i != new_item_i) {
535 output_order = true;
536 }
537 }
538 }
539 for (const nodes::ClosureSignature::Item &old_item : old_signature.outputs) {
540 if (!new_signature.outputs.contains_as(old_item.key)) {
541 removed_outputs.append(old_item.key);
542 }
543 }
544
545 fmt::memory_buffer string_buffer;
546 auto buf = fmt::appender(string_buffer);
547 if (!added_inputs.is_empty()) {
548 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Add Inputs"), fmt::join(added_inputs, ", "));
549 }
550 if (!removed_inputs.is_empty()) {
551 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Remove Inputs"), fmt::join(removed_inputs, ", "));
552 }
553 if (!changed_inputs.is_empty()) {
554 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Change Inputs"), fmt::join(changed_inputs, ", "));
555 }
556 if (input_order) {
557 fmt::format_to(buf, "\u2022 {}\n", TIP_("Reorder Inputs"));
558 }
559 if (!added_outputs.is_empty()) {
560 fmt::format_to(buf, "\u2022 {}: {}\n", TIP_("Add Outputs"), fmt::join(added_outputs, ", "));
561 }
562 if (!removed_outputs.is_empty()) {
563 fmt::format_to(
564 buf, "\u2022 {}: {}\n", TIP_("Remove Outputs"), fmt::join(removed_outputs, ", "));
565 }
566 if (!changed_outputs.is_empty()) {
567 fmt::format_to(
568 buf, "\u2022 {}: {}\n", TIP_("Change Outputs"), fmt::join(changed_outputs, ", "));
569 }
570 if (output_order) {
571 fmt::format_to(buf, "\u2022 {}\n", TIP_("Reorder Outputs"));
572 }
573 fmt::format_to(buf, "\n{}", TIP_("Update based on linked closure signature"));
574
575 return fmt::to_string(string_buffer);
576}
577
578void sync_node(bContext &C, bNode &node, ReportList *reports)
579{
581 SpaceNode &snode = *CTX_wm_space_node(&C);
582 if (node.is_type("NodeEvaluateClosure")) {
583 sync_sockets_evaluate_closure(snode, node, reports);
584 }
585 else if (node.is_type("NodeSeparateBundle")) {
586 sync_sockets_separate_bundle(snode, node, reports);
587 }
588 else if (node.is_type("NodeCombineBundle")) {
589 sync_sockets_combine_bundle(snode, node, reports);
590 }
591 else if (node.is_type("NodeClosureInput")) {
592 bNode &closure_input_node = node;
593 if (bNode *closure_output_node = closure_zone_type.get_corresponding_output(
594 *snode.edittree, closure_input_node))
595 {
596 sync_sockets_closure(snode, closure_input_node, *closure_output_node, reports);
597 }
598 }
599 else if (node.is_type("NodeClosureOutput")) {
600 bNode &closure_output_node = node;
601 if (bNode *closure_input_node = closure_zone_type.get_corresponding_input(*snode.edittree,
602 closure_output_node))
603 {
604 sync_sockets_closure(snode, *closure_input_node, closure_output_node, reports);
605 }
606 }
607}
608
609std::string sync_node_description_get(const bContext &C, const bNode &node)
610{
611 const SpaceNode *snode = CTX_wm_space_node(&C);
612 if (!snode) {
613 return "";
614 }
615
616 if (node.is_type("NodeSeparateBundle")) {
618 node, true);
619 if (const std::optional<nodes::BundleSignature> new_signature =
620 get_sync_state_separate_bundle(*snode, node).source_signature)
621 {
622 return get_bundle_sync_tooltip(old_signature, *new_signature);
623 }
624 }
625 else if (node.is_type("NodeCombineBundle")) {
627 node, true);
628 if (const std::optional<nodes::BundleSignature> new_signature =
629 get_sync_state_combine_bundle(*snode, node).source_signature)
630 {
631 return get_bundle_sync_tooltip(old_signature, *new_signature);
632 }
633 }
634 else if (node.is_type("NodeEvaluateClosure")) {
635 const nodes::ClosureSignature old_signature =
637 if (const std::optional<nodes::ClosureSignature> new_signature =
638 get_sync_state_evaluate_closure(*snode, node).source_signature)
639 {
640 return get_closure_sync_tooltip(old_signature, *new_signature);
641 }
642 }
643 else if (node.is_type("NodeClosureOutput")) {
644 const nodes::ClosureSignature old_signature =
646 if (const std::optional<nodes::ClosureSignature> new_signature =
647 get_sync_state_closure_output(*snode, node).source_signature)
648 {
649 return get_closure_sync_tooltip(old_signature, *new_signature);
650 }
651 }
652 return "";
653}
654
655bool node_can_sync_sockets(const bContext &C, const bNodeTree & /*tree*/, const bNode &node)
656{
657 SpaceNode *snode = CTX_wm_space_node(&C);
658 if (!snode) {
659 return false;
660 }
662 const bool can_sync = cache.lookup_or_add_cb(node.identifier, [&]() {
663 if (node.is_type("NodeEvaluateClosure")) {
664 return get_sync_state_evaluate_closure(*snode, node).source_signature.has_value();
665 }
666 if (node.is_type("NodeClosureOutput")) {
667 return get_sync_state_closure_output(*snode, node).source_signature.has_value();
668 }
669 if (node.is_type("NodeCombineBundle")) {
670 return get_sync_state_combine_bundle(*snode, node).source_signature.has_value();
671 }
672 if (node.is_type("NodeSeparateBundle")) {
673 return get_sync_state_separate_bundle(*snode, node).source_signature.has_value();
674 }
675 return false;
676 });
677 return can_sync;
678}
679
681{
682 if (wmWindowManager *wm = static_cast<wmWindowManager *>(bmain.wm.first)) {
683 LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
684 bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
685 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
686 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
687 if (sl->spacetype == SPACE_NODE) {
688 SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
689 /* This may be called before runtime data is initialized currently. */
690 if (snode->runtime) {
692 cache.clear();
693 }
694 }
695 }
696 }
697 }
698}
699
700} // namespace blender::nodes
SpaceNode * CTX_wm_space_node(const bContext *C)
#define NODE_CLOSURE_OUTPUT
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
@ RPT_INFO
Definition BKE_report.hh:35
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:614
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
#define TIP_(msgid)
@ SOCK_CLOSURE
@ SOCK_BUNDLE
@ SPACE_NODE
#define C
Definition RandGen.cpp:29
bool is_empty() const
void clear()
Definition BLI_map.hh:1038
std::optional< Value > lookup_try(const Key &key) const
Definition BLI_map.hh:531
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
bool contains(const Key &key) const
Definition BLI_map.hh:353
void append(const T &value)
bool is_empty() const
const bNode * get_corresponding_input(const bNodeTree &tree, const bNode &output_bnode) const
const bNode * get_corresponding_output(const bNodeTree &tree, const bNode &input_bnode) const
CustomIDVectorSet< Item, ItemKeyGetter > inputs
CustomIDVectorSet< Item, ItemKeyGetter > outputs
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)
const bNodeZoneType * zone_type_by_node_type(const int node_type)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
Definition node.cc:3810
const ComputeContext * compute_context_for_edittree_socket(const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache, const bNodeSocket &socket)
Map< int, bool > & node_can_sync_cache_get(SpaceNode &snode)
Accessor::ItemT * add_item_with_socket_type_and_name(bNodeTree &ntree, bNode &node, const eNodeSocketDatatype socket_type, const char *name, std::optional< int > dimensions=std::nullopt)
void sync_node(bContext &C, bNode &node, ReportList *reports)
static std::string get_bundle_sync_tooltip(const nodes::BundleSignature &old_signature, const nodes::BundleSignature &new_signature)
void sync_sockets_evaluate_closure(SpaceNode &snode, bNode &evaluate_closure_node, ReportList *reports, const bNodeSocket *src_closure_socket)
bool node_can_sync_sockets(const bContext &C, const bNodeTree &, const bNode &node)
void sync_sockets_combine_bundle(SpaceNode &snode, bNode &combine_bundle_node, ReportList *reports, const bNodeSocket *src_bundle_socket)
void sync_sockets_separate_bundle(SpaceNode &snode, bNode &separate_bundle_node, ReportList *reports, const bNodeSocket *src_bundle_socket)
void sync_sockets_closure(SpaceNode &snode, bNode &closure_input_node, bNode &closure_output_node, ReportList *reports, const bNodeSocket *src_closure_socket)
LinkedBundleSignatures gather_linked_target_bundle_signatures(const ComputeContext *bundle_socket_context, const bNodeSocket &bundle_socket, bke::ComputeContextCache &compute_context_cache)
static BundleSyncState get_sync_state_combine_bundle(const SpaceNode &snode, const bNode &combine_bundle_node, const bNodeSocket *src_bundle_socket=nullptr)
static ClosureSyncState get_sync_state_closure_output(const SpaceNode &snode, const bNode &closure_output_node, const bNodeSocket *src_closure_socket=nullptr)
static BundleSyncState get_sync_state_separate_bundle(const SpaceNode &snode, const bNode &separate_bundle_node, const bNodeSocket *src_bundle_socket=nullptr)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
LinkedClosureSignatures gather_linked_target_closure_signatures(const ComputeContext *closure_socket_context, const bNodeSocket &closure_socket, bke::ComputeContextCache &compute_context_cache)
static std::string get_closure_sync_tooltip(const nodes::ClosureSignature &old_signature, const nodes::ClosureSignature &new_signature)
void node_can_sync_cache_clear(Main &bmain)
static ClosureSyncState get_sync_state_evaluate_closure(const SpaceNode &snode, const bNode &evaluate_closure_node, const bNodeSocket *src_closure_socket=nullptr)
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::string sync_node_description_get(const bContext &C, const bNode &node)
void * first
ListBase wm
Definition BKE_main.hh:307
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
bNodeTreeTypeHandle * typeinfo
void * storage
int32_t identifier
ListBase areabase
eNodeSocketDatatype type
Definition BKE_node.hh:193
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)
std::optional< nodes::BundleSignature > source_signature
std::optional< nodes::ClosureSignature > source_signature
std::optional< BundleSignature > get_merged_signature() const
std::optional< ClosureSignature > get_merged_signature() const
i
Definition text_draw.cc:230