Cleanup: move internal links of nodes to runtime data

No functional changes are expected.
This commit is contained in:
Jacques Lucke 2022-11-18 13:46:21 +01:00
parent 40b63bbf5b
commit b4c3ea2644
Notes: blender-bot 2023-06-12 00:52:52 +02:00
Referenced by commit b43bdd8ba2, Fix T102751: missing tree update with muted nodes
Referenced by commit ab819517fc, Fix: Crash when deleting node
Referenced by issue #102751, Regression: Geometry Node: No update for tree with muted nodes
14 changed files with 86 additions and 89 deletions

View File

@ -690,6 +690,7 @@ void nodeRemoveNode(struct Main *bmain,
void nodeDimensionsGet(const struct bNode *node, float *r_width, float *r_height);
void nodeTagUpdateID(struct bNode *node);
void nodeInternalLinks(struct bNode *node, struct bNodeLink ***r_links, int *r_len);
#ifdef __cplusplus

View File

@ -186,10 +186,12 @@ class bNodeRuntime : NonCopyable, NonMovable {
/** Offset that will be added to locx for insert offset animation. */
float anim_ofsx;
/** List of cached internal links (input to output), for muted nodes and operators. */
Vector<bNodeLink *> internal_links;
/** Only valid if #topology_cache_is_dirty is false. */
Vector<bNodeSocket *> inputs;
Vector<bNodeSocket *> outputs;
Vector<bNodeLink *> internal_links;
Map<StringRefNull, bNodeSocket *> inputs_by_identifier;
Map<StringRefNull, bNodeSocket *> outputs_by_identifier;
int index_in_tree = -1;
@ -481,9 +483,8 @@ inline bool bNode::is_group_output() const
return this->type == NODE_GROUP_OUTPUT;
}
inline blender::Span<const bNodeLink *> bNode::internal_links_span() const
inline blender::Span<const bNodeLink *> bNode::internal_links() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->internal_links;
}

View File

@ -699,8 +699,6 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
BLO_read_data_address(reader, &node->prop);
IDP_BlendDataRead(reader, &node->prop);
BLI_listbase_clear(&node->internal_links);
if (node->type == CMP_NODE_MOVIEDISTORTION) {
/* Do nothing, this is runtime cache and hence handled by generic code using
* `IDTypeInfo.foreach_cache` callback. */
@ -1970,11 +1968,12 @@ void nodeRemoveSocketEx(struct bNodeTree *ntree,
}
}
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node->internal_links) {
for (bNodeLink *link : node->runtime->internal_links) {
if (link->fromsock == sock || link->tosock == sock) {
BLI_remlink(&node->internal_links, link);
node->runtime->internal_links.remove_first_occurrence_and_reorder(link);
MEM_freeN(link);
BKE_ntree_update_tag_node_internal_link(ntree, node);
break;
}
}
@ -1996,7 +1995,10 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
}
}
BLI_freelistN(&node->internal_links);
for (bNodeLink *link : node->runtime->internal_links) {
MEM_freeN(link);
}
node->runtime->internal_links.clear();
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
node_socket_free(sock, true);
@ -2304,14 +2306,14 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
node_dst->prop = IDP_CopyProperty_ex(node_src.prop, flag);
}
BLI_listbase_clear(&node_dst->internal_links);
LISTBASE_FOREACH (const bNodeLink *, src_link, &node_src.internal_links) {
node_dst->runtime->internal_links.clear();
for (const bNodeLink *src_link : node_src.runtime->internal_links) {
bNodeLink *dst_link = (bNodeLink *)MEM_dupallocN(src_link);
dst_link->fromnode = node_dst;
dst_link->tonode = node_dst;
dst_link->fromsock = socket_map.lookup(src_link->fromsock);
dst_link->tosock = socket_map.lookup(src_link->tosock);
BLI_addtail(&node_dst->internal_links, dst_link);
node_dst->runtime->internal_links.append(dst_link);
}
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
@ -2469,7 +2471,7 @@ static void adjust_multi_input_indices_after_removed_link(bNodeTree *ntree,
void nodeInternalRelink(bNodeTree *ntree, bNode *node)
{
/* store link pointers in output sockets, for efficient lookup */
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
for (bNodeLink *link : node->runtime->internal_links) {
link->tosock->link = link;
}
@ -2977,7 +2979,10 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
MEM_freeN(sock);
}
BLI_freelistN(&node->internal_links);
for (bNodeLink *link : node->runtime->internal_links) {
MEM_freeN(link);
}
node->runtime->internal_links.clear();
if (node->prop) {
/* Remember, no ID user refcount management here! */
@ -3763,6 +3768,12 @@ void nodeTagUpdateID(bNode *node)
node->runtime->update |= NODE_UPDATE_ID;
}
void nodeInternalLinks(bNode *node, bNodeLink ***r_links, int *r_len)
{
*r_links = node->runtime->internal_links.data();
*r_len = node->runtime->internal_links.size();
}
/* ************** Node Clipboard *********** */
#define USE_NODE_CB_VALIDATE

View File

@ -67,21 +67,6 @@ static void update_link_vector(const bNodeTree &ntree)
}
}
static void update_internal_links(const bNodeTree &ntree)
{
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
for (bNode *node : tree_runtime.nodes) {
node->runtime->internal_links.clear();
for (bNodeSocket *socket : node->runtime->outputs) {
socket->runtime->internal_link_input = nullptr;
}
LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) {
node->runtime->internal_links.append(link);
link->tosock->runtime->internal_link_input = link->fromsock;
}
}
}
static void update_socket_vectors_and_owner_node(const bNodeTree &ntree)
{
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
@ -431,7 +416,6 @@ static void ensure_topology_cache(const bNodeTree &ntree)
update_node_vector(ntree);
update_link_vector(ntree);
update_socket_vectors_and_owner_node(ntree);
update_internal_links(ntree);
update_directly_linked_links_and_sockets(ntree);
threading::parallel_invoke(
tree_runtime.nodes.size() > 32,

View File

@ -1137,7 +1137,7 @@ class NodeTreeMainUpdater {
}
}
/* Rebuilt internal links if they have changed. */
if (node->internal_links_span().size() != expected_internal_links.size()) {
if (node->runtime->internal_links.size() != expected_internal_links.size()) {
this->update_internal_links_in_node(ntree, *node, expected_internal_links);
}
else {
@ -1145,7 +1145,7 @@ class NodeTreeMainUpdater {
const bNodeSocket *from_socket = item.first;
const bNodeSocket *to_socket = item.second;
bool found = false;
for (const bNodeLink *internal_link : node->internal_links_span()) {
for (const bNodeLink *internal_link : node->runtime->internal_links) {
if (from_socket == internal_link->fromsock && to_socket == internal_link->tosock) {
found = true;
}
@ -1192,7 +1192,9 @@ class NodeTreeMainUpdater {
bNode &node,
Span<std::pair<bNodeSocket *, bNodeSocket *>> links)
{
BLI_freelistN(&node.internal_links);
for (bNodeLink *link : node.runtime->internal_links) {
MEM_freeN(link);
}
for (const auto &item : links) {
bNodeSocket *from_socket = item.first;
bNodeSocket *to_socket = item.second;
@ -1202,7 +1204,7 @@ class NodeTreeMainUpdater {
link->tonode = &node;
link->tosock = to_socket;
link->flag |= NODE_LINK_VALID;
BLI_addtail(&node.internal_links, link);
node.runtime->internal_links.append(link);
}
BKE_ntree_update_tag_node_internal_link(&ntree, &node);
}

View File

@ -1707,26 +1707,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 264, 6)) {
/* Fix for bug T32982, internal_links list could get corrupted from r51630 onward.
* Simply remove bad internal_links lists to avoid NULL pointers.
*/
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
bNode *node;
bNodeLink *link, *nextlink;
for (node = ntree->nodes.first; node; node = node->next) {
for (link = node->internal_links.first; link; link = nextlink) {
nextlink = link->next;
if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
BLI_remlink(&node->internal_links, link);
}
}
}
}
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_ATLEAST(bmain, 264, 7)) {
/* convert tiles size from resolution and number of tiles */
{

View File

@ -6,6 +6,7 @@
#include "DNA_node_types.h"
#include "BKE_node.h"
#include "BKE_node_runtime.hh"
#include "COM_Converter.h"
#include "COM_Debug.h"
@ -180,8 +181,7 @@ void NodeGraph::add_proxies_mute(bNodeTree *b_ntree,
bNodeInstanceKey key,
bool is_active_group)
{
for (bNodeLink *b_link = (bNodeLink *)b_node->internal_links.first; b_link;
b_link = b_link->next) {
for (const bNodeLink *b_link : b_node->internal_links()) {
SocketProxyNode *proxy = new SocketProxyNode(b_node, b_link->fromsock, b_link->tosock, false);
add_node(proxy, b_ntree, key, is_active_group);
}

View File

@ -703,7 +703,7 @@ static void node_draw_mute_line(const bContext &C,
{
GPU_blend(GPU_BLEND_ALPHA);
LISTBASE_FOREACH (const bNodeLink *, link, &node.internal_links) {
for (const bNodeLink *link : node.internal_links()) {
if (!nodeLinkIsHidden(link)) {
node_draw_link_bezier(C, v2d, snode, *link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE, false);
}

View File

@ -320,8 +320,6 @@ typedef struct bNode {
struct ID *id;
/** Custom data, must be struct, for storage in file. */
void *storage;
/** List of cached internal links (input to output), for muted nodes and operators. */
ListBase internal_links;
/** Root offset for drawing (parent space). */
float locx, locy;
@ -349,6 +347,8 @@ typedef struct bNode {
bool is_group_input() const;
bool is_group_output() const;
const blender::nodes::NodeDeclaration *declaration() const;
/** A span containing all internal links when the node is muted. */
blender::Span<const bNodeLink *> internal_links() const;
/* The following methods are only available when #bNodeTree.ensure_topology_cache has been
* called. */
@ -365,8 +365,6 @@ typedef struct bNode {
/** Utility to get an output socket by its index. */
bNodeSocket &output_socket(int index);
const bNodeSocket &output_socket(int index) const;
/** A span containing all internal links when the node is muted. */
blender::Span<const bNodeLink *> internal_links_span() const;
/** Lookup socket of this node by its identifier. */
const bNodeSocket &input_by_identifier(blender::StringRef identifier) const;
const bNodeSocket &output_by_identifier(blender::StringRef identifier) const;

View File

@ -2357,6 +2357,15 @@ static void rna_Node_parent_set(PointerRNA *ptr,
}
}
static void rna_Node_internal_links_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
bNode *node = ptr->data;
bNodeLink **begin;
int len;
nodeInternalLinks(node, &begin, &len);
rna_iterator_array_begin(iter, begin, sizeof(bNodeLink *), len, false, NULL);
}
static bool rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value)
{
bNode *node = ptr->data;
@ -12243,7 +12252,15 @@ static void rna_def_node(BlenderRNA *brna)
rna_def_node_sockets_api(brna, prop, SOCK_OUT);
prop = RNA_def_property(srna, "internal_links", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "internal_links", NULL);
RNA_def_property_collection_funcs(prop,
"rna_Node_internal_links_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_dereference_get",
NULL,
NULL,
NULL,
NULL);
RNA_def_property_struct_type(prop, "NodeLink");
RNA_def_property_ui_text(
prop, "Internal Links", "Internal input-to-output connections for muting");

View File

@ -236,7 +236,7 @@ void DOutputSocket::foreach_target_socket(ForeachTargetSocketFn target_fn,
path_info.sockets.pop_last();
}
else if (linked_node->is_muted()) {
for (const bNodeLink *internal_link : linked_node->internal_links_span()) {
for (const bNodeLink *internal_link : linked_node->internal_links()) {
if (internal_link->fromsock != linked_socket.bsocket()) {
continue;
}

View File

@ -337,7 +337,7 @@ class LazyFunctionForMutedNode : public LazyFunction {
input_by_output_index_.reinitialize(outputs_.size());
input_by_output_index_.fill(-1);
for (const bNodeLink *internal_link : node.internal_links_span()) {
for (const bNodeLink *internal_link : node.internal_links()) {
const int input_i = r_used_inputs.first_index_of_try(internal_link->fromsock);
const int output_i = r_used_outputs.first_index_of_try(internal_link->tosock);
if (ELEM(-1, input_i, output_i)) {

View File

@ -69,32 +69,25 @@ static void node_init_input_index(bNodeSocket *sock, int *index)
}
}
static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
static void node_init_output_index_muted(bNodeSocket *sock,
int *index,
const blender::Span<bNodeLink *> internal_links)
{
if (internal_links) {
bNodeLink *link;
/* copy the stack index from internally connected input to skip the node */
for (link = (bNodeLink *)internal_links->first; link; link = link->next) {
if (link->tosock == sock) {
sock->stack_index = link->fromsock->stack_index;
/* set the link pointer to indicate that this socket
* should not overwrite the stack value!
*/
sock->link = link;
break;
}
}
/* if not internally connected, assign a new stack index anyway to avoid bad stack access */
if (!link) {
if (node_exec_socket_use_stack(sock)) {
sock->stack_index = (*index)++;
}
else {
sock->stack_index = -1;
}
bNodeLink *link;
/* copy the stack index from internally connected input to skip the node */
for (bNodeLink *iter_link : internal_links) {
if (iter_link->tosock == sock) {
sock->stack_index = iter_link->fromsock->stack_index;
/* set the link pointer to indicate that this socket
* should not overwrite the stack value!
*/
sock->link = iter_link;
link = iter_link;
break;
}
}
else {
/* if not internally connected, assign a new stack index anyway to avoid bad stack access */
if (!link) {
if (node_exec_socket_use_stack(sock)) {
sock->stack_index = (*index)++;
}
@ -104,6 +97,16 @@ static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *inte
}
}
static void node_init_output_index(bNodeSocket *sock, int *index)
{
if (node_exec_socket_use_stack(sock)) {
sock->stack_index = (*index)++;
}
else {
sock->stack_index = -1;
}
}
/* basic preparation of socket stacks */
static struct bNodeStack *setup_stack(bNodeStack *stack,
bNodeTree *ntree,
@ -178,12 +181,12 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
node_init_output_index(sock, &index, &node->internal_links);
node_init_output_index_muted(sock, &index, node->runtime->internal_links);
}
}
else {
for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
node_init_output_index(sock, &index, nullptr);
node_init_output_index(sock, &index);
}
}
}

View File

@ -220,7 +220,7 @@ static void refresh_socket_list(bNodeTree &ntree,
link->tosock = new_socket;
}
}
LISTBASE_FOREACH (bNodeLink *, internal_link, &node.internal_links) {
for (bNodeLink *internal_link : node.runtime->internal_links) {
if (internal_link->fromsock == old_socket_with_same_identifier) {
internal_link->fromsock = new_socket;
}