1
1

Compare commits

...

20 Commits

Author SHA1 Message Date
83276fa0ee fixes 2021-11-15 19:08:22 +01:00
00a0d3315a progress 2021-11-15 18:35:06 +01:00
861f65040b progress 2021-11-15 18:24:56 +01:00
677dc13e12 Merge branch 'master' into node-tree-update-refactor 2021-11-15 18:07:04 +01:00
339839d58d progress 2021-11-15 18:01:00 +01:00
cb5569f849 progress 2021-11-15 17:23:22 +01:00
d77d9e8f6e progres 2021-11-15 16:47:12 +01:00
57ecab5509 progress 2021-11-15 13:59:07 +01:00
5c70f5a7f7 progress 2021-11-15 13:32:44 +01:00
a9ac8b44d5 Merge branch 'master' into node-tree-update-refactor 2021-11-15 13:21:15 +01:00
36bf158e5c progress 2021-11-11 15:03:51 +01:00
262efaf860 cleanup 2021-11-11 13:47:21 +01:00
2fa85494fc progress 2021-11-11 13:32:33 +01:00
c608858dd2 cleanup 2021-11-11 12:51:48 +01:00
d57ec78e6e progress 2021-11-11 12:51:20 +01:00
1d614fcfb1 progress 2021-11-11 12:09:37 +01:00
af5a4034b9 unify update a bit 2021-11-11 12:05:47 +01:00
053909a824 progress 2021-11-10 18:53:23 +01:00
c853595d3a initial tree update api 2021-11-10 18:22:35 +01:00
c02fa53f54 progress 2021-11-10 17:49:32 +01:00
34 changed files with 1463 additions and 926 deletions

View File

@@ -482,13 +482,13 @@ void ntreeFreeLocalTree(struct bNodeTree *ntree);
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree);
void ntreeUpdateAllNew(struct Main *main);
void ntreeUpdateAllUsers(struct Main *main, struct ID *id, int tree_update_flag);
void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
void ntreeGetDependencyList(struct bNodeTree *ntree,
struct bNode ***r_deplist,
int *r_deplist_len);
void ntreeUpdateNodeLevels(struct bNodeTree *ntree);
/* XXX old trees handle output flags automatically based on special output
* node types and last active selection.

View File

@@ -0,0 +1,98 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bke
*/
struct bNode;
struct bNodeSocket;
struct bNodeTree;
struct bNodeLink;
struct Main;
struct ID;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Tag tree as changed without providing any more information about what has changed exactly.
* The update process has to assume that everything may have changed.
*/
void BKE_node_tree_update_tag(struct bNodeTree *ntree);
/**
* More specialized tag functions that may result in a more efficient update.
*/
void BKE_node_tree_update_tag_node(struct bNodeTree *ntree, struct bNode *node);
void BKE_node_tree_update_tag_socket(struct bNodeTree *ntree, struct bNodeSocket *socket);
void BKE_node_tree_update_tag_link(struct bNodeTree *ntree);
void BKE_node_tree_update_tag_node_removed(struct bNodeTree *ntree);
void BKE_node_tree_update_tag_node_added(struct bNodeTree *ntree, struct bNode *node);
void BKE_node_tree_update_tag_link_removed(struct bNodeTree *ntree);
void BKE_node_tree_update_tag_link_added(struct bNodeTree *ntree, struct bNodeLink *link);
void BKE_node_tree_update_tag_link_mute(struct bNodeTree *ntree, struct bNodeLink *link);
void BKE_node_tree_update_tag_missing_runtime_data(struct bNodeTree *ntree);
void BKE_node_tree_update_tag_interface(struct bNodeTree *ntree);
typedef struct NodeTreeUpdateExtraParams {
/**
* Data passed into the callbacks.
*/
void *user_data;
/**
* Called for every tree that has been changed during the update. This can be used to send
* notifiers to trigger redraws or depsgraph updates.
*/
void (*tree_changed_fn)(struct ID *, struct bNodeTree *, void *user_data);
/**
* Called for every tree whose interface (e.g. input sockets) changed in some way.
*/
void (*tree_interface_changed_fn)(struct ID *, struct bNodeTree *, void *user_data);
/**
* Called for every tree whose output value may have changed based on the provided update tags.
* This can be used to tag the depsgraph if necessary.
*/
void (*tree_output_changed_fn)(struct ID *, struct bNodeTree *, void *user_data);
} NodeTreeUpdateExtraParams;
/**
* Updates #bmain based on changes to node trees.
*/
void BKE_node_tree_update_main(struct Main *bmain, struct NodeTreeUpdateExtraParams *params);
/**
* Same as #BKE_node_tree_update_main, but will first only look at the provided tree and only looks
* at #bmain when something relevant for other data-blocks changed.
*
* If #bmain is null, only the provided tree is updated. This should only be used in very rare
* cases because it may result it incorrectly synced data in DNA.
*
* If #tree is null, this will update everything.
*/
void BKE_node_tree_update_main_rooted(struct Main *bmain,
struct bNodeTree *ntree,
struct NodeTreeUpdateExtraParams *params);
#ifdef __cplusplus
}
#endif

View File

@@ -226,6 +226,7 @@ set(SRC
intern/multires_versioning.c
intern/nla.c
intern/node.cc
intern/node_tree_update.cc
intern/object.cc
intern/object_deform.c
intern/object_dupli.cc
@@ -418,6 +419,7 @@ set(SRC
BKE_multires.h
BKE_nla.h
BKE_node.h
BKE_node_tree_update.h
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h

View File

@@ -346,7 +346,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o
static void libblock_remap_data_postprocess_nodetree_update(Main *bmain, ID *new_id)
{
/* Update all group nodes using a node group. */
ntreeUpdateAllUsers(bmain, new_id, 0);
ntreeUpdateAllUsers(bmain, new_id);
}
/**

View File

@@ -50,6 +50,7 @@
#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_texture.h"
#include "BLO_read_write.h"
@@ -2087,5 +2088,5 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty
tosock = BLI_findlink(&output_linestyle->inputs, 0); /* Color */
nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock);
ntreeUpdateTree(CTX_data_main(C), ntree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), ntree, NULL);
}

View File

@@ -73,6 +73,7 @@
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
@@ -99,6 +100,7 @@
#define NODE_DEFAULT_MAX_WIDTH 700
using blender::Array;
using blender::Map;
using blender::MutableSpan;
using blender::Set;
using blender::Span;
@@ -695,6 +697,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
ntree->execdata = nullptr;
ntree->field_inferencing_interface = nullptr;
BKE_node_tree_update_tag_missing_runtime_data(ntree);
BLO_read_data_address(reader, &ntree->adt);
BKE_animdata_blend_read_data(reader, ntree->adt);
@@ -838,11 +841,6 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
/* TODO: should be dealt by new generic cache handling of IDs... */
ntree->previews = nullptr;
if (ntree->type == NTREE_GEOMETRY) {
/* Update field referencing for the geometry nodes modifier. */
ntree->update |= NTREE_UPDATE_FIELD_INFERENCING;
}
BLO_read_data_address(reader, &ntree->preview);
BKE_previewimg_blend_read(reader, ntree->preview);
@@ -1217,6 +1215,7 @@ static void node_socket_set_typeinfo(bNodeTree *ntree,
ntree->init &= ~NTREE_TYPE_INIT;
}
BKE_node_tree_update_tag_socket(ntree, sock);
}
/* Set specific typeinfo pointers in all node trees on register/unregister */
@@ -1707,7 +1706,7 @@ bNodeSocket *nodeAddSocket(bNodeTree *ntree,
BLI_remlink(lb, sock); /* does nothing for new socket */
BLI_addtail(lb, sock);
node->update |= NODE_UPDATE;
BKE_node_tree_update_tag_socket(ntree, sock);
return sock;
}
@@ -2160,7 +2159,7 @@ static void iter_backwards_ex(const bNodeTree *ntree,
* Can be called recursively (using another nodeChainIterBackwards) by
* setting the recursion_lvl accordingly.
*
* \note Needs updated socket links (ntreeUpdateTree).
* \note Needs updated socket links (BKE_node_tree_update_main).
* \note Recursive
*/
void nodeChainIterBackwards(const bNodeTree *ntree,
@@ -2218,7 +2217,7 @@ bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idnam
BLI_strncpy(node->idname, idname, sizeof(node->idname));
node_set_typeinfo(C, ntree, node, nodeTypeFind(idname));
ntree->update |= NTREE_UPDATE_NODES;
BKE_node_tree_update_tag_node(ntree, node);
return node;
}
@@ -2347,7 +2346,7 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
}
if (ntree) {
ntree->update |= NTREE_UPDATE_NODES;
BKE_node_tree_update_tag_node(ntree, node_dst);
}
/* Reset the declaration of the new node. */
@@ -2445,7 +2444,7 @@ bNodeLink *nodeAddLink(
}
if (ntree) {
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link_added(ntree, link);
}
if (link != nullptr && link->tosock->flag & SOCK_MULTI_INPUT) {
@@ -2468,7 +2467,7 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
MEM_freeN(link);
if (ntree) {
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link_removed(ntree);
}
}
@@ -2568,7 +2567,7 @@ void nodeMuteLinkToggle(bNodeTree *ntree, bNodeLink *link)
}
if (ntree) {
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link_mute(ntree, link);
}
}
@@ -2579,8 +2578,6 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
nodeRemLink(ntree, link);
}
}
ntree->update |= NTREE_UPDATE_LINKS;
}
bool nodeLinkIsHidden(const bNodeLink *link)
@@ -2645,7 +2642,7 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
link->flag |= NODE_LINK_MUTED;
}
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link(ntree);
}
else {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
@@ -3189,7 +3186,7 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
MEM_freeN(node);
if (ntree) {
ntree->update |= NTREE_UPDATE_NODES;
BKE_node_tree_update_tag_node_removed(ntree);
}
}
@@ -3576,12 +3573,11 @@ bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
if (in_out == SOCK_IN) {
BLI_addtail(&ntree->inputs, iosock);
ntree->update |= NTREE_UPDATE_GROUP_IN;
}
else if (in_out == SOCK_OUT) {
BLI_addtail(&ntree->outputs, iosock);
ntree->update |= NTREE_UPDATE_GROUP_OUT;
}
BKE_node_tree_update_tag_interface(ntree);
return iosock;
}
@@ -3594,12 +3590,11 @@ bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
if (in_out == SOCK_IN) {
BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
ntree->update |= NTREE_UPDATE_GROUP_IN;
}
else if (in_out == SOCK_OUT) {
BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
ntree->update |= NTREE_UPDATE_GROUP_OUT;
}
BKE_node_tree_update_tag_interface(ntree);
return iosock;
}
@@ -3645,7 +3640,7 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
node_socket_interface_free(ntree, sock, true);
MEM_freeN(sock);
ntree->update |= NTREE_UPDATE_GROUP;
BKE_node_tree_update_tag_interface(ntree);
}
/* generates a valid RNA identifier from the node tree name */
@@ -4459,7 +4454,7 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist,
}
/* only updates node->level for detecting cycles links */
static void ntree_update_node_level(bNodeTree *ntree)
void ntreeUpdateNodeLevels(bNodeTree *ntree)
{
/* first clear tag */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -4494,598 +4489,49 @@ void ntreeTagUsedSockets(bNodeTree *ntree)
}
}
static void ntree_update_link_pointers(bNodeTree *ntree)
{
/* first clear data */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
sock->link = nullptr;
}
}
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
link->tosock->link = link;
}
ntreeTagUsedSockets(ntree);
}
static void ntree_validate_links(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
link->flag |= NODE_LINK_VALID;
if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level) {
link->flag &= ~NODE_LINK_VALID;
}
else if (ntree->typeinfo->validate_link) {
if (!ntree->typeinfo->validate_link(ntree, link)) {
link->flag &= ~NODE_LINK_VALID;
}
}
}
}
void ntreeUpdateAllNew(Main *main)
{
Vector<bNodeTree *> new_ntrees;
/* Update all new node trees on file read or append, to add/remove sockets
* in groups nodes if the group changed, and handle any update flags that
* might have been set in file reading or versioning. */
FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
if (owner_id->tag & LIB_TAG_NEW) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
/* TODO: Move to update function. */
if (node->typeinfo->group_update_func) {
node->typeinfo->group_update_func(ntree, node);
}
}
ntreeUpdateTree(nullptr, ntree);
BKE_node_tree_update_tag(ntree);
}
}
FOREACH_NODETREE_END;
BKE_node_tree_update_main(main, nullptr);
}
namespace blender::bke::node_field_inferencing {
static bool is_field_socket_type(eNodeSocketDatatype type)
{
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA);
}
static bool is_field_socket_type(const SocketRef &socket)
{
return is_field_socket_type((eNodeSocketDatatype)socket.typeinfo()->type);
}
static bool update_field_inferencing(bNodeTree &btree);
static InputSocketFieldType get_interface_input_field_type(const NodeRef &node,
const InputSocketRef &socket)
{
if (!is_field_socket_type(socket)) {
return InputSocketFieldType::None;
}
if (node.is_reroute_node()) {
return InputSocketFieldType::IsSupported;
}
if (node.is_group_output_node()) {
/* Outputs always support fields when the data type is correct. */
return InputSocketFieldType::IsSupported;
}
if (node.is_undefined()) {
return InputSocketFieldType::None;
}
const NodeDeclaration *node_decl = node.declaration();
/* Node declarations should be implemented for nodes involved here. */
BLI_assert(node_decl != nullptr);
/* Get the field type from the declaration. */
const SocketDeclaration &socket_decl = *node_decl->inputs()[socket.index()];
const InputSocketFieldType field_type = socket_decl.input_field_type();
if (field_type == InputSocketFieldType::Implicit) {
return field_type;
}
if (node_decl->is_function_node()) {
/* In a function node, every socket supports fields. */
return InputSocketFieldType::IsSupported;
}
return field_type;
}
static OutputFieldDependency get_interface_output_field_dependency(const NodeRef &node,
const OutputSocketRef &socket)
{
if (!is_field_socket_type(socket)) {
/* Non-field sockets always output data. */
return OutputFieldDependency::ForDataSource();
}
if (node.is_reroute_node()) {
/* The reroute just forwards what is passed in. */
return OutputFieldDependency::ForDependentField();
}
if (node.is_group_input_node()) {
/* Input nodes get special treatment in #determine_group_input_states. */
return OutputFieldDependency::ForDependentField();
}
if (node.is_undefined()) {
return OutputFieldDependency::ForDataSource();
}
const NodeDeclaration *node_decl = node.declaration();
/* Node declarations should be implemented for nodes involved here. */
BLI_assert(node_decl != nullptr);
if (node_decl->is_function_node()) {
/* In a generic function node, all outputs depend on all inputs. */
return OutputFieldDependency::ForDependentField();
}
/* Use the socket declaration. */
const SocketDeclaration &socket_decl = *node_decl->outputs()[socket.index()];
return socket_decl.output_field_dependency();
}
static FieldInferencingInterface get_dummy_field_inferencing_interface(const NodeRef &node)
{
FieldInferencingInterface inferencing_interface;
inferencing_interface.inputs.append_n_times(InputSocketFieldType::None, node.inputs().size());
inferencing_interface.outputs.append_n_times(OutputFieldDependency::ForDataSource(),
node.outputs().size());
return inferencing_interface;
}
/**
* Retrieves information about how the node interacts with fields.
* In the future, this information can be stored in the node declaration. This would allow this
* function to return a reference, making it more efficient.
*/
static FieldInferencingInterface get_node_field_inferencing_interface(const NodeRef &node)
{
/* Node groups already reference all required information, so just return that. */
if (node.is_group_node()) {
bNodeTree *group = (bNodeTree *)node.bnode()->id;
if (group == nullptr) {
return FieldInferencingInterface();
}
if (!ntreeIsRegistered(group)) {
/* This can happen when there is a linked node group that was not found (see T92799). */
return get_dummy_field_inferencing_interface(node);
}
if (group->field_inferencing_interface == nullptr) {
/* Update group recursively. */
update_field_inferencing(*group);
}
return *group->field_inferencing_interface;
}
FieldInferencingInterface inferencing_interface;
for (const InputSocketRef *input_socket : node.inputs()) {
inferencing_interface.inputs.append(get_interface_input_field_type(node, *input_socket));
}
for (const OutputSocketRef *output_socket : node.outputs()) {
inferencing_interface.outputs.append(
get_interface_output_field_dependency(node, *output_socket));
}
return inferencing_interface;
}
/**
* This struct contains information for every socket. The values are propagated through the
* network.
*/
struct SocketFieldState {
/* This socket starts a new field. */
bool is_field_source = false;
/* This socket can never become a field, because the node itself does not support it. */
bool is_always_single = false;
/* This socket is currently a single value. It could become a field though. */
bool is_single = true;
/* This socket is required to be a single value. This can be because the node itself only
* supports this socket to be a single value, or because a node afterwards requires this to be a
* single value. */
bool requires_single = false;
};
static Vector<const InputSocketRef *> gather_input_socket_dependencies(
const OutputFieldDependency &field_dependency, const NodeRef &node)
{
const OutputSocketFieldType type = field_dependency.field_type();
Vector<const InputSocketRef *> input_sockets;
switch (type) {
case OutputSocketFieldType::FieldSource:
case OutputSocketFieldType::None: {
break;
}
case OutputSocketFieldType::DependentField: {
/* This output depends on all inputs. */
input_sockets.extend(node.inputs());
break;
}
case OutputSocketFieldType::PartiallyDependent: {
/* This output depends only on a few inputs. */
for (const int i : field_dependency.linked_input_indices()) {
input_sockets.append(&node.input(i));
}
break;
}
}
return input_sockets;
}
/**
* Check what the group output socket depends on. Potentially traverses the node tree
* to figure out if it is always a field or if it depends on any group inputs.
*/
static OutputFieldDependency find_group_output_dependencies(
const InputSocketRef &group_output_socket,
const Span<SocketFieldState> field_state_by_socket_id)
{
if (!is_field_socket_type(group_output_socket)) {
return OutputFieldDependency::ForDataSource();
}
/* Use a Set here instead of an array indexed by socket id, because we my only need to look at
* very few sockets. */
Set<const InputSocketRef *> handled_sockets;
Stack<const InputSocketRef *> sockets_to_check;
handled_sockets.add(&group_output_socket);
sockets_to_check.push(&group_output_socket);
/* Keeps track of group input indices that are (indirectly) connected to the output. */
Vector<int> linked_input_indices;
while (!sockets_to_check.is_empty()) {
const InputSocketRef *input_socket = sockets_to_check.pop();
for (const OutputSocketRef *origin_socket : input_socket->directly_linked_sockets()) {
const NodeRef &origin_node = origin_socket->node();
const SocketFieldState &origin_state = field_state_by_socket_id[origin_socket->id()];
if (origin_state.is_field_source) {
if (origin_node.is_group_input_node()) {
/* Found a group input that the group output depends on. */
linked_input_indices.append_non_duplicates(origin_socket->index());
}
else {
/* Found a field source that is not the group input. So the output is always a field. */
return OutputFieldDependency::ForFieldSource();
}
}
else if (!origin_state.is_single) {
const FieldInferencingInterface inferencing_interface =
get_node_field_inferencing_interface(origin_node);
const OutputFieldDependency &field_dependency =
inferencing_interface.outputs[origin_socket->index()];
/* Propagate search further to the left. */
for (const InputSocketRef *origin_input_socket :
gather_input_socket_dependencies(field_dependency, origin_node)) {
if (!origin_input_socket->is_available()) {
continue;
}
if (!field_state_by_socket_id[origin_input_socket->id()].is_single) {
if (handled_sockets.add(origin_input_socket)) {
sockets_to_check.push(origin_input_socket);
}
}
}
}
}
}
return OutputFieldDependency::ForPartiallyDependentField(std::move(linked_input_indices));
}
static void propagate_data_requirements_from_right_to_left(
const NodeTreeRef &tree, const MutableSpan<SocketFieldState> field_state_by_socket_id)
{
const NodeTreeRef::ToposortResult toposort_result = tree.toposort(
NodeTreeRef::ToposortDirection::RightToLeft);
for (const NodeRef *node : toposort_result.sorted_nodes) {
const FieldInferencingInterface inferencing_interface = get_node_field_inferencing_interface(
*node);
for (const OutputSocketRef *output_socket : node->outputs()) {
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
const OutputFieldDependency &field_dependency =
inferencing_interface.outputs[output_socket->index()];
if (field_dependency.field_type() == OutputSocketFieldType::FieldSource) {
continue;
}
if (field_dependency.field_type() == OutputSocketFieldType::None) {
state.requires_single = true;
state.is_always_single = true;
continue;
}
/* The output is required to be a single value when it is connected to any input that does
* not support fields. */
for (const InputSocketRef *target_socket : output_socket->directly_linked_sockets()) {
state.requires_single |= field_state_by_socket_id[target_socket->id()].requires_single;
}
if (state.requires_single) {
bool any_input_is_field_implicitly = false;
const Vector<const InputSocketRef *> connected_inputs = gather_input_socket_dependencies(
field_dependency, *node);
for (const InputSocketRef *input_socket : connected_inputs) {
if (!input_socket->is_available()) {
continue;
}
if (inferencing_interface.inputs[input_socket->index()] ==
InputSocketFieldType::Implicit) {
if (!input_socket->is_logically_linked()) {
any_input_is_field_implicitly = true;
break;
}
}
}
if (any_input_is_field_implicitly) {
/* This output isn't a single value actually. */
state.requires_single = false;
}
else {
/* If the output is required to be a single value, the connected inputs in the same node
* must not be fields as well. */
for (const InputSocketRef *input_socket : connected_inputs) {
field_state_by_socket_id[input_socket->id()].requires_single = true;
}
}
}
}
/* Some inputs do not require fields independent of what the outputs are connected to. */
for (const InputSocketRef *input_socket : node->inputs()) {
SocketFieldState &state = field_state_by_socket_id[input_socket->id()];
if (inferencing_interface.inputs[input_socket->index()] == InputSocketFieldType::None) {
state.requires_single = true;
state.is_always_single = true;
}
}
}
}
static void determine_group_input_states(
const NodeTreeRef &tree,
FieldInferencingInterface &new_inferencing_interface,
const MutableSpan<SocketFieldState> field_state_by_socket_id)
{
{
/* Non-field inputs never support fields. */
int index;
LISTBASE_FOREACH_INDEX (bNodeSocket *, group_input, &tree.btree()->inputs, index) {
if (!is_field_socket_type((eNodeSocketDatatype)group_input->type)) {
new_inferencing_interface.inputs[index] = InputSocketFieldType::None;
}
}
}
/* Check if group inputs are required to be single values, because they are (indirectly)
* connected to some socket that does not support fields. */
for (const NodeRef *node : tree.nodes_by_type("NodeGroupInput")) {
for (const OutputSocketRef *output_socket : node->outputs().drop_back(1)) {
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
if (state.requires_single) {
new_inferencing_interface.inputs[output_socket->index()] = InputSocketFieldType::None;
}
}
}
/* If an input does not support fields, this should be reflected in all Group Input nodes. */
for (const NodeRef *node : tree.nodes_by_type("NodeGroupInput")) {
for (const OutputSocketRef *output_socket : node->outputs().drop_back(1)) {
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
const bool supports_field = new_inferencing_interface.inputs[output_socket->index()] !=
InputSocketFieldType::None;
if (supports_field) {
state.is_single = false;
state.is_field_source = true;
}
else {
state.requires_single = true;
}
}
SocketFieldState &dummy_socket_state = field_state_by_socket_id[node->outputs().last()->id()];
dummy_socket_state.requires_single = true;
}
}
static void propagate_field_status_from_left_to_right(
const NodeTreeRef &tree, const MutableSpan<SocketFieldState> field_state_by_socket_id)
{
const NodeTreeRef::ToposortResult toposort_result = tree.toposort(
NodeTreeRef::ToposortDirection::LeftToRight);
for (const NodeRef *node : toposort_result.sorted_nodes) {
if (node->is_group_input_node()) {
continue;
}
const FieldInferencingInterface inferencing_interface = get_node_field_inferencing_interface(
*node);
/* Update field state of input sockets, also taking into account linked origin sockets. */
for (const InputSocketRef *input_socket : node->inputs()) {
SocketFieldState &state = field_state_by_socket_id[input_socket->id()];
if (state.is_always_single) {
state.is_single = true;
continue;
}
state.is_single = true;
if (input_socket->directly_linked_sockets().is_empty()) {
if (inferencing_interface.inputs[input_socket->index()] ==
InputSocketFieldType::Implicit) {
state.is_single = false;
}
}
else {
for (const OutputSocketRef *origin_socket : input_socket->directly_linked_sockets()) {
if (!field_state_by_socket_id[origin_socket->id()].is_single) {
state.is_single = false;
break;
}
}
}
}
/* Update field state of output sockets, also taking into account input sockets. */
for (const OutputSocketRef *output_socket : node->outputs()) {
SocketFieldState &state = field_state_by_socket_id[output_socket->id()];
const OutputFieldDependency &field_dependency =
inferencing_interface.outputs[output_socket->index()];
switch (field_dependency.field_type()) {
case OutputSocketFieldType::None: {
state.is_single = true;
break;
}
case OutputSocketFieldType::FieldSource: {
state.is_single = false;
state.is_field_source = true;
break;
}
case OutputSocketFieldType::PartiallyDependent:
case OutputSocketFieldType::DependentField: {
for (const InputSocketRef *input_socket :
gather_input_socket_dependencies(field_dependency, *node)) {
if (!input_socket->is_available()) {
continue;
}
if (!field_state_by_socket_id[input_socket->id()].is_single) {
state.is_single = false;
break;
}
}
break;
}
}
}
}
}
static void determine_group_output_states(const NodeTreeRef &tree,
FieldInferencingInterface &new_inferencing_interface,
const Span<SocketFieldState> field_state_by_socket_id)
{
for (const NodeRef *group_output_node : tree.nodes_by_type("NodeGroupOutput")) {
/* Ignore inactive group output nodes. */
if (!(group_output_node->bnode()->flag & NODE_DO_OUTPUT)) {
continue;
}
/* Determine dependencies of all group outputs. */
for (const InputSocketRef *group_output_socket : group_output_node->inputs().drop_back(1)) {
OutputFieldDependency field_dependency = find_group_output_dependencies(
*group_output_socket, field_state_by_socket_id);
new_inferencing_interface.outputs[group_output_socket->index()] = std::move(
field_dependency);
}
break;
}
}
static void update_socket_shapes(const NodeTreeRef &tree,
const Span<SocketFieldState> field_state_by_socket_id)
{
const eNodeSocketDisplayShape requires_data_shape = SOCK_DISPLAY_SHAPE_CIRCLE;
const eNodeSocketDisplayShape data_but_can_be_field_shape = SOCK_DISPLAY_SHAPE_DIAMOND_DOT;
const eNodeSocketDisplayShape is_field_shape = SOCK_DISPLAY_SHAPE_DIAMOND;
auto get_shape_for_state = [&](const SocketFieldState &state) {
if (state.is_always_single) {
return requires_data_shape;
}
if (!state.is_single) {
return is_field_shape;
}
if (state.requires_single) {
return requires_data_shape;
}
return data_but_can_be_field_shape;
};
for (const InputSocketRef *socket : tree.input_sockets()) {
bNodeSocket *bsocket = socket->bsocket();
const SocketFieldState &state = field_state_by_socket_id[socket->id()];
bsocket->display_shape = get_shape_for_state(state);
}
for (const OutputSocketRef *socket : tree.output_sockets()) {
bNodeSocket *bsocket = socket->bsocket();
const SocketFieldState &state = field_state_by_socket_id[socket->id()];
bsocket->display_shape = get_shape_for_state(state);
}
}
static bool update_field_inferencing(bNodeTree &btree)
{
using namespace blender::nodes;
if (btree.type != NTREE_GEOMETRY) {
return false;
}
/* Create new inferencing interface for this node group. */
FieldInferencingInterface *new_inferencing_interface = new FieldInferencingInterface();
new_inferencing_interface->inputs.resize(BLI_listbase_count(&btree.inputs),
InputSocketFieldType::IsSupported);
new_inferencing_interface->outputs.resize(BLI_listbase_count(&btree.outputs),
OutputFieldDependency::ForDataSource());
/* Create #NodeTreeRef to accelerate various queries on the node tree (e.g. linked sockets). */
const NodeTreeRef tree{&btree};
/* Keep track of the state of all sockets. The index into this array is #SocketRef::id(). */
Array<SocketFieldState> field_state_by_socket_id(tree.sockets().size());
propagate_data_requirements_from_right_to_left(tree, field_state_by_socket_id);
determine_group_input_states(tree, *new_inferencing_interface, field_state_by_socket_id);
propagate_field_status_from_left_to_right(tree, field_state_by_socket_id);
determine_group_output_states(tree, *new_inferencing_interface, field_state_by_socket_id);
update_socket_shapes(tree, field_state_by_socket_id);
/* Update the previous group interface. */
const bool group_interface_changed = btree.field_inferencing_interface == nullptr ||
*btree.field_inferencing_interface !=
*new_inferencing_interface;
delete btree.field_inferencing_interface;
btree.field_inferencing_interface = new_inferencing_interface;
return group_interface_changed;
}
} // namespace blender::bke::node_field_inferencing
/**
* \param tree_update_flag: #eNodeTreeUpdate enum.
*/
void ntreeUpdateAllUsers(Main *main, ID *id, const int tree_update_flag)
void ntreeUpdateAllUsers(Main *main, ID *id)
{
if (id == nullptr) {
return;
}
bool need_update = false;
/* Update all users of ngroup, to add/remove sockets as needed. */
FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
bool need_update = false;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->id == id) {
if (node->typeinfo->group_update_func) {
node->typeinfo->group_update_func(ntree, node);
}
BKE_node_tree_update_tag_node(ntree, node);
need_update = true;
}
}
if (need_update) {
ntree->update |= tree_update_flag;
ntreeUpdateTree(tree_update_flag ? main : nullptr, ntree);
}
}
FOREACH_NODETREE_END;
if (need_update) {
BKE_node_tree_update_main(main, nullptr);
}
if (GS(id->name) == ID_NT) {
bNodeTree *ngroup = (bNodeTree *)id;
@@ -5104,80 +4550,6 @@ void ntreeUpdateAllUsers(Main *main, ID *id, const int tree_update_flag)
}
}
void ntreeUpdateTree(Main *bmain, bNodeTree *ntree)
{
if (!ntree) {
return;
}
/* Avoid re-entrant updates, can be caused by RNA update callbacks. */
if (ntree->is_updating) {
return;
}
ntree->is_updating = true;
if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
/* set the bNodeSocket->link pointers */
ntree_update_link_pointers(ntree);
}
/* update individual nodes */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
/* node tree update tags override individual node update flags */
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
if (node->typeinfo->updatefunc) {
node->typeinfo->updatefunc(ntree, node);
}
nodeUpdateInternalLinks(ntree, node);
}
}
/* generic tree update callback */
if (ntree->typeinfo->update) {
ntree->typeinfo->update(ntree);
}
/* XXX this should be moved into the tree type update callback for tree supporting node groups.
* Currently the node tree interface is still a generic feature of the base NodeTree type.
*/
if (ntree->update & NTREE_UPDATE_GROUP) {
ntreeInterfaceTypeUpdate(ntree);
}
int tree_user_update_flag = 0;
if (ntree->update & NTREE_UPDATE) {
/* If the field interface of this node tree has changed, all node trees using
* this group will need to recalculate their interface as well. */
if (blender::bke::node_field_inferencing::update_field_inferencing(*ntree)) {
tree_user_update_flag |= NTREE_UPDATE_FIELD_INFERENCING;
}
}
if (bmain) {
ntreeUpdateAllUsers(bmain, &ntree->id, tree_user_update_flag);
}
if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
/* node updates can change sockets or links, repeat link pointer update afterward */
ntree_update_link_pointers(ntree);
/* update the node level from link dependencies */
ntree_update_node_level(ntree);
/* check link validity */
ntree_validate_links(ntree);
}
/* clear update flags */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node->update = 0;
}
ntree->update = 0;
ntree->is_updating = false;
}
void nodeUpdate(bNodeTree *ntree, bNode *node)
{
/* Avoid re-entrant updates, can be caused by RNA update callbacks. */

File diff suppressed because it is too large Load Diff

View File

@@ -70,6 +70,7 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_node_tree_update.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_screen.h"
@@ -590,7 +591,7 @@ static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup,
BLI_addtail(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
ngroup->update |= (in_out == SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
BKE_node_tree_update_tag_interface(ngroup);
return gsock;
}
@@ -2019,7 +2020,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
link->fromsock = gsock;
link->tonode = node;
link->tosock = sock;
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link_added(ntree, link);
sock->link = link;
}
@@ -2042,7 +2043,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
link->fromsock = sock;
link->tonode = NULL;
link->tosock = gsock;
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link_added(ntree, link);
gsock->link = link;
}
@@ -2282,7 +2283,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
do_versions_socket_default_value_259(sock);
}
ntree->update |= NTREE_UPDATE;
BKE_node_tree_update_tag(ntree);
}
FOREACH_NODETREE_END;
}

View File

@@ -88,6 +88,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
@@ -810,7 +811,9 @@ static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase)
}
/* Return true if there is something to convert. */
static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, char blend_method)
static void do_versions_material_convert_legacy_blend_mode(Main *bmain,
bNodeTree *ntree,
char blend_method)
{
bool need_update = false;
@@ -896,7 +899,7 @@ static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, cha
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
}
}
@@ -1594,13 +1597,13 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
bNodeTree *ntree = ma->nodetree;
if (ma->blend_method == 1 /* MA_BM_ADD */) {
if (ma->use_nodes) {
do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */);
do_versions_material_convert_legacy_blend_mode(bmain, ntree, 1 /* MA_BM_ADD */);
}
ma->blend_method = MA_BM_BLEND;
}
else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) {
if (ma->use_nodes) {
do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */);
do_versions_material_convert_legacy_blend_mode(bmain, ntree, 2 /* MA_BM_MULTIPLY */);
}
ma->blend_method = MA_BM_BLEND;
}

View File

@@ -58,6 +58,7 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -585,7 +586,7 @@ static bNodeTree *add_realize_node_tree(Main *bmain)
nodeSetSelected(node, false);
}
ntreeUpdateTree(bmain, node_tree);
BKE_node_tree_update_main_rooted(bmain, node_tree, NULL);
return node_tree;
}

View File

@@ -41,6 +41,7 @@
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "MEM_guardedalloc.h"
@@ -170,7 +171,7 @@ static void displacement_node_insert(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -243,7 +244,7 @@ static void square_roughness_node_insert(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -318,7 +319,7 @@ static void ambient_occlusion_node_relink(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -466,7 +467,7 @@ static void update_math_node_single_operand_operators(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -528,7 +529,7 @@ static void update_vector_math_node_add_and_subtract_operators(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -566,7 +567,7 @@ static void update_vector_math_node_dot_product_operator(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -631,7 +632,7 @@ static void update_vector_math_node_cross_product_operator(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -683,7 +684,7 @@ static void update_vector_math_node_normalize_operator(bNodeTree *ntree)
}
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -785,7 +786,7 @@ static void update_vector_math_node_average_operator(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -974,7 +975,7 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -1149,7 +1150,7 @@ static void update_voronoi_node_crackle(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -1191,7 +1192,7 @@ static void update_voronoi_node_coloring(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -1234,7 +1235,7 @@ static void update_voronoi_node_square_distance(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}
@@ -1279,7 +1280,7 @@ static void update_noise_and_wave_distortion(bNodeTree *ntree)
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
BKE_node_tree_update_main_rooted(NULL, ntree, NULL);
}
}

View File

@@ -120,6 +120,25 @@ void ED_node_set_active(struct Main *bmain,
struct bNode *node,
bool *r_active_texture_changed);
/**
* Call after one or more node trees have been changed and have been tagged accordingly.
*
* This function will make sure that other parts of Blender update accordingly. For example, if the
* node group interface changed, parent node groups have to be updated as well.
*
* Additionally, this will send notifiers and tag the depsgraph based on the changes. Depsgraph
* relation updates have to be triggered by the caller.
*
* \param C: Context if available. This can be null.
* \param bmain: Main whose data-blocks should be updated based on the changes.
* \param only_tagged_tree: Under some circumstances the caller knows that only one node tree has
* changed since the last update. In this case the function may be able to skip scanning bmain
* for other things that have to be changed.
*/
void ED_node_tree_propagate_change(const struct bContext *C,
struct Main *bmain,
struct bNodeTree *ntree);
void ED_node_composite_job(const struct bContext *C,
struct bNodeTree *nodetree,
struct Scene *scene_owner);

View File

@@ -6636,7 +6636,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
}
}
ntreeUpdateTree(CTX_data_main(C), ntree);
ED_node_tree_propagate_change(C, bmain, ntree);
/* In case we added more than one node, position them too. */
nodePositionPropagate(out_node);

View File

@@ -29,6 +29,7 @@ set(INC
../../imbuf
../../makesdna
../../makesrna
../../modifiers
../../nodes
../../render
../../windowmanager

View File

@@ -3323,7 +3323,8 @@ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), Poin
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
ED_node_tag_update_nodetree(bmain, ntree, node);
UNUSED_VARS(node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)

View File

@@ -37,6 +37,7 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -89,7 +90,7 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx
nodeSetSelected(node, true);
ntreeUpdateTree(bmain, snode->edittree);
BKE_node_tree_update_main_rooted(bmain, snode->edittree, nullptr);
ED_node_set_active(bmain, snode, snode->edittree, node, nullptr);
snode_update(snode, node);
@@ -288,9 +289,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
BLI_freelistN(&input_links);
/* always last */
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
return OPERATOR_FINISHED;
}
@@ -392,11 +391,7 @@ static int node_add_group_exec(bContext *C, wmOperator *op)
id_us_plus(group_node->id);
nodeSetActive(ntree, group_node);
ntreeUpdateTree(bmain, node_group);
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, nullptr);
return OPERATOR_FINISHED;
}
@@ -487,12 +482,7 @@ static int node_add_object_exec(bContext *C, wmOperator *op)
id_us_plus(&object->id);
nodeSetActive(ntree, object_node);
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tag_update_nodetree(bmain, ntree, object_node);
ED_node_tree_propagate_change(C, bmain, ntree);
DEG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
@@ -587,14 +577,9 @@ static int node_add_texture_exec(bContext *C, wmOperator *op)
id_us_plus(&texture->id);
nodeSetActive(ntree, texture_node);
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, ntree);
DEG_relations_tag_update(bmain);
ED_node_tag_update_nodetree(bmain, ntree, texture_node);
return OPERATOR_FINISHED;
}
@@ -693,14 +678,9 @@ static int node_add_collection_exec(bContext *C, wmOperator *op)
id_us_plus(&collection->id);
nodeSetActive(ntree, collection_node);
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, ntree);
DEG_relations_tag_update(bmain);
ED_node_tag_update_nodetree(bmain, ntree, collection_node);
return OPERATOR_FINISHED;
}
@@ -817,8 +797,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
}
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, snode->edittree);
DEG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
@@ -913,8 +892,7 @@ static int node_add_mask_exec(bContext *C, wmOperator *op)
node->id = mask;
id_us_plus(mask);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, snode->edittree);
DEG_relations_tag_update(bmain);
return OPERATOR_FINISHED;

View File

@@ -27,6 +27,7 @@
#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_text_types.h"
#include "DNA_world_types.h"
@@ -41,6 +42,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_workspace.h"
@@ -63,6 +65,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "MOD_nodes.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -440,6 +444,53 @@ void snode_notify(bContext *C, SpaceNode *snode)
}
}
static void handle_tree_change(ID *id, bNodeTree *ntree)
{
WM_main_add_notifier(NC_NODE | NA_EDITED, nullptr);
if (ntree->type == NTREE_SHADER) {
if (GS(id->name) == ID_MA) {
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
}
else if (GS(id->name) == ID_LA) {
WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
}
else if (GS(id->name) == ID_WO) {
WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
}
}
else if (ntree->type == NTREE_COMPOSIT) {
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
else if (ntree->type == NTREE_TEXTURE) {
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
else if (ntree->type == NTREE_GEOMETRY) {
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, id);
}
}
void ED_node_tree_propagate_change(const bContext *UNUSED(C), Main *bmain, bNodeTree *ntree)
{
struct UserData {
Main *bmain;
} user_data = {bmain};
NodeTreeUpdateExtraParams params = {0};
params.user_data = &user_data;
params.tree_changed_fn = [](ID *id, bNodeTree *ntree, void *UNUSED(user_data)) {
handle_tree_change(id, ntree);
};
params.tree_output_changed_fn = [](ID *id, bNodeTree *ntree, void *UNUSED(user_data)) {
if (id != nullptr) {
DEG_id_tag_update(id, 0);
}
DEG_id_tag_update(&ntree->id, 0);
};
BKE_node_tree_update_main_rooted(bmain, ntree, &params);
}
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
{
if (typeinfo) {
@@ -490,7 +541,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
}
ma->nodetree = ntreeCopyTree(bmain, ma_default->nodetree);
ntreeUpdateTree(bmain, ma->nodetree);
BKE_node_tree_update_main_rooted(bmain, ma->nodetree, nullptr);
}
else if (ELEM(GS(id->name), ID_WO, ID_LA)) {
/* Emission */
@@ -530,7 +581,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
output->locx = 300.0f;
output->locy = 300.0f;
nodeSetActive(ntree, output);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, nullptr);
}
else {
printf("ED_node_shader_default called on wrong ID type.\n");
@@ -570,7 +621,7 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
bNodeSocket *tosock = (bNodeSocket *)out->inputs.first;
nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), sce->nodetree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), sce->nodetree, nullptr);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
@@ -600,7 +651,7 @@ void ED_node_texture_default(const bContext *C, Tex *tex)
bNodeSocket *tosock = (bNodeSocket *)out->inputs.first;
nodeAddLink(tex->nodetree, in, fromsock, out, tosock);
ntreeUpdateTree(CTX_data_main(C), tex->nodetree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), tex->nodetree, nullptr);
}
/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
@@ -712,14 +763,10 @@ void ED_node_set_active(
}
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0) {
ED_node_tag_update_nodetree(bmain, ntree, node);
}
}
else if (do_update) {
ED_node_tag_update_nodetree(bmain, ntree, node);
}
ED_node_tree_propagate_change(nullptr, bmain, ntree);
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
/* If active texture changed, free glsl materials. */
LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
@@ -765,7 +812,7 @@ void ED_node_set_active(
if (r_active_texture_changed) {
*r_active_texture_changed = true;
}
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
WM_main_add_notifier(NC_IMAGE, nullptr);
}
@@ -782,7 +829,7 @@ void ED_node_set_active(
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0) {
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
/* Adding a node doesn't link this yet. */
@@ -797,11 +844,11 @@ void ED_node_set_active(
}
node->flag |= NODE_DO_OUTPUT;
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
}
else if (do_update) {
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
}
else if (ntree->type == NTREE_TEXTURE) {
@@ -1398,12 +1445,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
}
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, bmain, snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1495,8 +1537,7 @@ static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
}
}
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1663,7 +1704,7 @@ static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
node_flag_toggle_exec(snode, NODE_PREVIEW);
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1742,7 +1783,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
@@ -1783,10 +1824,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
}
}
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, bmain, snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1823,12 +1861,7 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, bmain, snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1872,10 +1905,7 @@ static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1910,10 +1940,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1960,7 +1987,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "file_path", file_path);
ntreeCompositOutputFileAddSocket(ntree, node, file_path, &scene->r.im_format);
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -2009,7 +2036,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
return OPERATOR_CANCELLED;
}
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
return OPERATOR_FINISHED;
}
@@ -2076,7 +2103,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
nimf->active_input++;
}
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -2322,10 +2349,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
}
Main *bmain = CTX_data_main(C);
ntreeUpdateTree(bmain, snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, snode->edittree);
/* Pasting nodes can create arbitrary new relations, because nodes can reference IDs. */
DEG_relations_tag_update(bmain);
@@ -2393,10 +2417,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
/* make the new socket active */
sock->flag |= SELECT;
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
@@ -2443,10 +2464,7 @@ static int ntree_socket_remove_exec(bContext *C, wmOperator *op)
active_sock->flag |= SELECT;
}
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
@@ -2497,7 +2515,7 @@ static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
/* Need the extra update here because the loop above does not check for valid links in the node
* group we're currently editing. */
ntree->update |= NTREE_UPDATE_GROUP | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ntree);
/* Deactivate sockets. */
LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) {
@@ -2506,10 +2524,7 @@ static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
/* Make the new socket active. */
iosock->flag |= SELECT;
ntreeUpdateTree(main, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, main, ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
@@ -2620,11 +2635,8 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
}
}
ntree->update |= NTREE_UPDATE_GROUP;
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
BKE_node_tree_update_tag_interface(ntree);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, nullptr);
@@ -2940,7 +2952,7 @@ static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
ntreeCompositCryptomatteAddSocket(ntree, node);
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
return OPERATOR_FINISHED;
}
@@ -2986,7 +2998,7 @@ static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(o
return OPERATOR_CANCELLED;
}
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
return OPERATOR_FINISHED;
}

View File

@@ -40,6 +40,7 @@
#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node_tree_update.h"
#include "BKE_report.h"
#include "DEG_depsgraph_build.h"
@@ -391,7 +392,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
/* delete the group instance and dereference group tree */
nodeRemoveNode(bmain, ntree, gnode, true);
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ntree);
return 1;
}
@@ -410,16 +411,14 @@ static int node_group_ungroup_exec(bContext *C, wmOperator *op)
}
if (gnode->id && node_group_ungroup(bmain, snode->edittree, gnode)) {
ntreeUpdateTree(bmain, snode->nodetree);
BKE_node_tree_update_main_rooted(bmain, snode->edittree, nullptr);
}
else {
BKE_report(op->reports, RPT_WARNING, "Cannot ungroup");
return OPERATOR_CANCELLED;
}
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), nullptr);
return OPERATOR_FINISHED;
}
@@ -554,9 +553,9 @@ static int node_group_separate_selected(
}
}
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ntree);
if (!make_copy) {
ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ngroup);
}
return 1;
@@ -611,10 +610,7 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
/* switch to parent tree */
ED_node_tree_pop(snode);
ntreeUpdateTree(CTX_data_main(C), snode->nodetree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), nullptr);
return OPERATOR_FINISHED;
}
@@ -982,9 +978,9 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
}
/* update of the group tree */
ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ngroup);
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ntree);
}
static bNode *node_group_make_from_selected(const bContext *C,
@@ -1014,7 +1010,7 @@ static bNode *node_group_make_from_selected(const bContext *C,
node_group_make_insert_selected(C, ntree, gnode);
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES;
BKE_node_tree_update_tag(ntree);
return gnode;
}
@@ -1044,14 +1040,10 @@ static int node_group_make_exec(bContext *C, wmOperator *op)
LISTBASE_FOREACH (bNode *, node, &ngroup->nodes) {
sort_multi_input_socket_links(snode, node, nullptr, nullptr);
}
ntreeUpdateTree(bmain, ngroup);
}
}
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, nullptr);
/* We broke relations in node tree, need to rebuild them in the graphs. */
DEG_relations_tag_update(bmain);
@@ -1104,12 +1096,7 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
nodeSetActive(ntree, gnode);
ED_node_tree_push(snode, ngroup, gnode);
ntreeUpdateTree(bmain, ngroup);
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, bmain, nullptr);
return OPERATOR_FINISHED;
}

View File

@@ -36,6 +36,7 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_screen.h"
#include "ED_node.h" /* own include */
@@ -604,7 +605,7 @@ static void snode_autoconnect(Main *bmain,
}
if (numlinks > 0) {
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, nullptr);
}
BLI_freelistN(nodelist);
@@ -851,7 +852,7 @@ static int link_socket_to_viewer(const bContext *C,
else {
link_to_change->fromnode = bnode_to_view;
link_to_change->fromsock = bsocket_to_view;
btree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link(btree);
}
remove_links_to_unavailable_viewer_sockets(*btree, *viewer_bnode);
@@ -860,7 +861,7 @@ static int link_socket_to_viewer(const bContext *C,
ED_spreadsheet_context_paths_set_geometry_node(CTX_data_main(C), snode, viewer_bnode);
}
ntreeUpdateTree(CTX_data_main(C), btree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), btree, nullptr);
snode_update(snode, viewer_bnode);
DEG_id_tag_update(&btree->id, 0);
@@ -908,7 +909,7 @@ static int node_active_link_viewer_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
snode_notify(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1037,8 +1038,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
/* add link to the node tree */
BLI_addtail(&ntree->links, link);
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link(ntree);
/* tag tonode for update */
link->tonode->update |= NODE_UPDATE;
@@ -1058,11 +1058,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
}
ntree->is_updating = false;
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
if (reset_view) {
UI_view2d_edge_pan_cancel(C, &nldrag->pan_data);
@@ -1425,9 +1421,7 @@ static int node_make_link_exec(bContext *C, wmOperator *op)
node_deselect_all_input_sockets(snode, false);
node_deselect_all_output_sockets(snode, false);
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1530,12 +1524,7 @@ static int cut_links_exec(bContext *C, wmOperator *op)
}
if (found) {
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1639,12 +1628,7 @@ static int mute_links_exec(bContext *C, wmOperator *op)
link->flag &= ~NODE_LINK_TEST;
}
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
}
ED_node_tree_propagate_change(C, CTX_data_main(C), snode->edittree);
return OPERATOR_FINISHED;
}
@@ -1695,11 +1679,7 @@ static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
}
}
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
ED_node_tree_propagate_change(C, CTX_data_main(C), ntree);
return OPERATOR_FINISHED;
}
@@ -2616,7 +2596,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area)
snode->runtime->iofsd = iofsd;
}
ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */
BKE_node_tree_update_main_rooted(bmain, snode->edittree, nullptr); /* needed for pointers */
snode_update(snode, select);
ED_node_tag_update_id((ID *)snode->edittree);
ED_node_tag_update_id(snode->id);

View File

@@ -37,6 +37,7 @@
#include "BKE_context.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node_tree_update.h"
#include "RNA_access.h"
@@ -84,7 +85,7 @@ static void node_link_item_apply(Main *bmain, bNode *node, NodeLinkItem *item)
{
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
node->id = (ID *)item->ngroup;
ntreeUpdateTree(bmain, item->ngroup);
BKE_node_tree_update_main_rooted(bmain, item->ngroup, nullptr);
}
else {
/* nothing to do for now */
@@ -180,9 +181,7 @@ static void node_socket_disconnect(Main *bmain,
sock_to->flag |= SOCK_COLLAPSED;
nodeUpdate(ntree, node_to);
ntreeUpdateTree(bmain, ntree);
ED_node_tag_update_nodetree(bmain, ntree, node_to);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -196,9 +195,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
sock_to->flag |= SOCK_COLLAPSED;
nodeUpdate(ntree, node_to);
ntreeUpdateTree(bmain, ntree);
ED_node_tag_update_nodetree(bmain, ntree, node_to);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
/* add new node connected to this socket, or replace an existing one */
@@ -301,9 +298,7 @@ static void node_socket_add_replace(const bContext *C,
nodeUpdate(ntree, node_from);
nodeUpdate(ntree, node_to);
ntreeUpdateTree(CTX_data_main(C), ntree);
ED_node_tag_update_nodetree(CTX_data_main(C), ntree, node_to);
ED_node_tree_propagate_change(nullptr, bmain, ntree);
}
/****************************** Node Link Menu *******************************/

View File

@@ -31,6 +31,7 @@
#include "BKE_context.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_report.h"
#include "ED_node.h"
@@ -246,7 +247,7 @@ void special_aftertrans_update__node(bContext *C, TransInfo *t)
nodeRemoveNode(bmain, ntree, node, true);
}
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
}
}

View File

@@ -180,7 +180,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
if (node && is_image_texture_node(node)) {
node->id = &ima->id;
ED_node_tag_update_nodetree(bmain, ma->nodetree, node);
ED_node_tree_propagate_change(NULL, bmain, ma->nodetree);
}
}

View File

@@ -48,6 +48,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -415,7 +416,7 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain,
}
nodeSetActive(ntree, output_material);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
return ma;
}

View File

@@ -16,6 +16,8 @@
#include "Materials.h"
#include "BKE_node_tree_update.h"
MaterialNode::MaterialNode(bContext *C, Material *ma, KeyImageMap &key_image_map)
: mContext(C), material(ma), effect(nullptr), key_image_map(&key_image_map)
{
@@ -107,7 +109,7 @@ bNodeTree *MaterialNode::prepare_material_nodetree()
void MaterialNode::update_material_nodetree()
{
ntreeUpdateTree(CTX_data_main(mContext), ntree);
BKE_node_tree_update_main_rooted(CTX_data_main(mContext), ntree, NULL);
}
bNode *MaterialNode::add_node(int node_type, int locx, int locy, std::string label)

View File

@@ -23,6 +23,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
@@ -340,7 +341,7 @@ void USDMaterialReader::import_usd_preview(Material *mtl,
nodeSetActive(ntree, output);
ntreeUpdateTree(bmain_, ntree);
BKE_node_tree_update_main_rooted(bmain_, ntree, nullptr);
/* Optionally, set the material blend mode. */

View File

@@ -159,7 +159,7 @@ typedef struct bNodeSocket {
* restores pointer from matching own_index. */
struct bNodeSocket *groupsock DNA_DEPRECATED;
/** A link pointer, set in ntreeUpdateTree. */
/** A link pointer, set in BKE_node_tree_update_main. */
struct bNodeLink *link;
/* XXX deprecated, socket input values are stored in default_value now.
@@ -172,6 +172,9 @@ typedef struct bNodeSocket {
* data. It has to be updated when the node declaration changes.
*/
const SocketDeclarationHandle *declaration;
uint8_t changed_flag;
char _pad[7];
} bNodeSocket;
/* sock->type */
@@ -261,7 +264,7 @@ typedef struct bNode {
/** Used as a boolean for execution. */
uint8_t need_exec;
char _pad[1];
uint8_t changed_flag;
/** Custom user-defined color. */
float color[3];
@@ -551,7 +554,8 @@ typedef struct bNodeTree {
* in case multiple different editors are used and make context ambiguous.
*/
bNodeInstanceKey active_viewer_key;
char _pad[4];
char _pad[3];
uint8_t changed_flag;
/** Execution data.
*
@@ -576,6 +580,31 @@ typedef struct bNodeTree {
struct PreviewImage *preview;
} bNodeTree;
/** bNodeSocket->changed_flag */
typedef enum eNodeSocketChangedFlag {
SOCK_CHANGED_NONE = 0,
SOCK_CHANGED_ANY = (1 << 0),
} eNodeSocketChangedFlag;
/** bNode->changed_flag */
typedef enum eNodeChangedFlag {
NODE_CHANGED_NONE = 0,
NODE_CHANGED_ANY = (1 << 0),
} eNodeChangedFlag;
/** bNodeTree->changed_flag */
typedef enum eNodeTreeChangedFlag {
NTREE_CHANGED_NONE = 0,
NTREE_CHANGED_ANY = (1 << 0),
NTREE_CHANGED_SOCKET = (1 << 1),
NTREE_CHANGED_NODE = (1 << 2),
NTREE_CHANGED_LINK = (1 << 3),
NTREE_CHANGED_REMOVED_ANY = (1 << 4),
NTREE_CHANGED_MISSING_RUNTIME_DATA = (1 << 5),
NTREE_CHANGED_INTERFACE = (1 << 6),
NTREE_CHANGED_ALL = -1,
} eNodeTreeChangedFlag;
/* ntree->type, index */
#define NTREE_UNDEFINED -2 /* Represents #NodeTreeTypeUndefined type. */

View File

@@ -321,7 +321,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
CMP_NODE_VALTORGB,
TEX_NODE_VALTORGB,
GEO_NODE_LEGACY_ATTRIBUTE_COLOR_RAMP)) {
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
}
break;

View File

@@ -168,7 +168,7 @@ static void rna_ImageUser_update(Main *bmain, Scene *scene, PointerRNA *ptr)
if (id) {
if (GS(id->name) == ID_NT) {
/* Special update for nodetrees to find parent datablock. */
ED_node_tag_update_nodetree(bmain, (bNodeTree *)id, NULL);
ED_node_tree_propagate_change(NULL, bmain, NULL);
}
else {
/* Update material or texture for render preview. */

View File

@@ -41,6 +41,7 @@
#include "BKE_cryptomatte.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_texture.h"
#include "RNA_access.h"
@@ -1186,7 +1187,7 @@ static void rna_NodeTree_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *p
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
ED_node_tag_update_nodetree(bmain, ntree, NULL);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
static bNode *rna_NodeTree_node_new(bNodeTree *ntree,
@@ -1235,7 +1236,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree,
ntreeTexCheckCyclics(ntree);
}
ntreeUpdateTree(CTX_data_main(C), ntree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), ntree, NULL);
nodeUpdate(ntree, node);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
@@ -1262,7 +1263,7 @@ static void rna_NodeTree_node_remove(bNodeTree *ntree,
RNA_POINTER_INVALIDATE(node_ptr);
ntreeUpdateTree(bmain, ntree); /* update group node socket links */
BKE_node_tree_update_main_rooted(bmain, ntree, NULL); /* update group node socket links */
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1282,7 +1283,7 @@ static void rna_NodeTree_node_clear(bNodeTree *ntree, Main *bmain, ReportList *r
node = next_node;
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1366,9 +1367,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
nodeUpdate(ntree, tonode);
}
ntreeUpdateTree(bmain, ntree);
ED_node_tag_update_nodetree(bmain, ntree, ret->tonode);
ED_node_tree_propagate_change(NULL, bmain, ntree);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
return ret;
@@ -1393,7 +1392,7 @@ static void rna_NodeTree_link_remove(bNodeTree *ntree,
nodeRemLink(ntree, link);
RNA_POINTER_INVALIDATE(link_ptr);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1412,7 +1411,7 @@ static void rna_NodeTree_link_clear(bNodeTree *ntree, Main *bmain, ReportList *r
link = next_link;
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1470,7 +1469,7 @@ static bNodeSocket *rna_NodeTree_inputs_new(
bNodeSocket *sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
return sock;
@@ -1485,7 +1484,7 @@ static bNodeSocket *rna_NodeTree_outputs_new(
bNodeSocket *sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
return sock;
@@ -1506,7 +1505,7 @@ static void rna_NodeTree_socket_remove(bNodeTree *ntree,
else {
ntreeRemoveSocketInterface(ntree, sock);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
DEG_id_tag_update(&ntree->id, 0);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1522,7 +1521,7 @@ static void rna_NodeTree_inputs_clear(bNodeTree *ntree, Main *bmain, ReportList
ntreeRemoveSocketInterface(ntree, socket);
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1536,7 +1535,7 @@ static void rna_NodeTree_outputs_clear(bNodeTree *ntree, Main *bmain, ReportList
ntreeRemoveSocketInterface(ntree, socket);
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1565,9 +1564,9 @@ static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_ind
}
}
ntree->update |= NTREE_UPDATE_GROUP_IN;
BKE_node_tree_update_tag_interface(ntree);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1596,9 +1595,9 @@ static void rna_NodeTree_outputs_move(bNodeTree *ntree, Main *bmain, int from_in
}
}
ntree->update |= NTREE_UPDATE_GROUP_OUT;
BKE_node_tree_update_tag_interface(ntree);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -1606,10 +1605,8 @@ static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C)
{
Main *bmain = CTX_data_main(C);
ntree->update |= NTREE_UPDATE_GROUP;
ntreeUpdateTree(bmain, ntree);
ED_node_tag_update_nodetree(bmain, ntree, NULL);
BKE_node_tree_update_tag_interface(ntree);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
/* ******** NodeLink ******** */
@@ -2489,7 +2486,8 @@ static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
ED_node_tag_update_nodetree(bmain, ntree, node);
UNUSED_VARS(node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
static void rna_Node_update_relations(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -2498,9 +2496,9 @@ static void rna_Node_update_relations(Main *bmain, Scene *scene, PointerRNA *ptr
DEG_relations_tag_update(bmain);
}
static void rna_Node_socket_value_update(ID *id, bNode *node, bContext *C)
static void rna_Node_socket_value_update(ID *id, bNode *UNUSED(node), bContext *C)
{
ED_node_tag_update_nodetree(CTX_data_main(C), (bNodeTree *)id, node);
ED_node_tree_propagate_change(C, CTX_data_main(C), (bNodeTree *)id);
}
static void rna_Node_select_set(PointerRNA *ptr, bool value)
@@ -2554,7 +2552,7 @@ static bNodeSocket *rna_Node_inputs_new(ID *id,
BKE_report(reports, RPT_ERROR, "Unable to create socket");
}
else {
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2588,7 +2586,7 @@ static bNodeSocket *rna_Node_outputs_new(ID *id,
BKE_report(reports, RPT_ERROR, "Unable to create socket");
}
else {
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2606,7 +2604,7 @@ static void rna_Node_socket_remove(
else {
nodeRemoveSocket(ntree, node, sock);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
}
@@ -2621,7 +2619,7 @@ static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain)
nodeRemoveSocket(ntree, node, sock);
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2635,7 +2633,7 @@ static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain)
nodeRemoveSocket(ntree, node, sock);
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2667,7 +2665,7 @@ static void rna_Node_inputs_move(ID *id, bNode *node, Main *bmain, int from_inde
}
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2699,7 +2697,7 @@ static void rna_Node_outputs_move(ID *id, bNode *node, Main *bmain, int from_ind
}
}
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
@@ -2928,9 +2926,8 @@ static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
if (nodeFindNode(ntree, sock, &node, NULL)) {
ED_node_tag_update_nodetree(bmain, ntree, node);
}
UNUSED_VARS(sock, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
static bool rna_NodeSocket_is_output_get(PointerRNA *ptr)
@@ -3220,10 +3217,8 @@ static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), Po
return;
}
ntree->update |= NTREE_UPDATE_GROUP;
ntreeUpdateTree(bmain, ntree);
ED_node_tag_update_nodetree(bmain, ntree, NULL);
BKE_node_tree_update_tag_interface(ntree);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
/* ******** Standard Node Socket Base Types ******** */
@@ -3342,7 +3337,7 @@ static void rna_NodeSocketStandard_value_and_relation_update(struct bContext *C,
rna_NodeSocketStandard_value_update(C, ptr);
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
Main *bmain = CTX_data_main(C);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, NULL);
DEG_relations_tag_update(bmain);
}
@@ -3589,21 +3584,17 @@ static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), Pointer
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
UNUSED_VARS(node);
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
WM_main_add_notifier(NC_IMAGE, NULL);
}
static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
if (node->id) {
ntreeUpdateTree(bmain, (bNodeTree *)node->id);
}
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
DEG_relations_tag_update(bmain);
}
@@ -4264,7 +4255,7 @@ static bNodeSocket *rna_NodeOutputFile_slots_new(
sock = ntreeCompositOutputFileAddSocket(ntree, node, name, im_format);
ntreeUpdateTree(CTX_data_main(C), ntree);
BKE_node_tree_update_main_rooted(CTX_data_main(C), ntree, NULL);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
return sock;
@@ -4373,7 +4364,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
RE_engine_free(engine);
}
ED_node_tag_update_nodetree(bmain, ntree, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr)

View File

@@ -199,7 +199,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
}
else if (GS(id->name) == ID_NT) {
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
ED_node_tag_update_nodetree(bmain, ntree, NULL);
ED_node_tree_propagate_change(NULL, bmain, ntree);
}
}

View File

@@ -60,6 +60,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_node_tree_update.h"
#include "BKE_object.h"
#include "BKE_pointcloud.h"
#include "BKE_screen.h"
@@ -695,7 +696,7 @@ void MOD_nodes_init(Main *bmain, NodesModifierData *nmd)
group_input_node,
(bNodeSocket *)group_input_node->outputs.first);
ntreeUpdateTree(bmain, ntree);
BKE_node_tree_update_main_rooted(bmain, ntree, nullptr);
}
static void initialize_group_input(NodesModifierData &nmd,

View File

@@ -37,6 +37,7 @@
#include "BLT_translation.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "RNA_types.h"
@@ -145,7 +146,7 @@ static bNodeSocket *group_verify_socket(bNodeTree *ntree,
if (sock->typeinfo != iosock->typeinfo) {
nodeModifySocketType(ntree, gnode, sock, iosock->idname);
/* Flag the tree to make sure link validity is updated after type changes. */
ntree->update |= NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag_link(ntree);
}
if (iosock->typeinfo->interface_verify_socket) {

View File

@@ -28,6 +28,7 @@
#include "BKE_global.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "MEM_guardedalloc.h"
@@ -172,7 +173,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
/* Using global main here is likely totally wrong, not sure what to do about that one though...
* We cannot even check ntree is in global main,
* since most of the time it won't be (thanks to ntree design)!!! */
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, nullptr);
/* get a dependency-sorted list of nodes */
ntreeGetDependencyList(ntree, &nodelist, &totnodes);

View File

@@ -44,6 +44,7 @@
#include "BKE_lib_id.h"
#include "BKE_linestyle.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_scene.h"
#include "RNA_access.h"
@@ -375,7 +376,7 @@ static void ntree_shader_unlink_hidden_value_sockets(bNode *group_node, bNodeSoc
}
if (removed_link) {
ntreeUpdateTree(G.main, group_ntree);
BKE_node_tree_update_main_rooted(G.main, group_ntree, NULL);
}
}
@@ -434,7 +435,7 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree)
}
if (link_added) {
ntreeUpdateTree(G.main, localtree);
BKE_node_tree_update_main_rooted(G.main, localtree, NULL);
}
}
@@ -514,7 +515,7 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode)
ntreeFreeLocalNode(ntree, node);
}
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
BKE_node_tree_update_tag(ntree);
}
/* Flatten group to only have a simple single tree */
@@ -539,7 +540,7 @@ static void ntree_shader_groups_flatten(bNodeTree *localtree)
}
}
ntreeUpdateTree(G.main, localtree);
BKE_node_tree_update_main_rooted(G.main, localtree, NULL);
}
/* Check whether shader has a displacement.
@@ -559,7 +560,7 @@ static bool ntree_shader_has_displacement(bNodeTree *ntree,
return false;
}
/* Make sure sockets links pointers are correct. */
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
bNodeSocket *displacement = ntree_shader_node_find_input(output_node, "Displacement");
if (displacement == NULL) {
@@ -648,7 +649,7 @@ static void ntree_shader_bypass_tagged_bump_nodes(bNodeTree *ntree)
ntree_shader_bypass_bump_link(ntree, node, link);
}
}
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
}
static bool ntree_branch_count_and_tag_nodes(bNode *fromnode, bNode *tonode, void *userdata)
@@ -733,7 +734,7 @@ static void ntree_shader_copy_branch_displacement(bNodeTree *ntree,
nodeRemLink(ntree, displacement_link);
nodeAddLink(ntree, displacement_node, displacement_socket, tonode, tosock);
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
}
/* Re-link displacement output to unconnected normal sockets via bump node.
@@ -797,12 +798,12 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
geo_node->tmp_flag = -2;
bump_node->tmp_flag = -2;
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
/* Connect all free-standing Normal inputs and relink geometry/coordinate nodes. */
ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket);
/* We modified the tree, it needs to be updated now. */
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
}
static void node_tag_branch_as_derivative(bNode *node, int dx)
@@ -882,7 +883,7 @@ void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tag
return;
}
/* Make sure sockets links pointers are correct. */
ntreeUpdateTree(G.main, ntree);
BKE_node_tree_update_main_rooted(G.main, ntree, NULL);
nodeChainIterBackwards(ntree, output_node, ntree_tag_bsdf_cb, tags, 0);
}