Fix T101214: hidden link can cause cycle in node tree

Links that are linked to unavailable sockets should be ignored.
This commit is contained in:
2022-09-20 13:21:03 +02:00
parent 22efaa2e7b
commit 2b4cb893e7
6 changed files with 42 additions and 24 deletions

View File

@@ -123,15 +123,17 @@ static void update_directly_linked_links_and_sockets(const bNodeTree &ntree)
socket->runtime->directly_linked_links.clear();
socket->runtime->directly_linked_sockets.clear();
}
node->runtime->has_linked_inputs = false;
node->runtime->has_linked_outputs = false;
node->runtime->has_available_linked_inputs = false;
node->runtime->has_available_linked_outputs = false;
}
for (bNodeLink *link : tree_runtime.links) {
link->fromsock->runtime->directly_linked_links.append(link);
link->fromsock->runtime->directly_linked_sockets.append(link->tosock);
link->tosock->runtime->directly_linked_links.append(link);
link->fromnode->runtime->has_linked_outputs = true;
link->tonode->runtime->has_linked_inputs = true;
if (link->is_available()) {
link->fromnode->runtime->has_available_linked_outputs = true;
link->tonode->runtime->has_available_linked_inputs = true;
}
}
for (bNodeSocket *socket : tree_runtime.input_sockets) {
if (socket->flag & SOCK_MULTI_INPUT) {
@@ -168,7 +170,10 @@ static void find_logical_origins_for_socket_recursive(
links_to_check = links_to_check.take_front(1);
}
for (bNodeLink *link : links_to_check) {
if (link->flag & NODE_LINK_MUTED) {
if (link->is_muted()) {
continue;
}
if (!link->is_available()) {
continue;
}
bNodeSocket &origin_socket = *link->fromsock;
@@ -285,14 +290,20 @@ static void toposort_from_start_node(const ToposortDirection direction,
break;
}
bNodeSocket &socket = *sockets[item.socket_index];
const Span<bNodeSocket *> linked_sockets = socket.runtime->directly_linked_sockets;
if (item.link_index == linked_sockets.size()) {
const Span<bNodeLink *> linked_links = socket.runtime->directly_linked_links;
if (item.link_index == linked_links.size()) {
/* All links connected to this socket have already been visited. */
item.socket_index++;
item.link_index = 0;
continue;
}
bNodeSocket &linked_socket = *linked_sockets[item.link_index];
bNodeLink &link = *linked_links[item.link_index];
if (!link.is_available()) {
/* Ignore unavailable links. */
item.link_index++;
continue;
}
bNodeSocket &linked_socket = *socket.runtime->directly_linked_sockets[item.link_index];
bNode &linked_node = *linked_socket.runtime->owner_node;
ToposortNodeState &linked_node_state = node_states[linked_node.runtime->index_in_tree];
if (linked_node_state.is_done) {
@@ -337,8 +348,9 @@ static void update_toposort(const bNodeTree &ntree,
/* Ignore nodes that are done already. */
continue;
}
if ((direction == ToposortDirection::LeftToRight) ? node->runtime->has_linked_outputs :
node->runtime->has_linked_inputs) {
if ((direction == ToposortDirection::LeftToRight) ?
node->runtime->has_available_linked_outputs :
node->runtime->has_available_linked_inputs) {
/* Ignore non-start nodes. */
continue;
}
@@ -398,7 +410,7 @@ static void ensure_topology_cache(const bNodeTree &ntree)
update_toposort(ntree,
ToposortDirection::LeftToRight,
tree_runtime.toposort_left_to_right,
tree_runtime.has_link_cycle);
tree_runtime.has_available_link_cycle);
},
[&]() {
bool dummy;