58 node->runtime->changed_flag |= flag;
64 socket->
runtime->changed_flag |= flag;
69 namespace node_field_inferencing {
87 if (
node.is_reroute_node()) {
90 if (
node.is_group_output_node()) {
94 if (
node.is_undefined()) {
126 if (
node.is_reroute_node()) {
130 if (
node.is_group_input_node()) {
134 if (
node.is_undefined()) {
161 node.outputs().size());
162 return inferencing_interface;
173 if (
node.is_group_node()) {
175 if (group ==
nullptr) {
182 if (!group->
runtime->field_inferencing_interface) {
186 return *group->
runtime->field_inferencing_interface;
195 inferencing_interface.
outputs.append(
198 return inferencing_interface;
207 bool is_field_source =
false;
209 bool is_always_single =
false;
211 bool is_single =
true;
215 bool requires_single =
false;
241 return input_sockets;
261 handled_sockets.
add(&group_output_socket);
262 sockets_to_check.
push(&group_output_socket);
267 while (!sockets_to_check.
is_empty()) {
271 !field_state_by_socket_id[input_socket->
id()].is_single) {
277 const NodeRef &origin_node = origin_socket->node();
278 const SocketFieldState &origin_state = field_state_by_socket_id[origin_socket->id()];
294 inferencing_interface.
outputs[origin_socket->index()];
299 if (!origin_input_socket->is_available()) {
302 if (!field_state_by_socket_id[origin_input_socket->id()].is_single) {
303 if (handled_sockets.
add(origin_input_socket)) {
304 sockets_to_check.
push(origin_input_socket);
328 inferencing_interface.
outputs[output_socket->index()];
334 state.requires_single =
true;
335 state.is_always_single =
true;
342 if (target_socket->is_available()) {
343 state.requires_single |= field_state_by_socket_id[target_socket->id()].requires_single;
347 if (
state.requires_single) {
348 bool any_input_is_field_implicitly =
false;
350 field_dependency, *
node);
352 if (!input_socket->is_available()) {
355 if (inferencing_interface.
inputs[input_socket->index()] ==
357 if (!input_socket->is_logically_linked()) {
358 any_input_is_field_implicitly =
true;
363 if (any_input_is_field_implicitly) {
365 state.requires_single =
false;
371 field_state_by_socket_id[input_socket->id()].requires_single =
true;
381 state.requires_single =
true;
382 state.is_always_single =
true;
407 if (
state.requires_single) {
416 const bool supports_field = new_inferencing_interface.
inputs[output_socket->index()] !=
418 if (supports_field) {
419 state.is_single =
false;
420 state.is_field_source =
true;
423 state.requires_single =
true;
438 if (
node->is_group_input_node()) {
448 if (
state.is_always_single) {
449 state.is_single =
true;
452 state.is_single =
true;
453 if (input_socket->directly_linked_sockets().is_empty()) {
454 if (inferencing_interface.
inputs[input_socket->index()] ==
456 state.is_single =
false;
461 if (!field_state_by_socket_id[origin_socket->id()].is_single) {
462 state.is_single =
false;
473 inferencing_interface.
outputs[output_socket->index()];
477 state.is_single =
true;
481 state.is_single =
false;
482 state.is_field_source =
true;
489 if (!input_socket->is_available()) {
492 if (!field_state_by_socket_id[input_socket->id()].is_single) {
493 state.is_single =
false;
508 for (
const NodeRef *group_output_node :
tree.nodes_by_type(
"NodeGroupOutput")) {
514 for (
const InputSocketRef *group_output_socket : group_output_node->inputs().drop_back(1)) {
516 *group_output_socket, field_state_by_socket_id);
517 new_inferencing_interface.
outputs[group_output_socket->index()] = std::move(
532 if (
state.is_always_single) {
533 return requires_data_shape;
535 if (!
state.is_single) {
536 return is_field_shape;
538 if (
state.requires_single) {
539 return requires_data_shape;
541 return data_but_can_be_field_shape;
561 std::unique_ptr<FieldInferencingInterface> new_inferencing_interface =
562 std::make_unique<FieldInferencingInterface>();
578 const bool group_interface_changed = !btree.
runtime->field_inferencing_interface ||
579 *btree.
runtime->field_inferencing_interface !=
580 *new_inferencing_interface;
581 btree.
runtime->field_inferencing_interface = std::move(new_inferencing_interface);
583 return group_interface_changed;
598 switch (
from->type) {
610 switch (
from->type) {
622 switch (
from->type) {
636 switch (
from->type) {
650 switch (
from->type) {
685 std::optional<Vector<bNodeTree *>> all_trees_;
686 std::optional<Map<bNodeTree *, ID *>> owner_ids_;
687 std::optional<MultiValueMap<bNodeTree *, TreeNodePair>> group_node_users_;
688 std::optional<MultiValueMap<bNodeTree *, ObjectModifierPair>> modifiers_users_;
697 if (all_trees_.has_value()) {
700 all_trees_.emplace();
701 owner_ids_.emplace();
702 if (bmain_ ==
nullptr) {
707 all_trees_->append(
ntree);
709 owner_ids_->add_new(
ntree,
id);
717 this->ensure_all_trees();
722 if (group_node_users_.has_value()) {
725 group_node_users_.emplace();
726 if (bmain_ ==
nullptr) {
730 this->ensure_all_trees();
734 if (
node->id ==
nullptr) {
740 group_node_users_->add(group, {
ntree,
node});
748 if (modifiers_users_.has_value()) {
751 modifiers_users_.emplace();
752 if (bmain_ ==
nullptr) {
761 modifiers_users_->add(nmd->
node_group, {
object, md});
771 return modifiers_users_->lookup(
ntree);
777 return group_node_users_->lookup(
ntree);
788 bool interface_changed =
false;
789 bool output_changed =
false;
801 : bmain_(bmain), params_(
params), relations_(bmain)
814 this->update_rooted(changed_ntrees);
823 bool is_single_tree_update =
false;
825 if (root_ntrees.
size() == 1) {
832 if (!
result.interface_changed && !
result.output_changed) {
833 is_single_tree_update =
true;
837 if (!is_single_tree_update) {
849 if (
result.output_changed) {
854 if (
result.interface_changed) {
862 for (
const auto item : update_result_by_tree_.
items()) {
866 this->reset_changed_flags(*
ntree);
868 if (
result.interface_changed) {
872 Object *
object = pair.first;
896 enum class ToposortMark {
916 ToposortMarkMap marks;
918 marks.add_new(
ntree, ToposortMark::None);
921 if (marks.lookup(
ntree) == ToposortMark::None) {
922 const bool cycle_detected = !this->get_tree_update_order__visit_recursive(
923 ntree, marks, sorted_ntrees);
930 std::reverse(sorted_ntrees.
begin(), sorted_ntrees.
end());
932 return sorted_ntrees;
936 ToposortMarkMap &marks,
937 Vector<bNodeTree *> &sorted_ntrees)
939 ToposortMark &mark = marks.lookup(
ntree);
940 if (mark == ToposortMark::Permanent) {
943 if (mark == ToposortMark::Temporary) {
948 mark = ToposortMark::Temporary;
951 this->get_tree_update_order__visit_recursive(pair.first, marks, sorted_ntrees);
953 sorted_ntrees.append(
ntree);
955 mark = ToposortMark::Permanent;
959 Set<bNodeTree *> get_trees_to_update(Span<bNodeTree *> root_ntrees)
963 Set<bNodeTree *> reachable_trees;
964 VectorSet<bNodeTree *> trees_to_check = root_ntrees;
966 while (!trees_to_check.is_empty()) {
968 if (reachable_trees.add(
ntree)) {
970 trees_to_check.add(pair.first);
975 return reachable_trees;
985 std::unique_ptr<NodeTreeRef> tree_ref;
986 this->ensure_tree_ref(
ntree, tree_ref);
988 this->update_socket_link_and_use(*tree_ref);
989 this->update_individual_nodes(
ntree, tree_ref);
990 this->update_internal_links(
ntree, tree_ref);
991 this->update_generic_callback(
ntree, tree_ref);
992 this->remove_unused_previews_when_necessary(
ntree);
994 this->ensure_tree_ref(
ntree, tree_ref);
995 this->propagate_runtime_flags(*tree_ref);
998 result.interface_changed =
true;
1002 result.output_changed = this->check_if_output_changed(*tree_ref);
1004 this->update_socket_link_and_use(*tree_ref);
1005 this->update_node_levels(
ntree);
1006 this->update_link_validation(
ntree);
1014 result.interface_changed =
true;
1017 if (
result.interface_changed) {
1024 void ensure_tree_ref(
bNodeTree &
ntree, std::unique_ptr<NodeTreeRef> &tree_ref)
1027 tree_ref = std::make_unique<NodeTreeRef>(&
ntree);
1035 if (socket->directly_linked_links().is_empty()) {
1036 bsocket->
link =
nullptr;
1039 bsocket->
link = socket->directly_linked_links()[0]->blink();
1043 this->update_socket_used_tags(
tree);
1051 for (
const LinkRef *link : socket->directly_linked_links()) {
1052 if (!link->is_muted()) {
1060 void update_individual_nodes(
bNodeTree &
ntree, std::unique_ptr<NodeTreeRef> &tree_ref)
1065 this->ensure_tree_ref(
ntree, tree_ref);
1066 const NodeRef &
node = *tree_ref->find_node(*bnode);
1067 if (this->should_update_individual_node(
node)) {
1072 this->update_individual_node(
node);
1084 bool should_update_individual_node(
const NodeRef &
node)
1097 if (
node.is_group_input_node()) {
1098 if (
node.outputs().last()->is_directly_linked()) {
1102 else if (
node.is_group_output_node()) {
1103 if (
node.inputs().last()->is_directly_linked()) {
1113 if (
node.is_group_input_node() ||
node.is_group_output_node()) {
1133 void update_internal_links(
bNodeTree &
ntree, std::unique_ptr<NodeTreeRef> &tree_ref)
1135 bool any_internal_links_updated =
false;
1136 this->ensure_tree_ref(
ntree, tree_ref);
1138 if (!this->should_update_individual_node(*
node)) {
1142 Vector<std::pair<bNodeSocket *, bNodeSocket *>> expected_internal_links;
1144 if (!output_socket->is_available()) {
1147 if (!output_socket->is_directly_linked()) {
1153 const InputSocketRef *input_socket = this->find_internally_linked_input(output_socket);
1154 if (input_socket !=
nullptr) {
1155 expected_internal_links.append({input_socket->
bsocket(), output_socket->bsocket()});
1159 if (
node->internal_links().size() != expected_internal_links.size()) {
1160 this->update_internal_links_in_node(
ntree, *
node->bnode(), expected_internal_links);
1161 any_internal_links_updated =
true;
1164 for (
auto &item : expected_internal_links) {
1169 if (from_socket == internal_link->from().bsocket() &&
1170 to_socket == internal_link->to().bsocket()) {
1175 this->update_internal_links_in_node(
ntree, *
node->bnode(), expected_internal_links);
1176 any_internal_links_updated =
true;
1183 if (any_internal_links_updated) {
1191 int selected_priority = -1;
1192 bool selected_is_linked =
false;
1206 const bool is_preferred = priority > selected_priority || (is_linked && !selected_is_linked);
1207 if (!is_preferred) {
1210 selected_socket = input_socket;
1211 selected_priority = priority;
1212 selected_is_linked = is_linked;
1214 return selected_socket;
1219 Span<std::pair<bNodeSocket *, bNodeSocket *>> links)
1222 for (
const auto &item : links) {
1225 bNodeLink *link = MEM_cnew<bNodeLink>(__func__);
1229 link->
tosock = to_socket;
1236 void update_generic_callback(
bNodeTree &
ntree, std::unique_ptr<NodeTreeRef> &tree_ref)
1267 void propagate_runtime_flags(
const NodeTreeRef &tree_ref)
1278 if (group !=
nullptr) {
1283 for (
const StringRefNull idname : {
"ShaderNodeTexImage",
"ShaderNodeTexEnvironment"}) {
1293 for (
const StringRefNull idname : {
"ShaderNodeOutputMaterial",
1294 "ShaderNodeOutputLight",
1295 "ShaderNodeOutputWorld",
1296 "ShaderNodeOutputAOV"}) {
1297 const Span<const NodeRef *> nodes = tree_ref.
nodes_by_type(idname);
1298 if (!nodes.is_empty()) {
1314 if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level) {
1319 link->fromsock->type);
1335 const Vector<const SocketRef *> tree_output_sockets = this->find_output_sockets(
tree);
1336 const uint32_t old_topology_hash = btree.
runtime->output_topology_hash;
1337 const uint32_t new_topology_hash = this->get_combined_socket_topology_hash(
1338 tree, tree_output_sockets);
1339 btree.
runtime->output_topology_hash = new_topology_hash;
1351 const StringRef expression = driver->
expression;
1352 if (expression.startswith(
"frame")) {
1353 const StringRef remaining_expression = expression.drop_known_prefix(
"frame");
1367 if (old_topology_hash != new_topology_hash) {
1372 if (btree.
runtime->changed_flag ==
1374 if (old_topology_hash == new_topology_hash) {
1379 if (!this->check_if_socket_outputs_changed_based_on_flags(
tree, tree_output_sockets)) {
1386 Vector<const SocketRef *> find_output_sockets(
const NodeTreeRef &
tree)
1388 Vector<const SocketRef *> sockets;
1390 if (!this->is_output_node(*
node)) {
1394 if (socket->idname() !=
"NodeSocketVirtual") {
1395 sockets.append(socket);
1414 if (node_group !=
nullptr &&
1427 Span<const SocketRef *> sockets)
1429 if (
tree.has_link_cycles()) {
1434 Array<uint32_t> hashes = this->get_socket_topology_hashes(
tree, sockets);
1439 return combined_hash;
1443 Span<const SocketRef *> sockets)
1446 Array<std::optional<uint32_t>> hash_by_socket_id(
tree.sockets().size());
1447 Stack<const SocketRef *> sockets_to_check = sockets;
1449 while (!sockets_to_check.is_empty()) {
1450 const SocketRef &in_out_socket = *sockets_to_check.peek();
1453 if (hash_by_socket_id[in_out_socket.
id()].has_value()) {
1454 sockets_to_check.pop();
1462 bool all_origins_computed =
true;
1464 if (!hash_by_socket_id[origin_socket->id()].has_value()) {
1465 sockets_to_check.push(origin_socket);
1466 all_origins_computed =
false;
1469 if (!all_origins_computed) {
1477 const uint32_t origin_socket_hash = *hash_by_socket_id[origin_socket->id()];
1478 socket_hash =
noise::hash(socket_hash, origin_socket_hash);
1480 hash_by_socket_id[socket.
id()] = socket_hash;
1481 sockets_to_check.pop();
1486 bool all_available_inputs_computed =
true;
1489 if (!hash_by_socket_id[input_socket->
id()].has_value()) {
1490 sockets_to_check.push(input_socket);
1491 all_available_inputs_computed =
false;
1495 if (!all_available_inputs_computed) {
1504 const uint32_t input_socket_hash = *hash_by_socket_id[input_socket->
id()];
1505 socket_hash =
noise::hash(socket_hash, input_socket_hash);
1518 hash_by_socket_id[socket.
id()] = socket_hash;
1519 sockets_to_check.pop();
1524 Array<uint32_t> hashes(sockets.size());
1525 for (
const int i : sockets.index_range()) {
1526 hashes[i] = *hash_by_socket_id[sockets[i]->id()];
1535 bool check_if_socket_outputs_changed_based_on_flags(
const NodeTreeRef &
tree,
1536 Span<const SocketRef *> sockets)
1539 Array<bool> pushed_by_socket_id(
tree.sockets().size(),
false);
1540 Stack<const SocketRef *> sockets_to_check = sockets;
1542 for (
const SocketRef *socket : sockets) {
1543 pushed_by_socket_id[socket->
id()] =
true;
1546 while (!sockets_to_check.is_empty()) {
1547 const SocketRef &in_out_socket = *sockets_to_check.pop();
1555 const bool only_unused_internal_link_changed = (bnode.
flag &
NODE_MUTED) == 0 &&
1556 bnode.
runtime->changed_flag ==
1558 if (!only_unused_internal_link_changed) {
1565 bool &pushed = pushed_by_socket_id[origin_socket->id()];
1567 sockets_to_check.push(origin_socket);
1576 bool &pushed = pushed_by_socket_id[input_socket->
id()];
1578 sockets_to_check.push(input_socket);
1589 bool &pushed = pushed_by_socket_id[normal_output.
id()];
1591 sockets_to_check.push(&normal_output);
1712 if (
node->id ==
id) {
1750 if (
ntree ==
nullptr) {
1761 updater.update_rooted({
ntree});
struct AnimData * BKE_animdata_from_id(const struct ID *id)
bool BKE_image_is_animated(struct Image *image)
#define NODE_CLASS_OUTPUT
void BKE_node_preview_remove_unused(struct bNodeTree *ntree)
void ntreeUpdateNodeLevels(struct bNodeTree *ntree)
void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree)
#define FOREACH_NODETREE_END
bool ntreeIsRegistered(struct bNodeTree *ntree)
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define UNUSED_VARS_NDEBUG(...)
@ NTREE_RUNTIME_FLAG_HAS_MATERIAL_OUTPUT
@ NTREE_RUNTIME_FLAG_HAS_IMAGE_ANIMATION
@ SOCK_DISPLAY_SHAPE_CIRCLE
@ SOCK_DISPLAY_SHAPE_DIAMOND
@ SOCK_DISPLAY_SHAPE_DIAMOND_DOT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value SH_NODE_NORMAL
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 Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block SH_NODE_TEX_IMAGE
void ntreeTexCheckCyclics(struct bNodeTree *ntree)
const Value & lookup(const Key &key) const
void add_new(const Key &key, const Value &value)
ItemIterator items() const
bool contains(const Key &key) const
constexpr int64_t size() const
constexpr bool is_empty() const
void push(const T &value)
static constexpr int64_t not_found
void append(const T &value)
void extend(Span< T > array)
void append_non_duplicates(const T &value)
void append_n_times(const T &value, const int64_t n)
void update_rooted(Span< bNodeTree * > root_ntrees)
NodeTreeMainUpdater(Main *bmain, NodeTreeUpdateExtraParams *params)
Span< SocketDeclarationPtr > outputs() const
Span< SocketDeclarationPtr > inputs() const
bool is_function_node() const
Span< const InputSocketRef * > inputs() const
bool is_group_input_node() const
bNodeTree * btree() const
Span< const NodeRef * > nodes_by_type(StringRefNull idname) const
static OutputFieldDependency ForPartiallyDependentField(Vector< int > indices)
static OutputFieldDependency ForDataSource()
static OutputFieldDependency ForDependentField()
Span< int > linked_input_indices() const
static OutputFieldDependency ForFieldSource()
OutputSocketFieldType field_type() const
Span< const InputSocketRef * > directly_linked_sockets() const
const OutputFieldDependency & output_field_dependency() const
InputSocketFieldType input_field_type() const
const NodeRef & node() const
bool is_directly_linked() const
const OutputSocketRef & as_output() const
bNodeSocketType * typeinfo() const
bNodeSocket * bsocket() const
bool is_available() const
const InputSocketRef & as_input() const
StringRefNull name() const
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
static void determine_group_input_states(const NodeTreeRef &tree, FieldInferencingInterface &new_inferencing_interface, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static Vector< const InputSocketRef * > gather_input_socket_dependencies(const OutputFieldDependency &field_dependency, const NodeRef &node)
static OutputFieldDependency get_interface_output_field_dependency(const NodeRef &node, const OutputSocketRef &socket)
static void update_socket_shapes(const NodeTreeRef &tree, const Span< SocketFieldState > field_state_by_socket_id)
static bool update_field_inferencing(const NodeTreeRef &tree)
static void determine_group_output_states(const NodeTreeRef &tree, FieldInferencingInterface &new_inferencing_interface, const Span< SocketFieldState > field_state_by_socket_id)
static bool is_field_socket_type(const SocketRef &socket)
static FieldInferencingInterface get_node_field_inferencing_interface(const NodeRef &node)
static void propagate_data_requirements_from_right_to_left(const NodeTreeRef &tree, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static void propagate_field_status_from_left_to_right(const NodeTreeRef &tree, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static InputSocketFieldType get_interface_input_field_type(const NodeRef &node, const InputSocketRef &socket)
static FieldInferencingInterface get_dummy_field_inferencing_interface(const NodeRef &node)
static OutputFieldDependency find_group_output_dependencies(const InputSocketRef &group_output_socket, const Span< SocketFieldState > field_state_by_socket_id)
std::pair< Object *, ModifierData * > ObjectModifierPair
std::pair< bNode *, bNodeSocket * > NodeSocketPair
static int get_internal_link_type_priority(const bNodeSocketType *from, const bNodeSocketType *to)
std::pair< bNodeTree *, bNode * > TreeNodePair
static Type to_type(const eGPUType type)
uint32_t hash(uint32_t kx)
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_link_mute(bNodeTree *ntree, bNodeLink *UNUSED(link))
void BKE_ntree_update_tag_node_mute(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_all(bNodeTree *ntree)
void BKE_ntree_update_tag_interface(bNodeTree *ntree)
void BKE_ntree_update_tag_link_changed(bNodeTree *ntree)
void BKE_ntree_update_tag_socket_new(bNodeTree *ntree, bNodeSocket *socket)
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)
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_image_user_changed(bNodeTree *ntree, ImageUser *UNUSED(iuser))
void BKE_ntree_update_tag_node_removed(bNodeTree *ntree)
void BKE_ntree_update_tag_id_changed(Main *bmain, ID *id)
@ NTREE_CHANGED_REMOVED_SOCKET
@ NTREE_CHANGED_INTERFACE
@ NTREE_CHANGED_NODE_OUTPUT
@ NTREE_CHANGED_NODE_PROPERTY
@ NTREE_CHANGED_SOCKET_PROPERTY
@ NTREE_CHANGED_REMOVED_NODE
@ NTREE_CHANGED_INTERNAL_LINK
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
void BKE_ntree_update_tag_link_added(bNodeTree *ntree, bNodeLink *UNUSED(link))
_W64 unsigned int uintptr_t
unsigned __int64 uint64_t
struct bNodeTree * node_group
bNodeSocketRuntimeHandle * runtime
struct bNodeSocketType * typeinfo
bool(* validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to)
void(* update)(struct bNodeTree *ntree)
bNodeTreeRuntimeHandle * runtime
struct bNodeTreeType * typeinfo
void(* group_update_func)(struct bNodeTree *ntree, struct bNode *node)
void(* updatefunc)(struct bNodeTree *ntree, struct bNode *node)
struct bNodeType * typeinfo
bNodeRuntimeHandle * runtime
NodeTreeRelations(Main *bmain)
void ensure_group_node_users()
Span< ObjectModifierPair > get_modifier_users(bNodeTree *ntree)
ID * get_owner_id(bNodeTree *ntree)
Span< TreeNodePair > get_group_node_users(bNodeTree *ntree)
void ensure_modifier_users()
Vector< OutputFieldDependency > outputs
Vector< InputSocketFieldType > inputs
Vector< const NodeRef * > sorted_nodes