Blender V4.3
node_tree_update.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <fmt/format.h>
6
7#include "BLI_map.hh"
9#include "BLI_noise.hh"
10#include "BLI_rand.hh"
11#include "BLI_set.hh"
12#include "BLI_stack.hh"
14#include "BLI_vector_set.hh"
15
16#include "DNA_anim_types.h"
17#include "DNA_modifier_types.h"
18#include "DNA_node_types.h"
19
20#include "BKE_anim_data.hh"
21#include "BKE_image.hh"
22#include "BKE_main.hh"
23#include "BKE_node.hh"
24#include "BKE_node_enum.hh"
25#include "BKE_node_runtime.hh"
28
29#include "MOD_nodes.hh"
30
34#include "NOD_socket.hh"
35#include "NOD_texture.h"
36
37#include "BLT_translation.hh"
38
39using namespace blender::nodes;
40
59
61{
62 ntree->runtime->changed_flag |= flag;
63 ntree->runtime->topology_cache_mutex.tag_dirty();
64 ntree->runtime->tree_zones_cache_mutex.tag_dirty();
65}
66
67static void add_node_tag(bNodeTree *ntree, bNode *node, const eNodeTreeChangedFlag flag)
68{
69 add_tree_tag(ntree, flag);
70 node->runtime->changed_flag |= flag;
71}
72
74{
75 add_tree_tag(ntree, flag);
76 socket->runtime->changed_flag |= flag;
77}
78
79namespace blender::bke {
80
88{
89 switch (to->type) {
90 case SOCK_RGBA:
91 switch (from->type) {
92 case SOCK_RGBA:
93 return 4;
94 case SOCK_FLOAT:
95 return 3;
96 case SOCK_INT:
97 return 2;
98 case SOCK_BOOLEAN:
99 return 1;
100 }
101 return -1;
102 case SOCK_VECTOR:
103 switch (from->type) {
104 case SOCK_VECTOR:
105 return 4;
106 case SOCK_FLOAT:
107 return 3;
108 case SOCK_INT:
109 return 2;
110 case SOCK_BOOLEAN:
111 return 1;
112 }
113 return -1;
114 case SOCK_FLOAT:
115 switch (from->type) {
116 case SOCK_FLOAT:
117 return 5;
118 case SOCK_INT:
119 return 4;
120 case SOCK_BOOLEAN:
121 return 3;
122 case SOCK_RGBA:
123 return 2;
124 case SOCK_VECTOR:
125 return 1;
126 }
127 return -1;
128 case SOCK_INT:
129 switch (from->type) {
130 case SOCK_INT:
131 return 5;
132 case SOCK_FLOAT:
133 return 4;
134 case SOCK_BOOLEAN:
135 return 3;
136 case SOCK_RGBA:
137 return 2;
138 case SOCK_VECTOR:
139 return 1;
140 }
141 return -1;
142 case SOCK_BOOLEAN:
143 switch (from->type) {
144 case SOCK_BOOLEAN:
145 return 5;
146 case SOCK_INT:
147 return 4;
148 case SOCK_FLOAT:
149 return 3;
150 case SOCK_RGBA:
151 return 2;
152 case SOCK_VECTOR:
153 return 1;
154 }
155 return -1;
156 case SOCK_ROTATION:
157 switch (from->type) {
158 case SOCK_ROTATION:
159 return 3;
160 case SOCK_VECTOR:
161 return 2;
162 case SOCK_FLOAT:
163 return 1;
164 }
165 return -1;
166 }
167
168 /* The rest of the socket types only allow an internal link if both the input and output socket
169 * have the same type. If the sockets are custom, we check the idname instead. */
170 if (to->type == from->type && (to->type != SOCK_CUSTOM || STREQ(to->idname, from->idname))) {
171 return 1;
172 }
173
174 return -1;
175}
176
177/* Check both the tree's own tags and the interface tags. */
178static bool is_tree_changed(const bNodeTree &tree)
179{
180 return tree.runtime->changed_flag != NTREE_CHANGED_NOTHING || tree.tree_interface.is_changed();
181}
182
183using TreeNodePair = std::pair<bNodeTree *, bNode *>;
184using ObjectModifierPair = std::pair<Object *, ModifierData *>;
185using NodeSocketPair = std::pair<bNode *, bNodeSocket *>;
186
192 private:
193 Main *bmain_;
194 std::optional<Vector<bNodeTree *>> all_trees_;
195 std::optional<Map<bNodeTree *, ID *>> owner_ids_;
196 std::optional<MultiValueMap<bNodeTree *, TreeNodePair>> group_node_users_;
197 std::optional<MultiValueMap<bNodeTree *, ObjectModifierPair>> modifiers_users_;
198
199 public:
200 NodeTreeRelations(Main *bmain) : bmain_(bmain) {}
201
203 {
204 if (all_trees_.has_value()) {
205 return;
206 }
207 all_trees_.emplace();
208 owner_ids_.emplace();
209 if (bmain_ == nullptr) {
210 return;
211 }
212
213 FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
214 all_trees_->append(ntree);
215 if (&ntree->id != id) {
216 owner_ids_->add_new(ntree, id);
217 }
218 }
220 }
221
223 {
224 this->ensure_all_trees();
225 }
226
228 {
229 if (group_node_users_.has_value()) {
230 return;
231 }
232 group_node_users_.emplace();
233 if (bmain_ == nullptr) {
234 return;
235 }
236
237 this->ensure_all_trees();
238
239 for (bNodeTree *ntree : *all_trees_) {
240 for (bNode *node : ntree->all_nodes()) {
241 if (node->id == nullptr) {
242 continue;
243 }
244 ID *id = node->id;
245 if (GS(id->name) == ID_NT) {
246 bNodeTree *group = (bNodeTree *)id;
247 group_node_users_->add(group, {ntree, node});
248 }
249 }
250 }
251 }
252
254 {
255 if (modifiers_users_.has_value()) {
256 return;
257 }
258 modifiers_users_.emplace();
259 if (bmain_ == nullptr) {
260 return;
261 }
262
263 LISTBASE_FOREACH (Object *, object, &bmain_->objects) {
264 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
265 if (md->type == eModifierType_Nodes) {
267 if (nmd->node_group != nullptr) {
268 modifiers_users_->add(nmd->node_group, {object, md});
269 }
270 }
271 }
272 }
273 }
274
276 {
277 BLI_assert(modifiers_users_.has_value());
278 return modifiers_users_->lookup(ntree);
279 }
280
282 {
283 BLI_assert(group_node_users_.has_value());
284 return group_node_users_->lookup(ntree);
285 }
286
288 {
289 BLI_assert(owner_ids_.has_value());
290 return owner_ids_->lookup_default(ntree, &ntree->id);
291 }
292};
293
295 bool interface_changed = false;
296 bool output_changed = false;
297};
298
300 private:
301 Main *bmain_;
303 Map<bNodeTree *, TreeUpdateResult> update_result_by_tree_;
304 NodeTreeRelations relations_;
305
306 public:
308 : bmain_(bmain), params_(params), relations_(bmain)
309 {
310 }
311
312 void update()
313 {
314 Vector<bNodeTree *> changed_ntrees;
315 FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
316 if (is_tree_changed(*ntree)) {
317 changed_ntrees.append(ntree);
318 }
319 }
321 this->update_rooted(changed_ntrees);
322 }
323
325 {
326 if (root_ntrees.is_empty()) {
327 return;
328 }
329
330 bool is_single_tree_update = false;
331
332 if (root_ntrees.size() == 1) {
333 bNodeTree *ntree = root_ntrees[0];
334 if (!is_tree_changed(*ntree)) {
335 return;
336 }
337 const TreeUpdateResult result = this->update_tree(*ntree);
338 update_result_by_tree_.add_new(ntree, result);
339 if (!result.interface_changed && !result.output_changed) {
340 is_single_tree_update = true;
341 }
342 }
343
344 if (!is_single_tree_update) {
345 Vector<bNodeTree *> ntrees_in_order = this->get_tree_update_order(root_ntrees);
346 for (bNodeTree *ntree : ntrees_in_order) {
347 if (!is_tree_changed(*ntree)) {
348 continue;
349 }
350 if (!update_result_by_tree_.contains(ntree)) {
351 const TreeUpdateResult result = this->update_tree(*ntree);
352 update_result_by_tree_.add_new(ntree, result);
353 }
354 const TreeUpdateResult result = update_result_by_tree_.lookup(ntree);
355 Span<TreeNodePair> dependent_trees = relations_.get_group_node_users(ntree);
356 if (result.output_changed) {
357 for (const TreeNodePair &pair : dependent_trees) {
358 add_node_tag(pair.first, pair.second, NTREE_CHANGED_NODE_OUTPUT);
359 }
360 }
361 if (result.interface_changed) {
362 for (const TreeNodePair &pair : dependent_trees) {
363 add_node_tag(pair.first, pair.second, NTREE_CHANGED_NODE_PROPERTY);
364 }
365 }
366 }
367 }
368
369 for (const auto item : update_result_by_tree_.items()) {
370 bNodeTree *ntree = item.key;
371 const TreeUpdateResult &result = item.value;
372
373 this->reset_changed_flags(*ntree);
374
375 if (result.interface_changed) {
376 if (ntree->type == NTREE_GEOMETRY) {
377 relations_.ensure_modifier_users();
378 for (const ObjectModifierPair &pair : relations_.get_modifier_users(ntree)) {
379 Object *object = pair.first;
380 ModifierData *md = pair.second;
381
382 if (md->type == eModifierType_Nodes) {
384 }
385 }
386 }
387 }
388
389 if (result.output_changed) {
390 ntree->runtime->geometry_nodes_lazy_function_graph_info.reset();
391 }
392
393 if (params_) {
394 relations_.ensure_owner_ids();
395 ID *id = relations_.get_owner_id(ntree);
396 if (params_->tree_changed_fn) {
397 params_->tree_changed_fn(id, ntree, params_->user_data);
398 }
399 if (params_->tree_output_changed_fn && result.output_changed) {
400 params_->tree_output_changed_fn(id, ntree, params_->user_data);
401 }
402 }
403 }
404 }
405
406 private:
407 enum class ToposortMark {
408 None,
409 Temporary,
410 Permanent,
411 };
412
413 using ToposortMarkMap = Map<bNodeTree *, ToposortMark>;
414
419 Vector<bNodeTree *> get_tree_update_order(Span<bNodeTree *> root_ntrees)
420 {
421 relations_.ensure_group_node_users();
422
423 Set<bNodeTree *> trees_to_update = get_trees_to_update(root_ntrees);
424
425 Vector<bNodeTree *> sorted_ntrees;
426
427 ToposortMarkMap marks;
428 for (bNodeTree *ntree : trees_to_update) {
429 marks.add_new(ntree, ToposortMark::None);
430 }
431 for (bNodeTree *ntree : trees_to_update) {
432 if (marks.lookup(ntree) == ToposortMark::None) {
433 const bool cycle_detected = !this->get_tree_update_order__visit_recursive(
434 ntree, marks, sorted_ntrees);
435 /* This should be prevented by higher level operators. */
436 BLI_assert(!cycle_detected);
437 UNUSED_VARS_NDEBUG(cycle_detected);
438 }
439 }
440
441 std::reverse(sorted_ntrees.begin(), sorted_ntrees.end());
442
443 return sorted_ntrees;
444 }
445
446 bool get_tree_update_order__visit_recursive(bNodeTree *ntree,
447 ToposortMarkMap &marks,
448 Vector<bNodeTree *> &sorted_ntrees)
449 {
450 ToposortMark &mark = marks.lookup(ntree);
451 if (mark == ToposortMark::Permanent) {
452 return true;
453 }
454 if (mark == ToposortMark::Temporary) {
455 /* There is a dependency cycle. */
456 return false;
457 }
458
459 mark = ToposortMark::Temporary;
460
461 for (const TreeNodePair &pair : relations_.get_group_node_users(ntree)) {
462 this->get_tree_update_order__visit_recursive(pair.first, marks, sorted_ntrees);
463 }
464 sorted_ntrees.append(ntree);
465
466 mark = ToposortMark::Permanent;
467 return true;
468 }
469
470 Set<bNodeTree *> get_trees_to_update(Span<bNodeTree *> root_ntrees)
471 {
472 relations_.ensure_group_node_users();
473
474 Set<bNodeTree *> reachable_trees;
475 VectorSet<bNodeTree *> trees_to_check = root_ntrees;
476
477 while (!trees_to_check.is_empty()) {
478 bNodeTree *ntree = trees_to_check.pop();
479 if (reachable_trees.add(ntree)) {
480 for (const TreeNodePair &pair : relations_.get_group_node_users(ntree)) {
481 trees_to_check.add(pair.first);
482 }
483 }
484 }
485
486 return reachable_trees;
487 }
488
489 TreeUpdateResult update_tree(bNodeTree &ntree)
490 {
491 TreeUpdateResult result;
492
493 ntree.runtime->link_errors_by_target_node.clear();
494
495 this->update_socket_link_and_use(ntree);
496 this->update_individual_nodes(ntree);
497 this->update_internal_links(ntree);
498 this->update_generic_callback(ntree);
499 this->remove_unused_previews_when_necessary(ntree);
500 this->make_node_previews_dirty(ntree);
501
502 this->propagate_runtime_flags(ntree);
503 if (ntree.type == NTREE_GEOMETRY) {
504 if (this->propagate_enum_definitions(ntree)) {
505 result.interface_changed = true;
506 }
508 result.interface_changed = true;
509 }
510 this->update_from_field_inference(ntree);
512 result.interface_changed = true;
513 }
515 result.interface_changed = true;
516 }
517 this->update_socket_shapes(ntree);
518 }
519
520 result.output_changed = this->check_if_output_changed(ntree);
521
522 this->update_socket_link_and_use(ntree);
523 this->update_link_validation(ntree);
524
525 if (this->update_nested_node_refs(ntree)) {
526 result.interface_changed = true;
527 }
528
529 if (ntree.type == NTREE_TEXTURE) {
530 ntreeTexCheckCyclics(&ntree);
531 }
532
533 if (ntree.tree_interface.is_changed()) {
534 result.interface_changed = true;
535 }
536
537#ifndef NDEBUG
538 /* Check the uniqueness of node identifiers. */
539 Set<int32_t> node_identifiers;
540 const Span<const bNode *> nodes = ntree.all_nodes();
541 for (const int i : nodes.index_range()) {
542 const bNode &node = *nodes[i];
543 BLI_assert(node.identifier > 0);
544 node_identifiers.add_new(node.identifier);
545 BLI_assert(node.runtime->index_in_tree == i);
546 }
547#endif
548
549 return result;
550 }
551
552 void update_socket_link_and_use(bNodeTree &tree)
553 {
554 tree.ensure_topology_cache();
555 for (bNodeSocket *socket : tree.all_input_sockets()) {
556 if (socket->directly_linked_links().is_empty()) {
557 socket->link = nullptr;
558 }
559 else {
560 socket->link = socket->directly_linked_links()[0];
561 }
562 }
563
564 this->update_socket_used_tags(tree);
565 }
566
567 void update_socket_used_tags(bNodeTree &tree)
568 {
569 tree.ensure_topology_cache();
570 for (bNodeSocket *socket : tree.all_sockets()) {
571 const bool socket_is_linked = !socket->directly_linked_links().is_empty();
572 SET_FLAG_FROM_TEST(socket->flag, socket_is_linked, SOCK_IS_LINKED);
573 }
574 }
575
576 void update_individual_nodes(bNodeTree &ntree)
577 {
578 for (bNode *node : ntree.all_nodes()) {
579 bke::node_declaration_ensure(&ntree, node);
580 if (this->should_update_individual_node(ntree, *node)) {
581 bke::bNodeType &ntype = *node->typeinfo;
582 if (ntype.group_update_func) {
583 ntype.group_update_func(&ntree, node);
584 }
585 if (ntype.declare) {
586 /* Should have been created when the node was registered. */
587 BLI_assert(ntype.static_declaration != nullptr);
590 }
591 }
592 if (ntype.updatefunc) {
593 ntype.updatefunc(&ntree, node);
594 }
595 }
596 }
597 }
598
599 bool should_update_individual_node(const bNodeTree &ntree, const bNode &node)
600 {
601 if (ntree.runtime->changed_flag & NTREE_CHANGED_ANY) {
602 return true;
603 }
604 if (node.runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
605 return true;
606 }
607 if (ntree.runtime->changed_flag & NTREE_CHANGED_LINK) {
608 /* Currently we have no way to tell if a node needs to be updated when a link changed. */
609 return true;
610 }
611 if (ntree.tree_interface.is_changed()) {
613 return true;
614 }
615 }
616 /* Check paired simulation zone nodes. */
617 if (all_zone_input_node_types().contains(node.type)) {
618 const bNodeZoneType &zone_type = *zone_type_by_node_type(node.type);
619 if (const bNode *output_node = zone_type.get_corresponding_output(ntree, node)) {
620 if (output_node->runtime->changed_flag & NTREE_CHANGED_NODE_PROPERTY) {
621 return true;
622 }
623 }
624 }
625 return false;
626 }
627
628 struct InternalLink {
629 bNodeSocket *from;
630 bNodeSocket *to;
631 int multi_input_sort_id = 0;
632
633 BLI_STRUCT_EQUALITY_OPERATORS_3(InternalLink, from, to, multi_input_sort_id);
634 };
635
636 const bNodeLink *first_non_dangling_link(const bNodeTree & /*ntree*/,
637 const Span<const bNodeLink *> links) const
638 {
639 for (const bNodeLink *link : links) {
640 if (!link->fromnode->is_dangling_reroute()) {
641 return link;
642 }
643 }
644 return nullptr;
645 }
646
647 void update_internal_links(bNodeTree &ntree)
648 {
649 bke::node_tree_runtime::AllowUsingOutdatedInfo allow_outdated_info{ntree};
650 ntree.ensure_topology_cache();
651 for (bNode *node : ntree.all_nodes()) {
652 if (!this->should_update_individual_node(ntree, *node)) {
653 continue;
654 }
655 /* Find all expected internal links. */
656 Vector<InternalLink> expected_internal_links;
657 for (const bNodeSocket *output_socket : node->output_sockets()) {
658 if (!output_socket->is_available()) {
659 continue;
660 }
661 if (!output_socket->is_directly_linked()) {
662 continue;
663 }
664 if (output_socket->flag & SOCK_NO_INTERNAL_LINK) {
665 continue;
666 }
667 const bNodeSocket *input_socket = this->find_internally_linked_input(output_socket);
668 if (input_socket == nullptr) {
669 continue;
670 }
671
672 const Span<const bNodeLink *> connected_links = input_socket->directly_linked_links();
673 const bNodeLink *connected_link = first_non_dangling_link(ntree, connected_links);
674
675 const int index = connected_link ? connected_link->multi_input_sort_id :
676 std::max<int>(0, connected_links.size() - 1);
677 expected_internal_links.append(InternalLink{const_cast<bNodeSocket *>(input_socket),
678 const_cast<bNodeSocket *>(output_socket),
679 index});
680 }
681
682 /* Rebuilt internal links if they have changed. */
683 if (node->runtime->internal_links.size() != expected_internal_links.size()) {
684 this->update_internal_links_in_node(ntree, *node, expected_internal_links);
685 continue;
686 }
687
688 const bool all_expected_internal_links_exist = std::all_of(
689 node->runtime->internal_links.begin(),
690 node->runtime->internal_links.end(),
691 [&](const bNodeLink &link) {
692 const InternalLink internal_link{link.fromsock, link.tosock, link.multi_input_sort_id};
693 return expected_internal_links.as_span().contains(internal_link);
694 });
695
696 if (all_expected_internal_links_exist) {
697 continue;
698 }
699
700 this->update_internal_links_in_node(ntree, *node, expected_internal_links);
701 }
702 }
703
704 const bNodeSocket *find_internally_linked_input(const bNodeSocket *output_socket)
705 {
706 const bNodeSocket *selected_socket = nullptr;
707 int selected_priority = -1;
708 bool selected_is_linked = false;
709 const bNode &node = output_socket->owner_node();
710 if (node.type == GEO_NODE_BAKE) {
711 /* Internal links should always map corresponding input and output sockets. */
712 return &node.input_by_identifier(output_socket->identifier);
713 }
714 for (const bNodeSocket *input_socket : node.input_sockets()) {
715 if (!input_socket->is_available()) {
716 continue;
717 }
718 if (input_socket->flag & SOCK_NO_INTERNAL_LINK) {
719 continue;
720 }
721 const int priority = get_internal_link_type_priority(input_socket->typeinfo,
722 output_socket->typeinfo);
723 if (priority < 0) {
724 continue;
725 }
726 const bool is_linked = input_socket->is_directly_linked();
727 const bool is_preferred = priority > selected_priority || (is_linked && !selected_is_linked);
728 if (!is_preferred) {
729 continue;
730 }
731 selected_socket = input_socket;
732 selected_priority = priority;
733 selected_is_linked = is_linked;
734 }
735 return selected_socket;
736 }
737
738 void update_internal_links_in_node(bNodeTree &ntree,
739 bNode &node,
740 Span<InternalLink> internal_links)
741 {
742 node.runtime->internal_links.clear();
743 node.runtime->internal_links.reserve(internal_links.size());
744 for (const InternalLink &internal_link : internal_links) {
745 bNodeLink link{};
746 link.fromnode = &node;
747 link.fromsock = internal_link.from;
748 link.tonode = &node;
749 link.tosock = internal_link.to;
750 link.multi_input_sort_id = internal_link.multi_input_sort_id;
751 link.flag |= NODE_LINK_VALID;
752 node.runtime->internal_links.append(link);
753 }
755 }
756
757 void update_generic_callback(bNodeTree &ntree)
758 {
759 if (ntree.typeinfo->update == nullptr) {
760 return;
761 }
762 ntree.typeinfo->update(&ntree);
763 }
764
765 void remove_unused_previews_when_necessary(bNodeTree &ntree)
766 {
767 /* Don't trigger preview removal when only those flags are set. */
770 if ((ntree.runtime->changed_flag & allowed_flags) == ntree.runtime->changed_flag) {
771 return;
772 }
774 }
775
776 void make_node_previews_dirty(bNodeTree &ntree)
777 {
778 ntree.runtime->previews_refresh_state++;
779 for (bNode *node : ntree.all_nodes()) {
780 if (node->type != NODE_GROUP) {
781 continue;
782 }
783 if (bNodeTree *nested_tree = reinterpret_cast<bNodeTree *>(node->id)) {
784 this->make_node_previews_dirty(*nested_tree);
785 }
786 }
787 }
788
789 void propagate_runtime_flags(const bNodeTree &ntree)
790 {
791 ntree.ensure_topology_cache();
792
793 ntree.runtime->runtime_flag = 0;
794
795 for (const bNode *group_node : ntree.group_nodes()) {
796 const bNodeTree *group = reinterpret_cast<bNodeTree *>(group_node->id);
797 if (group != nullptr) {
798 ntree.runtime->runtime_flag |= group->runtime->runtime_flag;
799 }
800 }
801
802 if (ntree.type == NTREE_SHADER) {
803 /* Check if the tree itself has an animated image. */
804 for (const StringRefNull idname : {"ShaderNodeTexImage", "ShaderNodeTexEnvironment"}) {
805 for (const bNode *node : ntree.nodes_by_type(idname)) {
806 Image *image = reinterpret_cast<Image *>(node->id);
807 if (image != nullptr && BKE_image_is_animated(image)) {
808 ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION;
809 break;
810 }
811 }
812 }
813 /* Check if the tree has a material output. */
814 for (const StringRefNull idname : {"ShaderNodeOutputMaterial",
815 "ShaderNodeOutputLight",
816 "ShaderNodeOutputWorld",
817 "ShaderNodeOutputAOV"})
818 {
819 const Span<const bNode *> nodes = ntree.nodes_by_type(idname);
820 if (!nodes.is_empty()) {
821 ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT;
822 break;
823 }
824 }
825 }
826 if (ntree.type == NTREE_GEOMETRY) {
827 /* Check if there is a simulation zone. */
828 if (!ntree.nodes_by_type("GeometryNodeSimulationOutput").is_empty()) {
829 ntree.runtime->runtime_flag |= NTREE_RUNTIME_FLAG_HAS_SIMULATION_ZONE;
830 }
831 }
832 }
833
834 void update_from_field_inference(bNodeTree &ntree)
835 {
836 /* Automatically tag a bake item as attribute when the input is a field. The flag should not be
837 * removed automatically even when the field input is disconnected because the baked data may
838 * still contain attribute data instead of a single value. */
839 for (bNode *node : ntree.nodes_by_type("GeometryNodeBake")) {
840 NodeGeometryBake &storage = *static_cast<NodeGeometryBake *>(node->storage);
841 for (const int i : IndexRange(storage.items_num)) {
842 const bNodeSocket &socket = node->input_socket(i);
843 NodeGeometryBakeItem &item = storage.items[i];
844 if (socket.runtime->field_state == FieldSocketState::IsField) {
846 }
847 }
848 }
849 }
850
851 void update_socket_shapes(bNodeTree &ntree)
852 {
853 ntree.ensure_topology_cache();
854 for (bNodeSocket *socket : ntree.all_sockets()) {
855 socket->display_shape = this->get_socket_shape(*socket);
856 }
857 }
858
859 int get_socket_shape(const bNodeSocket &socket)
860 {
861 if (socket.runtime->field_state) {
862 switch (*socket.runtime->field_state) {
869 }
870 }
871 return socket.display_shape;
872 }
873
874 bool propagate_enum_definitions(bNodeTree &ntree)
875 {
876 ntree.ensure_interface_cache();
877
878 /* Propagation from right to left to determine which enum
879 * definition to use for menu sockets. */
880 for (bNode *node : ntree.toposort_right_to_left()) {
881 const bool node_updated = this->should_update_individual_node(ntree, *node);
882
883 if (node->typeinfo->type == GEO_NODE_MENU_SWITCH) {
884 /* Generate new enum items when the node has changed, otherwise keep existing items. */
885 if (node_updated) {
886 const NodeMenuSwitch &storage = *static_cast<NodeMenuSwitch *>(node->storage);
887 const RuntimeNodeEnumItems *enum_items = this->create_runtime_enum_items(
888 storage.enum_definition);
889
890 bNodeSocket &input = *node->input_sockets()[0];
891 BLI_assert(input.is_available() && input.type == SOCK_MENU);
892 this->set_enum_ptr(*input.default_value_typed<bNodeSocketValueMenu>(), enum_items);
893 /* Remove initial user. */
894 enum_items->remove_user_and_delete_if_last();
895 }
896 continue;
897 }
898 else {
899 /* Clear current enum references. */
900 for (bNodeSocket *socket : node->input_sockets()) {
901 if (socket->is_available() && socket->type == SOCK_MENU) {
902 clear_enum_reference(*socket);
903 }
904 }
905 for (bNodeSocket *socket : node->output_sockets()) {
906 if (socket->is_available() && socket->type == SOCK_MENU) {
907 clear_enum_reference(*socket);
908 }
909 }
910 }
911
912 /* Propagate enum references from output links. */
913 for (bNodeSocket *output : node->output_sockets()) {
914 if (!output->is_available() || output->type != SOCK_MENU) {
915 continue;
916 }
917 for (const bNodeSocket *input : output->directly_linked_sockets()) {
918 if (!input->is_available() || input->type != SOCK_MENU) {
919 continue;
920 }
921 this->update_socket_enum_definition(*output->default_value_typed<bNodeSocketValueMenu>(),
922 *input->default_value_typed<bNodeSocketValueMenu>());
923 }
924 }
925
926 if (node->is_group()) {
927 /* Node groups expose internal enum definitions. */
928 if (node->id == nullptr) {
929 continue;
930 }
931 const bNodeTree *group_tree = reinterpret_cast<bNodeTree *>(node->id);
932 group_tree->ensure_interface_cache();
933
934 for (const int socket_i : group_tree->interface_inputs().index_range()) {
935 bNodeSocket &input = *node->input_sockets()[socket_i];
936 const bNodeTreeInterfaceSocket &iosocket = *group_tree->interface_inputs()[socket_i];
937 BLI_assert(STREQ(input.identifier, iosocket.identifier));
938 if (input.is_available() && input.type == SOCK_MENU) {
939 BLI_assert(STREQ(iosocket.socket_type, "NodeSocketMenu"));
940 this->update_socket_enum_definition(
941 *input.default_value_typed<bNodeSocketValueMenu>(),
942 *static_cast<bNodeSocketValueMenu *>(iosocket.socket_data));
943 }
944 }
945 }
946 else if (node->type == GEO_NODE_MENU_SWITCH) {
947 /* First input is always the node's own menu, propagate only to the enum case inputs. */
948 const bNodeSocket *output = node->output_sockets().first();
949 for (bNodeSocket *input : node->input_sockets().drop_front(1)) {
950 if (input->is_available() && input->type == SOCK_MENU) {
951 this->update_socket_enum_definition(
952 *input->default_value_typed<bNodeSocketValueMenu>(),
953 *output->default_value_typed<bNodeSocketValueMenu>());
954 }
955 }
956 }
958 /* Propagate menu from element inputs to field inputs. */
959 BLI_assert(node->input_sockets().size() == node->output_sockets().size());
960 /* Inputs Geometry, Selection and outputs Index, Element are ignored. */
961 const IndexRange sockets = node->input_sockets().index_range().drop_front(2);
962 for (const int socket_i : sockets) {
963 bNodeSocket *input = node->input_sockets()[socket_i];
964 bNodeSocket *output = node->output_sockets()[socket_i];
965 if (input->is_available() && input->type == SOCK_MENU && output->is_available() &&
966 output->type == SOCK_MENU)
967 {
968 this->update_socket_enum_definition(
969 *input->default_value_typed<bNodeSocketValueMenu>(),
970 *output->default_value_typed<bNodeSocketValueMenu>());
971 }
972 }
973 }
974 else {
975 /* Propagate over internal relations. */
976 /* XXX Placeholder implementation just propagates all outputs
977 * to all inputs for built-in nodes This could perhaps use
978 * input/output relations to handle propagation generically? */
979 for (bNodeSocket *input : node->input_sockets()) {
980 if (input->is_available() && input->type == SOCK_MENU) {
981 for (const bNodeSocket *output : node->output_sockets()) {
982 if (output->is_available() && output->type == SOCK_MENU) {
983 this->update_socket_enum_definition(
984 *input->default_value_typed<bNodeSocketValueMenu>(),
985 *output->default_value_typed<bNodeSocketValueMenu>());
986 }
987 }
988 }
989 }
990 }
991 }
992
993 /* Find conflicts between on corresponding menu sockets on different group input nodes. */
994 const Span<bNode *> group_input_nodes = ntree.group_input_nodes();
995 for (const int interface_input_i : ntree.interface_inputs().index_range()) {
996 const bNodeTreeInterfaceSocket &interface_socket =
997 *ntree.interface_inputs()[interface_input_i];
998 if (interface_socket.socket_type != StringRef("NodeSocketMenu")) {
999 continue;
1000 }
1001 const RuntimeNodeEnumItems *found_enum_items = nullptr;
1002 bool found_conflict = false;
1003 for (bNode *input_node : group_input_nodes) {
1004 const bNodeSocket &socket = input_node->output_socket(interface_input_i);
1005 const auto &socket_value = *socket.default_value_typed<bNodeSocketValueMenu>();
1006 if (socket_value.has_conflict()) {
1007 found_conflict = true;
1008 break;
1009 }
1010 if (found_enum_items == nullptr) {
1011 found_enum_items = socket_value.enum_items;
1012 }
1013 else if (socket_value.enum_items != nullptr) {
1014 if (found_enum_items != socket_value.enum_items) {
1015 found_conflict = true;
1016 break;
1017 }
1018 }
1019 }
1020 if (found_conflict) {
1021 /* Make sure that all group input sockets know that there is a socket. */
1022 for (bNode *input_node : group_input_nodes) {
1023 bNodeSocket &socket = input_node->output_socket(interface_input_i);
1024 auto &socket_value = *socket.default_value_typed<bNodeSocketValueMenu>();
1025 if (socket_value.enum_items) {
1026 socket_value.enum_items->remove_user_and_delete_if_last();
1027 socket_value.enum_items = nullptr;
1028 }
1030 }
1031 }
1032 else if (found_enum_items != nullptr) {
1033 /* Make sure all corresponding menu sockets have the same menu reference. */
1034 for (bNode *input_node : group_input_nodes) {
1035 bNodeSocket &socket = input_node->output_socket(interface_input_i);
1036 auto &socket_value = *socket.default_value_typed<bNodeSocketValueMenu>();
1037 if (socket_value.enum_items == nullptr) {
1038 found_enum_items->add_user();
1039 socket_value.enum_items = found_enum_items;
1040 }
1041 }
1042 }
1043 }
1044
1045 /* Build list of new enum items for the node tree interface. */
1046 Vector<bNodeSocketValueMenu> interface_enum_items(ntree.interface_inputs().size(), {0});
1047 for (const bNode *group_input_node : ntree.group_input_nodes()) {
1048 for (const int socket_i : ntree.interface_inputs().index_range()) {
1049 const bNodeSocket &output = *group_input_node->output_sockets()[socket_i];
1050
1051 if (output.is_available() && output.type == SOCK_MENU) {
1052 this->update_socket_enum_definition(interface_enum_items[socket_i],
1053 *output.default_value_typed<bNodeSocketValueMenu>());
1054 }
1055 }
1056 }
1057
1058 /* Move enum items to the interface and detect if anything changed. */
1059 bool changed = false;
1060 for (const int socket_i : ntree.interface_inputs().index_range()) {
1061 bNodeTreeInterfaceSocket &iosocket = *ntree.interface_inputs()[socket_i];
1062 if (STREQ(iosocket.socket_type, "NodeSocketMenu")) {
1063 bNodeSocketValueMenu &dst = *static_cast<bNodeSocketValueMenu *>(iosocket.socket_data);
1064 const bNodeSocketValueMenu &src = interface_enum_items[socket_i];
1065 if (dst.enum_items != src.enum_items || dst.has_conflict() != src.has_conflict()) {
1066 changed = true;
1067 if (dst.enum_items) {
1068 dst.enum_items->remove_user_and_delete_if_last();
1069 }
1070 /* Items are moved, no need to change user count. */
1071 dst.enum_items = src.enum_items;
1073 }
1074 }
1075 }
1076
1077 return changed;
1078 }
1079
1084 const RuntimeNodeEnumItems *create_runtime_enum_items(const NodeEnumDefinition &enum_def)
1085 {
1086 RuntimeNodeEnumItems *enum_items = new RuntimeNodeEnumItems();
1087 enum_items->items.reinitialize(enum_def.items_num);
1088 for (const int i : enum_def.items().index_range()) {
1089 const NodeEnumItem &src = enum_def.items()[i];
1090 RuntimeNodeEnumItem &dst = enum_items->items[i];
1091
1092 dst.identifier = src.identifier;
1093 dst.name = src.name ? src.name : "";
1094 dst.description = src.description ? src.description : "";
1095 }
1096 return enum_items;
1097 }
1098
1099 void clear_enum_reference(bNodeSocket &socket)
1100 {
1101 BLI_assert(socket.is_available() && socket.type == SOCK_MENU);
1102 bNodeSocketValueMenu &default_value = *socket.default_value_typed<bNodeSocketValueMenu>();
1103 this->reset_enum_ptr(default_value);
1104 default_value.runtime_flag &= ~NODE_MENU_ITEMS_CONFLICT;
1105 }
1106
1107 void update_socket_enum_definition(bNodeSocketValueMenu &dst, const bNodeSocketValueMenu &src)
1108 {
1109 if (dst.has_conflict()) {
1110 /* Target enum already has a conflict. */
1111 BLI_assert(dst.enum_items == nullptr);
1112 return;
1113 }
1114
1115 if (src.has_conflict()) {
1116 /* Target conflict if any source enum has a conflict. */
1117 this->reset_enum_ptr(dst);
1119 }
1120 else if (!dst.enum_items) {
1121 /* First connection, set the reference. */
1122 this->set_enum_ptr(dst, src.enum_items);
1123 }
1124 else if (src.enum_items && dst.enum_items != src.enum_items) {
1125 /* Error if enum ref does not match other connections. */
1126 this->reset_enum_ptr(dst);
1128 }
1129 }
1130
1131 void reset_enum_ptr(bNodeSocketValueMenu &dst)
1132 {
1133 if (dst.enum_items) {
1134 dst.enum_items->remove_user_and_delete_if_last();
1135 dst.enum_items = nullptr;
1136 }
1137 }
1138
1139 void set_enum_ptr(bNodeSocketValueMenu &dst, const RuntimeNodeEnumItems *enum_items)
1140 {
1141 if (dst.enum_items) {
1142 dst.enum_items->remove_user_and_delete_if_last();
1143 dst.enum_items = nullptr;
1144 }
1145 if (enum_items) {
1146 enum_items->add_user();
1147 dst.enum_items = enum_items;
1148 }
1149 }
1150
1151 void update_link_validation(bNodeTree &ntree)
1152 {
1153 /* Tests if enum references are undefined. */
1154 const auto is_invalid_enum_ref = [](const bNodeSocket &socket) -> bool {
1155 if (socket.type == SOCK_MENU) {
1156 return socket.default_value_typed<bNodeSocketValueMenu>()->enum_items == nullptr;
1157 }
1158 return false;
1159 };
1160
1161 LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
1162 link->flag |= NODE_LINK_VALID;
1163 if (!link->fromsock->is_available() || !link->tosock->is_available()) {
1164 link->flag &= ~NODE_LINK_VALID;
1165 continue;
1166 }
1167 if (is_invalid_enum_ref(*link->fromsock) || is_invalid_enum_ref(*link->tosock)) {
1168 link->flag &= ~NODE_LINK_VALID;
1169 ntree.runtime->link_errors_by_target_node.add(
1170 link->tonode->identifier,
1171 NodeLinkError{TIP_("Use node groups to reuse the same menu multiple times")});
1172 continue;
1173 }
1174 if (ntree.type == NTREE_GEOMETRY) {
1175 if (link->fromsock->runtime->field_state == FieldSocketState::IsField &&
1176 link->tosock->runtime->field_state != FieldSocketState::IsField)
1177 {
1178 link->flag &= ~NODE_LINK_VALID;
1179 ntree.runtime->link_errors_by_target_node.add(
1180 link->tonode->identifier,
1181 NodeLinkError{TIP_("The node input does not support fields")});
1182 continue;
1183 }
1184 }
1185 const bNode &from_node = *link->fromnode;
1186 const bNode &to_node = *link->tonode;
1187 if (from_node.runtime->toposort_left_to_right_index >
1188 to_node.runtime->toposort_left_to_right_index)
1189 {
1190 link->flag &= ~NODE_LINK_VALID;
1191 ntree.runtime->link_errors_by_target_node.add(
1192 link->tonode->identifier,
1193 NodeLinkError{TIP_("The links form a cycle which is not supported")});
1194 continue;
1195 }
1196 if (ntree.typeinfo->validate_link) {
1197 const eNodeSocketDatatype from_type = eNodeSocketDatatype(link->fromsock->type);
1198 const eNodeSocketDatatype to_type = eNodeSocketDatatype(link->tosock->type);
1199 if (!ntree.typeinfo->validate_link(from_type, to_type)) {
1200 link->flag &= ~NODE_LINK_VALID;
1201 ntree.runtime->link_errors_by_target_node.add(
1202 link->tonode->identifier,
1203 NodeLinkError{fmt::format("{}: {} " BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE
1204 " {}",
1205 TIP_("Conversion is not supported"),
1206 TIP_(link->fromsock->typeinfo->label),
1207 TIP_(link->tosock->typeinfo->label))});
1208 continue;
1209 }
1210 }
1211 }
1212 }
1213
1214 bool check_if_output_changed(const bNodeTree &tree)
1215 {
1216 tree.ensure_topology_cache();
1217
1218 /* Compute a hash that represents the node topology connected to the output. This always has
1219 * to be updated even if it is not used to detect changes right now. Otherwise
1220 * #btree.runtime.output_topology_hash will go out of date. */
1221 const Vector<const bNodeSocket *> tree_output_sockets = this->find_output_sockets(tree);
1222 const uint32_t old_topology_hash = tree.runtime->output_topology_hash;
1223 const uint32_t new_topology_hash = this->get_combined_socket_topology_hash(
1224 tree, tree_output_sockets);
1225 tree.runtime->output_topology_hash = new_topology_hash;
1226
1227 if (const AnimData *adt = BKE_animdata_from_id(&tree.id)) {
1228 /* Drivers may copy values in the node tree around arbitrarily and may cause the output to
1229 * change even if it wouldn't without drivers. Only some special drivers like `frame/5` can
1230 * be used without causing updates all the time currently. In the future we could try to
1231 * handle other drivers better as well.
1232 * Note that this optimization only works in practice when the depsgraph didn't also get a
1233 * copy-on-evaluation tag for the node tree (which happens when changing node properties). It
1234 * does work in a few situations like adding reroutes and duplicating nodes though. */
1235 LISTBASE_FOREACH (const FCurve *, fcurve, &adt->drivers) {
1236 const ChannelDriver *driver = fcurve->driver;
1237 const StringRef expression = driver->expression;
1238 if (expression.startswith("frame")) {
1239 const StringRef remaining_expression = expression.drop_known_prefix("frame");
1240 if (remaining_expression.find_first_not_of(" */+-0123456789.") == StringRef::not_found) {
1241 continue;
1242 }
1243 }
1244 /* Unrecognized driver, assume that the output always changes. */
1245 return true;
1246 }
1247 }
1248
1249 if (tree.runtime->changed_flag & NTREE_CHANGED_ANY) {
1250 return true;
1251 }
1252
1253 if (old_topology_hash != new_topology_hash) {
1254 return true;
1255 }
1256
1257 /* The topology hash can only be used when only topology-changing operations have been done.
1258 */
1259 if (tree.runtime->changed_flag ==
1260 (tree.runtime->changed_flag & (NTREE_CHANGED_LINK | NTREE_CHANGED_REMOVED_NODE)))
1261 {
1262 if (old_topology_hash == new_topology_hash) {
1263 return false;
1264 }
1265 }
1266
1267 if (!this->check_if_socket_outputs_changed_based_on_flags(tree, tree_output_sockets)) {
1268 return false;
1269 }
1270
1271 return true;
1272 }
1273
1274 Vector<const bNodeSocket *> find_output_sockets(const bNodeTree &tree)
1275 {
1277 for (const bNode *node : tree.all_nodes()) {
1278 if (!this->is_output_node(*node)) {
1279 continue;
1280 }
1281 for (const bNodeSocket *socket : node->input_sockets()) {
1282 if (!STREQ(socket->idname, "NodeSocketVirtual")) {
1283 sockets.append(socket);
1284 }
1285 }
1286 }
1287 return sockets;
1288 }
1289
1290 bool is_output_node(const bNode &node) const
1291 {
1292 if (node.typeinfo->nclass == NODE_CLASS_OUTPUT) {
1293 return true;
1294 }
1295 if (node.type == NODE_GROUP_OUTPUT) {
1296 return true;
1297 }
1298 if (node.type == GEO_NODE_WARNING) {
1299 return true;
1300 }
1302 return true;
1303 }
1304 /* Assume node groups without output sockets are outputs. */
1305 if (node.type == NODE_GROUP) {
1306 const bNodeTree *node_group = reinterpret_cast<const bNodeTree *>(node.id);
1307 if (node_group != nullptr &&
1308 node_group->runtime->runtime_flag & NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT)
1309 {
1310 return true;
1311 }
1312 }
1313 return false;
1314 }
1315
1320 uint32_t get_combined_socket_topology_hash(const bNodeTree &tree,
1321 Span<const bNodeSocket *> sockets)
1322 {
1323 if (tree.has_available_link_cycle()) {
1324 /* Return dummy value when the link has any cycles. The algorithm below could be improved
1325 * to handle cycles more gracefully. */
1326 return 0;
1327 }
1328 Array<uint32_t> hashes = this->get_socket_topology_hashes(tree, sockets);
1329 uint32_t combined_hash = 0;
1330 for (uint32_t hash : hashes) {
1331 combined_hash = noise::hash(combined_hash, hash);
1332 }
1333 return combined_hash;
1334 }
1335
1336 Array<uint32_t> get_socket_topology_hashes(const bNodeTree &tree,
1337 const Span<const bNodeSocket *> sockets)
1338 {
1339 BLI_assert(!tree.has_available_link_cycle());
1340 Array<std::optional<uint32_t>> hash_by_socket_id(tree.all_sockets().size());
1341 Stack<const bNodeSocket *> sockets_to_check = sockets;
1342
1343 auto get_socket_ptr_hash = [&](const bNodeSocket &socket) {
1344 const uint64_t socket_ptr = uintptr_t(&socket);
1345 return noise::hash(socket_ptr, socket_ptr >> 32);
1346 };
1347
1348 while (!sockets_to_check.is_empty()) {
1349 const bNodeSocket &socket = *sockets_to_check.peek();
1350 const bNode &node = socket.owner_node();
1351
1352 if (hash_by_socket_id[socket.index_in_tree()].has_value()) {
1353 sockets_to_check.pop();
1354 /* Socket is handled already. */
1355 continue;
1356 }
1357
1358 uint32_t socket_hash = 0;
1359 if (socket.is_input()) {
1360 /* For input sockets, first compute the hashes of all linked sockets. */
1361 bool all_origins_computed = true;
1362 bool get_value_from_origin = false;
1363 for (const bNodeLink *link : socket.directly_linked_links()) {
1364 if (link->is_muted()) {
1365 continue;
1366 }
1367 if (!link->is_available()) {
1368 continue;
1369 }
1370 const bNodeSocket &origin_socket = *link->fromsock;
1371 const std::optional<uint32_t> origin_hash =
1372 hash_by_socket_id[origin_socket.index_in_tree()];
1373 if (origin_hash.has_value()) {
1374 if (get_value_from_origin || socket.type != origin_socket.type) {
1375 socket_hash = noise::hash(socket_hash, *origin_hash);
1376 }
1377 else {
1378 /* Copy the socket hash because the link did not change it. */
1379 socket_hash = *origin_hash;
1380 }
1381 get_value_from_origin = true;
1382 }
1383 else {
1384 sockets_to_check.push(&origin_socket);
1385 all_origins_computed = false;
1386 }
1387 }
1388 if (!all_origins_computed) {
1389 continue;
1390 }
1391
1392 if (!get_value_from_origin) {
1393 socket_hash = get_socket_ptr_hash(socket);
1394 }
1395 }
1396 else {
1397 bool all_available_inputs_computed = true;
1398 for (const bNodeSocket *input_socket : node.input_sockets()) {
1399 if (input_socket->is_available()) {
1400 if (!hash_by_socket_id[input_socket->index_in_tree()].has_value()) {
1401 sockets_to_check.push(input_socket);
1402 all_available_inputs_computed = false;
1403 }
1404 }
1405 }
1406 if (!all_available_inputs_computed) {
1407 continue;
1408 }
1409 if (node.type == NODE_REROUTE) {
1410 socket_hash = *hash_by_socket_id[node.input_socket(0).index_in_tree()];
1411 }
1412 else if (node.is_muted()) {
1413 const bNodeSocket *internal_input = socket.internal_link_input();
1414 if (internal_input == nullptr) {
1415 socket_hash = get_socket_ptr_hash(socket);
1416 }
1417 else {
1418 if (internal_input->type == socket.type) {
1419 socket_hash = *hash_by_socket_id[internal_input->index_in_tree()];
1420 }
1421 else {
1422 socket_hash = get_socket_ptr_hash(socket);
1423 }
1424 }
1425 }
1426 else {
1427 socket_hash = get_socket_ptr_hash(socket);
1428 for (const bNodeSocket *input_socket : node.input_sockets()) {
1429 if (input_socket->is_available()) {
1430 const uint32_t input_socket_hash = *hash_by_socket_id[input_socket->index_in_tree()];
1431 socket_hash = noise::hash(socket_hash, input_socket_hash);
1432 }
1433 }
1434
1435 /* The Image Texture node has a special case. The behavior of the color output changes
1436 * depending on whether the Alpha output is linked. */
1437 if (node.type == SH_NODE_TEX_IMAGE && socket.index() == 0) {
1438 BLI_assert(STREQ(socket.name, "Color"));
1439 const bNodeSocket &alpha_socket = node.output_socket(1);
1440 BLI_assert(STREQ(alpha_socket.name, "Alpha"));
1441 if (alpha_socket.is_directly_linked()) {
1442 socket_hash = noise::hash(socket_hash);
1443 }
1444 }
1445 }
1446 }
1447 hash_by_socket_id[socket.index_in_tree()] = socket_hash;
1448 /* Check that nothing has been pushed in the meantime. */
1449 BLI_assert(sockets_to_check.peek() == &socket);
1450 sockets_to_check.pop();
1451 }
1452
1453 /* Create output array. */
1454 Array<uint32_t> hashes(sockets.size());
1455 for (const int i : sockets.index_range()) {
1456 hashes[i] = *hash_by_socket_id[sockets[i]->index_in_tree()];
1457 }
1458 return hashes;
1459 }
1460
1465 bool check_if_socket_outputs_changed_based_on_flags(const bNodeTree &tree,
1466 Span<const bNodeSocket *> sockets)
1467 {
1468 /* Avoid visiting the same socket twice when multiple links point to the same socket. */
1469 Array<bool> pushed_by_socket_id(tree.all_sockets().size(), false);
1470 Stack<const bNodeSocket *> sockets_to_check = sockets;
1471
1472 for (const bNodeSocket *socket : sockets) {
1473 pushed_by_socket_id[socket->index_in_tree()] = true;
1474 }
1475
1476 while (!sockets_to_check.is_empty()) {
1477 const bNodeSocket &socket = *sockets_to_check.pop();
1478 const bNode &node = socket.owner_node();
1479 if (socket.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
1480 return true;
1481 }
1482 if (node.runtime->changed_flag != NTREE_CHANGED_NOTHING) {
1483 const bool only_unused_internal_link_changed = !node.is_muted() &&
1484 node.runtime->changed_flag ==
1486 if (!only_unused_internal_link_changed) {
1487 return true;
1488 }
1489 }
1490 if (socket.is_input()) {
1491 for (const bNodeSocket *origin_socket : socket.directly_linked_sockets()) {
1492 bool &pushed = pushed_by_socket_id[origin_socket->index_in_tree()];
1493 if (!pushed) {
1494 sockets_to_check.push(origin_socket);
1495 pushed = true;
1496 }
1497 }
1498 }
1499 else {
1500 for (const bNodeSocket *input_socket : node.input_sockets()) {
1501 if (input_socket->is_available()) {
1502 bool &pushed = pushed_by_socket_id[input_socket->index_in_tree()];
1503 if (!pushed) {
1504 sockets_to_check.push(input_socket);
1505 pushed = true;
1506 }
1507 }
1508 }
1509 /* Zones may propagate changes from the input node to the output node even though there is
1510 * no explicit link. */
1511 switch (node.type) {
1515 const bNodeTreeZones *zones = tree.zones();
1516 if (!zones) {
1517 break;
1518 }
1519 const bNodeTreeZone *zone = zones->get_zone_by_node(node.identifier);
1520 if (!zone->input_node) {
1521 break;
1522 }
1523 for (const bNodeSocket *input_socket : zone->input_node->input_sockets()) {
1524 if (input_socket->is_available()) {
1525 bool &pushed = pushed_by_socket_id[input_socket->index_in_tree()];
1526 if (!pushed) {
1527 sockets_to_check.push(input_socket);
1528 pushed = true;
1529 }
1530 }
1531 }
1532 break;
1533 }
1534 }
1535 /* The Normal node has a special case, because the value stored in the first output
1536 * socket is used as input in the node. */
1537 if (node.type == SH_NODE_NORMAL && socket.index() == 1) {
1538 BLI_assert(STREQ(socket.name, "Dot"));
1539 const bNodeSocket &normal_output = node.output_socket(0);
1540 BLI_assert(STREQ(normal_output.name, "Normal"));
1541 bool &pushed = pushed_by_socket_id[normal_output.index_in_tree()];
1542 if (!pushed) {
1543 sockets_to_check.push(&normal_output);
1544 pushed = true;
1545 }
1546 }
1547 }
1548 }
1549 return false;
1550 }
1551
1556 bool update_nested_node_refs(bNodeTree &ntree)
1557 {
1558 ntree.ensure_topology_cache();
1559
1560 /* Simplify lookup of old ids. */
1561 Map<bNestedNodePath, int32_t> old_id_by_path;
1562 Set<int32_t> old_ids;
1563 for (const bNestedNodeRef &ref : ntree.nested_node_refs_span()) {
1564 old_id_by_path.add(ref.path, ref.id);
1565 old_ids.add(ref.id);
1566 }
1567
1568 Vector<bNestedNodePath> nested_node_paths;
1569
1570 /* Don't forget nested node refs just because the linked file is not available right now. */
1571 for (const bNestedNodePath &path : old_id_by_path.keys()) {
1572 const bNode *node = ntree.node_by_id(path.node_id);
1573 if (node && node->is_group() && node->id) {
1574 if (node->id->tag & ID_TAG_MISSING) {
1575 nested_node_paths.append(path);
1576 }
1577 }
1578 }
1579 if (ntree.type == NTREE_GEOMETRY) {
1580 /* Create references for simulations and bake nodes in geometry nodes.
1581 * Those are the nodes that we want to store settings for at a higher level. */
1582 for (StringRefNull idname : {"GeometryNodeSimulationOutput", "GeometryNodeBake"}) {
1583 for (const bNode *node : ntree.nodes_by_type(idname)) {
1584 nested_node_paths.append({node->identifier, -1});
1585 }
1586 }
1587 }
1588 /* Propagate references to nested nodes in group nodes. */
1589 for (const bNode *node : ntree.group_nodes()) {
1590 const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id);
1591 if (group == nullptr) {
1592 continue;
1593 }
1594 for (const int i : group->nested_node_refs_span().index_range()) {
1595 const bNestedNodeRef &child_ref = group->nested_node_refs[i];
1596 nested_node_paths.append({node->identifier, child_ref.id});
1597 }
1598 }
1599
1600 /* Used to generate new unique IDs if necessary. */
1601 RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
1602
1603 Map<int32_t, bNestedNodePath> new_path_by_id;
1604 for (const bNestedNodePath &path : nested_node_paths) {
1605 const int32_t old_id = old_id_by_path.lookup_default(path, -1);
1606 if (old_id != -1) {
1607 /* The same path existed before, it should keep the same ID as before. */
1608 new_path_by_id.add(old_id, path);
1609 continue;
1610 }
1611 int32_t new_id;
1612 while (true) {
1613 new_id = rng.get_int32(INT32_MAX);
1614 if (!old_ids.contains(new_id) && !new_path_by_id.contains(new_id)) {
1615 break;
1616 }
1617 }
1618 /* The path is new, it should get a new ID that does not collide with any existing IDs. */
1619 new_path_by_id.add(new_id, path);
1620 }
1621
1622 /* Check if the old and new references are identical. */
1623 if (!this->nested_node_refs_changed(ntree, new_path_by_id)) {
1624 return false;
1625 }
1626
1628 if (new_path_by_id.is_empty()) {
1629 ntree.nested_node_refs_num = 0;
1630 return true;
1631 }
1632
1633 /* Allocate new array for the nested node references contained in the node tree. */
1634 bNestedNodeRef *new_refs = static_cast<bNestedNodeRef *>(
1635 MEM_malloc_arrayN(new_path_by_id.size(), sizeof(bNestedNodeRef), __func__));
1636 int index = 0;
1637 for (const auto item : new_path_by_id.items()) {
1638 bNestedNodeRef &ref = new_refs[index];
1639 ref.id = item.key;
1640 ref.path = item.value;
1641 index++;
1642 }
1643
1644 ntree.nested_node_refs = new_refs;
1645 ntree.nested_node_refs_num = new_path_by_id.size();
1646
1647 return true;
1648 }
1649
1650 bool nested_node_refs_changed(const bNodeTree &ntree,
1651 const Map<int32_t, bNestedNodePath> &new_path_by_id)
1652 {
1653 if (ntree.nested_node_refs_num != new_path_by_id.size()) {
1654 return true;
1655 }
1656 for (const bNestedNodeRef &ref : ntree.nested_node_refs_span()) {
1657 if (!new_path_by_id.contains(ref.id)) {
1658 return true;
1659 }
1660 }
1661 return false;
1662 }
1663
1664 void reset_changed_flags(bNodeTree &ntree)
1665 {
1666 ntree.runtime->changed_flag = NTREE_CHANGED_NOTHING;
1667 for (bNode *node : ntree.all_nodes()) {
1668 node->runtime->changed_flag = NTREE_CHANGED_NOTHING;
1669 node->runtime->update = 0;
1670 LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
1671 socket->runtime->changed_flag = NTREE_CHANGED_NOTHING;
1672 }
1673 LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
1674 socket->runtime->changed_flag = NTREE_CHANGED_NOTHING;
1675 }
1676 }
1677
1678 ntree.tree_interface.reset_changed_flags();
1679 }
1680};
1681
1682} // namespace blender::bke
1683
1688
1693
1698
1703
1708
1713
1718
1723
1728
1733
1738
1743
1748
1750{
1752}
1753
1755{
1757}
1758
1763
1768
1770{
1771 add_node_tag(ntree, node, NTREE_CHANGED_PARENT);
1772}
1773
1775{
1776 FOREACH_NODETREE_BEGIN (bmain, ntree, ntree_id) {
1777 for (bNode *node : ntree->all_nodes()) {
1778 if (node->id == id) {
1779 node->runtime->update |= NODE_UPDATE_ID;
1781 }
1782 }
1783 }
1785}
1786
1788{
1789 /* Would have to search for the node that uses the image user for a more detailed tag. */
1791}
1792
1793uint64_t bNestedNodePath::hash() const
1794{
1795 return blender::get_default_hash(this->node_id, this->id_in_node);
1796}
1797
1799{
1800 return a.node_id == b.node_id && a.id_in_node == b.id_in_node;
1801}
1802
1810static bool is_updating = false;
1811
1813{
1814 if (is_updating) {
1815 return;
1816 }
1817
1818 is_updating = true;
1820 updater.update();
1821 is_updating = false;
1822}
1823
1825{
1826 if (ntree == nullptr) {
1828 return;
1829 }
1830
1831 if (is_updating) {
1832 return;
1833 }
1834
1835 is_updating = true;
1837 updater.update_rooted({ntree});
1838 is_updating = false;
1839}
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
bool BKE_image_is_animated(Image *image)
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:405
#define NODE_REROUTE
Definition BKE_node.hh:804
#define SH_NODE_NORMAL
Definition BKE_node.hh:898
#define GEO_NODE_MENU_SWITCH
Definition BKE_node.hh:1354
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT
Definition BKE_node.hh:1378
#define SH_NODE_TEX_IMAGE
Definition BKE_node.hh:930
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
Definition BKE_node.hh:1379
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define GEO_NODE_SIMULATION_OUTPUT
Definition BKE_node.hh:1331
#define FOREACH_NODETREE_END
Definition BKE_node.hh:870
#define GEO_NODE_BAKE
Definition BKE_node.hh:1350
#define NODE_GROUP
Definition BKE_node.hh:800
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition BKE_node.hh:860
#define GEO_NODE_WARNING
Definition BKE_node.hh:1377
#define GEO_NODE_REPEAT_OUTPUT
Definition BKE_node.hh:1338
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
void BKE_ntree_update_tag_node_internal_link(bNodeTree *ntree, bNode *node)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
#define BLI_STRUCT_EQUALITY_OPERATORS_3(Type, m1, m2, m3)
#define UNUSED_VARS_NDEBUG(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
@ ID_TAG_MISSING
Definition DNA_ID.h:813
@ ID_NT
struct FCurve FCurve
struct AnimData AnimData
struct ChannelDriver ChannelDriver
struct Image Image
@ eModifierType_Nodes
struct bNodeTreeInterfaceSocket bNodeTreeInterfaceSocket
struct NodeMenuSwitch NodeMenuSwitch
struct bNodeSocketValueMenu bNodeSocketValueMenu
struct bNestedNodeRef bNestedNodeRef
struct NodeGeometryBake NodeGeometryBake
struct NodeEnumDefinition NodeEnumDefinition
struct NodeGeometryBakeItem NodeGeometryBakeItem
@ GEO_NODE_BAKE_ITEM_IS_ATTRIBUTE
struct bNodeLink bNodeLink
@ NTREE_RUNTIME_FLAG_HAS_SIMULATION_ZONE
@ NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT
@ NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION
@ SOCK_IS_LINKED
@ SOCK_NO_INTERNAL_LINK
struct bNode bNode
@ SOCK_DISPLAY_SHAPE_CIRCLE
@ SOCK_DISPLAY_SHAPE_DIAMOND
@ SOCK_DISPLAY_SHAPE_DIAMOND_DOT
@ NTREE_TEXTURE
@ NTREE_SHADER
@ NTREE_GEOMETRY
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_CUSTOM
@ SOCK_ROTATION
@ SOCK_RGBA
@ SOCK_MENU
struct bNodeTree bNodeTree
@ NODE_LINK_VALID
struct bNestedNodePath bNestedNodePath
struct NodeEnumItem NodeEnumItem
@ NODE_UPDATE_ID
struct bNodeSocket bNodeSocket
#define MEM_SAFE_FREE(v)
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Definition MOD_nodes.cc:453
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
void ntreeTexCheckCyclics(struct bNodeTree *ntree)
#define output
KeyIterator keys() const
Definition BLI_map.hh:837
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
int64_t size() const
Definition BLI_map.hh:927
ItemIterator items() const
Definition BLI_map.hh:864
bool is_empty() const
Definition BLI_map.hh:937
bool contains(const Key &key) const
Definition BLI_map.hh:329
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
void add_new(const Key &key)
Definition BLI_set.hh:233
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr bool is_empty() const
Definition BLI_span.hh:261
T & peek()
Definition BLI_stack.hh:263
bool is_empty() const
Definition BLI_stack.hh:308
T pop()
Definition BLI_stack.hh:242
void push(const T &value)
Definition BLI_stack.hh:213
constexpr StringRef drop_known_prefix(StringRef prefix) const
bool add(const Key &key)
bool is_empty() const
int64_t size() const
void append(const T &value)
Span< T > as_span() const
static RandomNumberGenerator from_random_seed()
Definition rand.cc:365
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:261
static constexpr int64_t not_found
constexpr int64_t find_first_not_of(StringRef chars, int64_t pos=0) const
constexpr bool startswith(StringRef prefix) const
void append(const T &value)
void update_rooted(Span< bNodeTree * > root_ntrees)
NodeTreeMainUpdater(Main *bmain, NodeTreeUpdateExtraParams *params)
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
Vector< std::unique_ptr< bNodeTreeZone > > zones
local_group_size(16, 16) .push_constant(Type b
KDTree_3d * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition iris.cc:202
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
const bNodeZoneType * zone_type_by_node_type(const int node_type)
std::pair< Object *, ModifierData * > ObjectModifierPair
std::pair< bNodeTree *, bNode * > TreeNodePair
void node_preview_remove_unused(bNodeTree *ntree)
Definition node.cc:3376
Span< int > all_zone_input_node_types()
static bool is_tree_changed(const bNodeTree &tree)
std::pair< bNode *, bNodeSocket * > NodeSocketPair
bool node_declaration_ensure(bNodeTree *ntree, bNode *node)
Definition node.cc:3992
static int get_internal_link_type_priority(const bNodeSocketType *from, const bNodeSocketType *to)
static Type to_type(const eGPUType type)
bool update_tree_gizmo_propagation(bNodeTree &tree)
bool is_builtin_gizmo_node(const bNode &node)
void index(const bNode &, void *r_value)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
uint32_t hash(uint32_t kx)
Definition noise.cc:72
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
void BKE_ntree_update_tag_node_new(bNodeTree *ntree, bNode *node)
static void add_node_tag(bNodeTree *ntree, bNode *node, const eNodeTreeChangedFlag flag)
void BKE_ntree_update_tag_active_output_changed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_type(bNodeTree *ntree, bNodeSocket *socket)
void BKE_ntree_update_tag_node_internal_link(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_node_mute(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_all(bNodeTree *ntree)
void BKE_ntree_update_tag_link_mute(bNodeTree *ntree, bNodeLink *)
void BKE_ntree_update_tag_link_changed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_new(bNodeTree *ntree, bNodeSocket *socket)
bool operator==(const bNestedNodePath &a, const bNestedNodePath &b)
void BKE_ntree_update_tag_socket_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_property(bNodeTree *ntree, bNodeSocket *socket)
static void add_socket_tag(bNodeTree *ntree, bNodeSocket *socket, const eNodeTreeChangedFlag flag)
static void add_tree_tag(bNodeTree *ntree, const eNodeTreeChangedFlag flag)
void BKE_ntree_update_main(Main *bmain, NodeTreeUpdateExtraParams *params)
void BKE_ntree_update_tag_missing_runtime_data(bNodeTree *ntree)
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
static bool is_updating
void BKE_ntree_update_tag_link_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_availability(bNodeTree *ntree, bNodeSocket *socket)
void BKE_ntree_update_tag_link_added(bNodeTree *ntree, bNodeLink *)
void BKE_ntree_update_tag_node_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
void BKE_ntree_update_tag_image_user_changed(bNodeTree *ntree, ImageUser *)
eNodeTreeChangedFlag
@ NTREE_CHANGED_ANY
@ NTREE_CHANGED_REMOVED_SOCKET
@ NTREE_CHANGED_NOTHING
@ NTREE_CHANGED_NODE_OUTPUT
@ NTREE_CHANGED_NODE_PROPERTY
@ NTREE_CHANGED_LINK
@ NTREE_CHANGED_SOCKET_PROPERTY
@ NTREE_CHANGED_REMOVED_NODE
@ NTREE_CHANGED_PARENT
@ NTREE_CHANGED_ALL
@ NTREE_CHANGED_INTERNAL_LINK
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_parent_change(bNodeTree *ntree, bNode *node)
#define hash
Definition noise.c:154
#define INT32_MAX
Definition stdint.h:137
_W64 unsigned int uintptr_t
Definition stdint.h:119
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned __int64 uint64_t
Definition stdint.h:90
char expression[256]
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
NodeGeometryBakeItem * items
NodeEnumDefinition enum_definition
struct bNodeTree * node_group
bNestedNodePath path
const RuntimeNodeEnumItemsHandle * enum_items
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
char identifier[64]
char idname[64]
bNodeTreeRuntimeHandle * runtime
int nested_node_refs_num
bNestedNodeRef * nested_node_refs
bNodeTreeTypeHandle * typeinfo
bNodeTreeInterface tree_interface
ListBase links
bNodeTypeHandle * typeinfo
ListBase inputs
struct ID * id
bNodeRuntimeHandle * runtime
void * storage
ListBase outputs
int32_t identifier
int16_t type
ID * get_owner_id(bNodeTree *ntree)
Span< TreeNodePair > get_group_node_users(bNodeTree *ntree)
Span< ObjectModifierPair > get_modifier_users(bNodeTree *ntree)
Defines a socket type.
Definition BKE_node.hh:151
blender::nodes::NodeDeclaration * static_declaration
Definition BKE_node.hh:356
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* group_update_func)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:259
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:257
uint8_t flag
Definition wm_window.cc:138