Blender V4.3
BKE_node_runtime.hh
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#pragma once
6
7#include <memory>
8#include <mutex>
9
10#include "BLI_cache_mutex.hh"
13#include "BLI_resource_scope.hh"
14#include "BLI_set.hh"
15#include "BLI_utility_mixins.hh"
16#include "BLI_vector.hh"
17#include "BLI_vector_set.hh"
18
19#include "DNA_node_types.h"
20
21#include "BKE_node.hh"
23
24struct bNode;
25struct bNodeSocket;
26struct bNodeTree;
27
28namespace blender::nodes {
29struct FieldInferencingInterface;
30class NodeDeclaration;
31struct GeometryNodesLazyFunctionGraphInfo;
32namespace anonymous_attribute_lifetime {
33}
34namespace aal = anonymous_attribute_lifetime;
35namespace gizmos {
37}
38} // namespace blender::nodes
39namespace blender::bke {
40struct bNodeType;
41class bNodeTreeZones;
42} // namespace blender::bke
46
47namespace blender {
48
49struct NodeIDHash {
50 uint64_t operator()(const bNode *node) const
51 {
52 return node->identifier;
53 }
54 uint64_t operator()(const int32_t id) const
55 {
56 return id;
57 }
58};
59
61 bool operator()(const bNode *a, const bNode *b) const
62 {
63 return a->identifier == b->identifier;
64 }
65 bool operator()(const bNode *a, const int32_t b) const
66 {
67 return a->identifier == b;
68 }
69 bool operator()(const int32_t a, const bNode *b) const
70 {
71 return this->operator()(b, a);
72 }
73};
74
75} // namespace blender
76
77namespace blender::bke {
78
80
82 std::string tooltip;
83};
84
94
102 public:
114
120
126
128 std::unique_ptr<LoggedZoneGraphs> logged_zone_graphs;
129
136
144 void (*progress)(void *, float progress) = nullptr;
146 void (*stats_draw)(void *, const char *str) = nullptr;
147 bool (*test_break)(void *) = nullptr;
148 void (*update_draw)(void *) = nullptr;
149 void *tbh = nullptr, *prh = nullptr, *sdh = nullptr, *udh = nullptr;
150
151 /* End legacy execution data. */
152
154 std::unique_ptr<nodes::FieldInferencingInterface> field_inferencing_interface;
156 std::unique_ptr<anonymous_attribute_inferencing::AnonymousAttributeInferencingResult>
158 std::unique_ptr<nodes::gizmos::TreeGizmoPropagation> gizmo_propagation;
159
166 std::unique_ptr<nodes::GeometryNodesLazyFunctionGraphInfo>
168
175
181 std::atomic<bool> topology_cache_exists = false;
186 mutable std::atomic<int> allow_use_dirty_topology_cache = 0;
187
189 std::unique_ptr<bNodeTreeZones> tree_zones;
190
196
210};
211
215 IsField,
216};
217
264
266 public:
267 /* The vertical location of the panel in the tree, calculated while drawing the nodes and invalid
268 * if the node tree hasn't been drawn yet. In the node tree's "world space" (the same as
269 * #bNode::runtime::totr). */
271 /* Vertical start location of the panel content. */
273 /* Vertical end location of the panel content. */
275};
276
369
370namespace node_tree_runtime {
371
376
378 private:
379 const bNodeTree &tree_;
380
381 public:
383 {
384 tree_.runtime->allow_use_dirty_topology_cache.fetch_add(1);
385 }
386
388 {
389 tree_.runtime->allow_use_dirty_topology_cache.fetch_sub(1);
390 }
391};
392
394{
395 if (!tree.runtime->topology_cache_exists) {
396 return false;
397 }
398 if (tree.runtime->allow_use_dirty_topology_cache.load() > 0) {
399 return true;
400 }
401 if (tree.runtime->topology_cache_mutex.is_dirty()) {
402 return false;
403 }
404 return true;
405}
406
407inline bool topology_cache_is_available(const bNode &node)
408{
409 const bNodeTree *ntree = node.runtime->owner_tree;
410 if (ntree == nullptr) {
411 return false;
412 }
413 return topology_cache_is_available(*ntree);
414}
415
416inline bool topology_cache_is_available(const bNodeSocket &socket)
417{
418 const bNode *node = socket.runtime->owner_node;
419 if (node == nullptr) {
420 return false;
421 }
422 return topology_cache_is_available(*node);
423}
424
425} // namespace node_tree_runtime
426
427namespace node_field_inferencing {
429}
430} // namespace blender::bke
431
432/* -------------------------------------------------------------------- */
436inline blender::Span<const bNode *> bNodeTree::all_nodes() const
437{
438 return this->runtime->nodes_by_id.as_span();
439}
440
441inline blender::Span<bNode *> bNodeTree::all_nodes()
442{
443 return this->runtime->nodes_by_id;
444}
445
446inline bNode *bNodeTree::node_by_id(const int32_t identifier)
447{
448 BLI_assert(identifier >= 0);
449 bNode *const *node = this->runtime->nodes_by_id.lookup_key_ptr_as(identifier);
450 return node ? *node : nullptr;
451}
452
453inline const bNode *bNodeTree::node_by_id(const int32_t identifier) const
454{
455 BLI_assert(identifier >= 0);
456 const bNode *const *node = this->runtime->nodes_by_id.lookup_key_ptr_as(identifier);
457 return node ? *node : nullptr;
458}
459
460inline blender::Span<bNode *> bNodeTree::nodes_by_type(const blender::StringRefNull type_idname)
461{
463 return this->runtime->nodes_by_type.lookup(blender::bke::node_type_find(type_idname.c_str()));
464}
465
466inline blender::Span<const bNode *> bNodeTree::nodes_by_type(
467 const blender::StringRefNull type_idname) const
468{
470 return this->runtime->nodes_by_type.lookup(blender::bke::node_type_find(type_idname.c_str()));
471}
472
473inline blender::Span<const bNode *> bNodeTree::toposort_left_to_right() const
474{
476 return this->runtime->toposort_left_to_right;
477}
478
479inline blender::Span<const bNode *> bNodeTree::toposort_right_to_left() const
480{
482 return this->runtime->toposort_right_to_left;
483}
484
485inline blender::Span<bNode *> bNodeTree::toposort_left_to_right()
486{
488 return this->runtime->toposort_left_to_right;
489}
490
491inline blender::Span<bNode *> bNodeTree::toposort_right_to_left()
492{
494 return this->runtime->toposort_right_to_left;
495}
496
497inline blender::Span<const bNode *> bNodeTree::group_nodes() const
498{
500 return this->runtime->group_nodes;
501}
502
503inline blender::Span<bNode *> bNodeTree::group_nodes()
504{
506 return this->runtime->group_nodes;
507}
508
509inline bool bNodeTree::has_available_link_cycle() const
510{
512 return this->runtime->has_available_link_cycle;
513}
514
515inline bool bNodeTree::has_undefined_nodes_or_sockets() const
516{
518 return this->runtime->has_undefined_nodes_or_sockets;
519}
520
521inline bNode *bNodeTree::group_output_node()
522{
524 return this->runtime->group_output_node;
525}
526
527inline const bNode *bNodeTree::group_output_node() const
528{
530 return this->runtime->group_output_node;
531}
532
533inline blender::Span<bNode *> bNodeTree::group_input_nodes()
534{
535 return this->nodes_by_type("NodeGroupInput");
536}
537
538inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const
539{
540 return this->nodes_by_type("NodeGroupInput");
541}
542
543inline blender::Span<const bNodeSocket *> bNodeTree::all_input_sockets() const
544{
546 return this->runtime->input_sockets;
547}
548
549inline blender::Span<bNodeSocket *> bNodeTree::all_input_sockets()
550{
552 return this->runtime->input_sockets;
553}
554
555inline blender::Span<const bNodeSocket *> bNodeTree::all_output_sockets() const
556{
558 return this->runtime->output_sockets;
559}
560
561inline blender::Span<bNodeSocket *> bNodeTree::all_output_sockets()
562{
564 return this->runtime->output_sockets;
565}
566
567inline blender::Span<const bNodeSocket *> bNodeTree::all_sockets() const
568{
570 return this->runtime->sockets;
571}
572
573inline blender::Span<bNodeSocket *> bNodeTree::all_sockets()
574{
576 return this->runtime->sockets;
577}
578
579inline blender::Span<bNode *> bNodeTree::root_frames() const
580{
582 return this->runtime->root_frames;
583}
584
585inline blender::Span<bNodeLink *> bNodeTree::all_links()
586{
588 return this->runtime->links;
589}
590
591inline blender::Span<const bNodeLink *> bNodeTree::all_links() const
592{
594 return this->runtime->links;
595}
596
597inline blender::MutableSpan<bNestedNodeRef> bNodeTree::nested_node_refs_span()
598{
599 return {this->nested_node_refs, this->nested_node_refs_num};
600}
601
602inline blender::Span<bNestedNodeRef> bNodeTree::nested_node_refs_span() const
603{
604 return {this->nested_node_refs, this->nested_node_refs_num};
605}
606
607inline void bNodeTree::ensure_interface_cache() const
608{
609 this->tree_interface.ensure_items_cache();
610}
611
612inline blender::Span<bNodeTreeInterfaceSocket *> bNodeTree::interface_inputs()
613{
614 BLI_assert(this->tree_interface.items_cache_is_available());
615 return this->tree_interface.runtime->inputs_;
616}
617
618inline blender::Span<const bNodeTreeInterfaceSocket *> bNodeTree::interface_inputs() const
619{
620 BLI_assert(this->tree_interface.items_cache_is_available());
621 return this->tree_interface.runtime->inputs_;
622}
623
624inline blender::Span<bNodeTreeInterfaceSocket *> bNodeTree::interface_outputs()
625{
626 BLI_assert(this->tree_interface.items_cache_is_available());
627 return this->tree_interface.runtime->outputs_;
628}
629
630inline blender::Span<const bNodeTreeInterfaceSocket *> bNodeTree::interface_outputs() const
631{
632 BLI_assert(this->tree_interface.items_cache_is_available());
633 return this->tree_interface.runtime->outputs_;
634}
635
636inline blender::Span<bNodeTreeInterfaceItem *> bNodeTree::interface_items()
637{
638 BLI_assert(this->tree_interface.items_cache_is_available());
639 return this->tree_interface.runtime->items_;
640}
641
642inline blender::Span<const bNodeTreeInterfaceItem *> bNodeTree::interface_items() const
643{
644 BLI_assert(this->tree_interface.items_cache_is_available());
645 return this->tree_interface.runtime->items_;
646}
647
650/* -------------------------------------------------------------------- */
654inline int bNode::index() const
655{
656 const int index = this->runtime->index_in_tree;
657 /* The order of nodes should always be consistent with the `nodes_by_id` vector. */
658 BLI_assert(index ==
659 this->runtime->owner_tree->runtime->nodes_by_id.index_of_as(this->identifier));
660 return index;
661}
662
663inline blender::Span<bNodeSocket *> bNode::input_sockets()
664{
666 return this->runtime->inputs;
667}
668
669inline blender::Span<bNodeSocket *> bNode::output_sockets()
670{
672 return this->runtime->outputs;
673}
674
675inline blender::Span<const bNodeSocket *> bNode::input_sockets() const
676{
678 return this->runtime->inputs;
679}
680
681inline blender::Span<const bNodeSocket *> bNode::output_sockets() const
682{
684 return this->runtime->outputs;
685}
686
687inline bNodeSocket &bNode::input_socket(int index)
688{
690 return *this->runtime->inputs[index];
691}
692
693inline bNodeSocket &bNode::output_socket(int index)
694{
696 return *this->runtime->outputs[index];
697}
698
699inline const bNodeSocket &bNode::input_socket(int index) const
700{
702 return *this->runtime->inputs[index];
703}
704
705inline const bNodeSocket &bNode::output_socket(int index) const
706{
708 return *this->runtime->outputs[index];
709}
710
711inline const bNodeSocket &bNode::input_by_identifier(blender::StringRef identifier) const
712{
714 return *this->runtime->inputs_by_identifier.lookup_as(identifier);
715}
716
717inline const bNodeSocket &bNode::output_by_identifier(blender::StringRef identifier) const
718{
720 return *this->runtime->outputs_by_identifier.lookup_as(identifier);
721}
722
723inline bNodeSocket &bNode::input_by_identifier(blender::StringRef identifier)
724{
726 return *this->runtime->inputs_by_identifier.lookup_as(identifier);
727}
728
729inline bNodeSocket &bNode::output_by_identifier(blender::StringRef identifier)
730{
732 return *this->runtime->outputs_by_identifier.lookup_as(identifier);
733}
734
735inline const bNodeTree &bNode::owner_tree() const
736{
738 return *this->runtime->owner_tree;
739}
740
741inline bNodeTree &bNode::owner_tree()
742{
744 return *this->runtime->owner_tree;
745}
746
747inline blender::StringRefNull bNode::label_or_name() const
748{
749 if (this->label[0] == '\0') {
750 return this->name;
751 }
752 return this->label;
753}
754
755inline bool bNode::is_muted() const
756{
757 return this->flag & NODE_MUTED;
758}
759
760inline bool bNode::is_reroute() const
761{
762 return this->type == NODE_REROUTE;
763}
764
765inline bool bNode::is_frame() const
766{
767 return this->type == NODE_FRAME;
768}
769
770inline bool bNode::is_group() const
771{
772 return ELEM(this->type, NODE_GROUP, NODE_CUSTOM_GROUP);
773}
774
775inline bool bNode::is_group_input() const
776{
777 return this->type == NODE_GROUP_INPUT;
778}
779
780inline bool bNode::is_group_output() const
781{
782 return this->type == NODE_GROUP_OUTPUT;
783}
784
785inline blender::Span<bNodeLink> bNode::internal_links() const
786{
787 return this->runtime->internal_links;
788}
789
790inline bool bNode::is_dangling_reroute() const
791{
793 return this->runtime->is_dangling_reroute;
794}
795
796inline bool bNode::is_socket_drawn(const bNodeSocket &socket) const
797{
798 return socket.is_visible();
799}
800
801inline bool bNode::is_socket_icon_drawn(const bNodeSocket &socket) const
802{
803 return socket.is_visible() && (this->flag & NODE_HIDDEN || !socket.is_panel_collapsed());
804}
805
806inline blender::Span<bNode *> bNode::direct_children_in_frame() const
807{
809 BLI_assert(this->is_frame());
810 return this->runtime->direct_children_in_frame;
811}
812
813inline const blender::nodes::NodeDeclaration *bNode::declaration() const
814{
815 return this->runtime->declaration;
816}
817
818inline blender::Span<bNodePanelState> bNode::panel_states() const
819{
821}
822
823inline blender::MutableSpan<bNodePanelState> bNode::panel_states()
824{
826}
827
830/* -------------------------------------------------------------------- */
834inline bool bNodeLink::is_muted() const
835{
836 return this->flag & NODE_LINK_MUTED;
837}
838
839inline bool bNodeLink::is_available() const
840{
841 return this->fromsock->is_available() && this->tosock->is_available();
842}
843
844inline bool bNodeLink::is_used() const
845{
846 return !this->is_muted() && this->is_available();
847}
848
851/* -------------------------------------------------------------------- */
855inline int bNodeSocket::index() const
856{
858 return this->runtime->index_in_node;
859}
860
861inline int bNodeSocket::index_in_tree() const
862{
864 return this->runtime->index_in_all_sockets;
865}
866
867inline int bNodeSocket::index_in_all_inputs() const
868{
870 BLI_assert(this->is_input());
871 return this->runtime->index_in_inout_sockets;
872}
873
874inline int bNodeSocket::index_in_all_outputs() const
875{
877 BLI_assert(this->is_output());
878 return this->runtime->index_in_inout_sockets;
879}
880
881inline bool bNodeSocket::is_hidden() const
882{
883 return (this->flag & SOCK_HIDDEN) != 0;
884}
885
886inline bool bNodeSocket::is_available() const
887{
888 return (this->flag & SOCK_UNAVAIL) == 0;
889}
890
891inline bool bNodeSocket::is_panel_collapsed() const
892{
893 return (this->flag & SOCK_PANEL_COLLAPSED) != 0;
894}
895
896inline bool bNodeSocket::is_visible() const
897{
898 return !this->is_hidden() && this->is_available();
899}
900
901inline bNode &bNodeSocket::owner_node()
902{
904 return *this->runtime->owner_node;
905}
906
907inline const bNodeTree &bNodeSocket::owner_tree() const
908{
910 return *this->runtime->owner_node->runtime->owner_tree;
911}
912
913inline bNodeTree &bNodeSocket::owner_tree()
914{
916 return *this->runtime->owner_node->runtime->owner_tree;
917}
918
919inline blender::Span<const bNodeSocket *> bNodeSocket::logically_linked_sockets() const
920{
922 return this->runtime->logically_linked_sockets;
923}
924
925inline blender::Span<const bNodeLink *> bNodeSocket::directly_linked_links() const
926{
928 return this->runtime->directly_linked_links;
929}
930
931inline blender::Span<bNodeLink *> bNodeSocket::directly_linked_links()
932{
934 return this->runtime->directly_linked_links;
935}
936
937inline blender::Span<const bNodeSocket *> bNodeSocket::directly_linked_sockets() const
938{
940 return this->runtime->directly_linked_sockets;
941}
942
943inline blender::Span<bNodeSocket *> bNodeSocket::directly_linked_sockets()
944{
946 return this->runtime->directly_linked_sockets;
947}
948
949inline bool bNodeSocket::is_directly_linked() const
950{
951 return !this->directly_linked_links().is_empty();
952}
953
954inline bool bNodeSocket::is_logically_linked() const
955{
956 return !this->logically_linked_sockets().is_empty();
957}
958
959inline const bNodeSocket *bNodeSocket::internal_link_input() const
960{
962 BLI_assert(this->in_out == SOCK_OUT);
963 return this->runtime->internal_link_input;
964}
965
966template<typename T> T *bNodeSocket::default_value_typed()
967{
968 return static_cast<T *>(this->default_value);
969}
970
971template<typename T> const T *bNodeSocket::default_value_typed() const
972{
973 return static_cast<const T *>(this->default_value);
974}
975
976inline bool bNodeSocket::is_input() const
977{
978 return this->in_out == SOCK_IN;
979}
980
981inline bool bNodeSocket::is_output() const
982{
983 return this->in_out == SOCK_OUT;
984}
985
986inline bool bNodeSocket::is_multi_input() const
987{
988 return this->flag & SOCK_MULTI_INPUT;
989}
990
991inline const bNode &bNodeSocket::owner_node() const
992{
994 return *this->runtime->owner_node;
995}
996
999/* -------------------------------------------------------------------- */
1003inline bool bNodePanelState::is_collapsed() const
1004{
1005 return flag & NODE_PANEL_COLLAPSED;
1006}
1007
1008inline bool bNodePanelState::is_parent_collapsed() const
1009{
1011}
1012
1013inline bool bNodePanelState::has_visible_content() const
1014{
1016}
1017
#define NODE_REROUTE
Definition BKE_node.hh:804
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define NODE_GROUP
Definition BKE_node.hh:800
#define NODE_FRAME
Definition BKE_node.hh:803
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
@ NODE_HIDDEN
@ NODE_MUTED
@ NODE_LINK_MUTED
@ SOCK_OUT
@ SOCK_IN
@ SOCK_MULTI_INPUT
@ SOCK_PANEL_COLLAPSED
@ SOCK_HIDDEN
@ SOCK_UNAVAIL
@ NODE_PANEL_COLLAPSED
@ NODE_PANEL_PARENT_COLLAPSED
@ NODE_PANEL_CONTENT_VISIBLE
constexpr const char * c_str() const
Array< bNodePanelRuntime > panels
Map< StringRefNull, bNodeSocket * > outputs_by_identifier
Vector< bNode * > direct_children_in_frame
Vector< bNodeSocket * > outputs
Map< StringRefNull, bNodeSocket * > inputs_by_identifier
Vector< bNodeSocket * > inputs
nodes::NodeDeclaration * declaration
Vector< bNodeLink > internal_links
Vector< bNodeSocket * > logically_linked_skipped_sockets
Vector< bNodeSocket * > directly_linked_sockets
Vector< bNodeSocket * > logically_linked_sockets
std::optional< FieldSocketState > field_state
Vector< bNodeLink * > directly_linked_links
const nodes::SocketDeclaration * declaration
std::unique_ptr< LoggedZoneGraphs > logged_zone_graphs
std::unique_ptr< anonymous_attribute_inferencing::AnonymousAttributeInferencingResult > anonymous_attribute_inferencing
void(* stats_draw)(void *, const char *str)
Vector< bNodeSocket * > output_sockets
Vector< bNodeSocket * > sockets
std::unique_ptr< nodes::gizmos::TreeGizmoPropagation > gizmo_propagation
Set< const bNodeSocket * > sockets_on_active_gizmo_paths
std::mutex geometry_nodes_lazy_function_graph_info_mutex
std::unique_ptr< nodes::GeometryNodesLazyFunctionGraphInfo > geometry_nodes_lazy_function_graph_info
std::atomic< bool > topology_cache_exists
MultiValueMap< const bNodeType *, bNode * > nodes_by_type
std::unique_ptr< bNodeTreeZones > tree_zones
void(* progress)(void *, float progress)
std::unique_ptr< nodes::FieldInferencingInterface > field_inferencing_interface
MultiValueMap< int, NodeLinkError > link_errors_by_target_node
std::atomic< int > allow_use_dirty_topology_cache
Vector< bNodeSocket * > input_sockets
local_group_size(16, 16) .push_constant(Type b
OperationNode * node
KDTree_3d * tree
#define str(s)
bool topology_cache_is_available(const bNodeTree &tree)
void preprocess_geometry_node_tree_for_evaluation(bNodeTree &tree_cow)
bNodeType * node_type_find(const char *idname)
Definition node.cc:1667
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
bNodeSocketRuntimeHandle * runtime
void * default_value
bNodeTreeInterfaceRuntimeHandle * runtime
bNodeTreeRuntimeHandle * runtime
int nested_node_refs_num
bNestedNodeRef * nested_node_refs
bNodeTreeInterface tree_interface
int num_panel_states
char name[64]
bNodePanelState * panel_states_array
bNodeRuntimeHandle * runtime
char label[64]
bool operator()(const int32_t a, const bNode *b) const
bool operator()(const bNode *a, const int32_t b) const
bool operator()(const bNode *a, const bNode *b) const
uint64_t operator()(const int32_t id) const
uint64_t operator()(const bNode *node) const
Map< int, std::string > graph_by_zone_id