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 }
507 if (node_field_inferencing::update_field_inferencing(ntree)) {
508 result.interface_changed = true;
509 }
510 this->update_from_field_inference(ntree);
511 if (anonymous_attribute_inferencing::update_anonymous_attribute_relations(ntree)) {
512 result.interface_changed = true;
513 }
514 if (nodes::gizmos::update_tree_gizmo_propagation(ntree)) {
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);
589 nodes::update_node_declaration_and_sockets(ntree, *node);
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()) {
612 if (ELEM(node.type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
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 {
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) {
863 case bke::FieldSocketState::RequiresSingle:
865 case bke::FieldSocketState::CanBeField:
867 case bke::FieldSocketState::IsField:
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 }
957 else if (node->type == GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT) {
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 }
1029 socket_value.runtime_flag |= NodeSocketValueMenuRuntimeFlag::NODE_MENU_ITEMS_CONFLICT;
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;
1072 SET_FLAG_FROM_TEST(dst.runtime_flag, src.has_conflict(), NODE_MENU_ITEMS_CONFLICT);
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 {
1276 Vector<const bNodeSocket *> sockets;
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 }
1301 if (nodes::gizmos::is_builtin_gizmo_node(node)) {
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,
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,
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 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 NODE_GROUP
Definition BKE_node.hh:800
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition BKE_node.hh:860
#define GEO_NODE_REPEAT_OUTPUT
Definition BKE_node.hh:1338
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#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
@ eModifierType_Nodes
@ NTREE_TEXTURE
@ NTREE_SHADER
@ NTREE_GEOMETRY
@ NODE_LINK_VALID
@ NODE_UPDATE_ID
@ GEO_NODE_BAKE_ITEM_IS_ATTRIBUTE
@ 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
@ SOCK_DISPLAY_SHAPE_CIRCLE
@ SOCK_DISPLAY_SHAPE_DIAMOND
@ SOCK_DISPLAY_SHAPE_DIAMOND_DOT
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_CUSTOM
@ SOCK_ROTATION
@ SOCK_RGBA
@ SOCK_MENU
#define MEM_SAFE_FREE(v)
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Definition MOD_nodes.cc:453
void ntreeTexCheckCyclics(struct bNodeTree *ntree)
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) const
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
ItemIterator items() const
Definition BLI_map.hh:864
bool contains(const Key &key) const
Definition BLI_map.hh:329
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:261
bool is_empty() const
Definition BLI_stack.hh:308
void push(const T &value)
Definition BLI_stack.hh:213
constexpr int64_t find_first_not_of(StringRef chars, int64_t pos=0) const
constexpr bool startswith(StringRef prefix) const
constexpr StringRef drop_known_prefix(StringRef prefix) const
bool add(const Key &key)
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
OperationNode * node
StackEntry * from
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
static int get_internal_link_type_priority(const bNodeSocketType *from, const bNodeSocketType *to)
static Type to_type(const eGPUType type)
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
ListBase objects
Definition BKE_main.hh:212
NodeGeometryBakeItem * items
NodeEnumDefinition enum_definition
void(* tree_changed_fn)(ID *, bNodeTree *, void *user_data)
void(* tree_output_changed_fn)(ID *, bNodeTree *, void *user_data)
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
bNodeRuntimeHandle * runtime
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
Defines a node type.
Definition BKE_node.hh:218
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