From a6b83617e9de01c3a4719770f88fc0ad2933e55a Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Mon, 17 Oct 2022 12:00:09 +0200 Subject: Fix T101705: crash when connecting reroute to multi-input socket Differential Revision: https://developer.blender.org/D16203 --- source/blender/blenkernel/BKE_node.h | 6 ++++ source/blender/blenkernel/intern/node.cc | 32 +++++++++++++++++++ .../nodes/intern/geometry_nodes_lazy_function.cc | 37 +++------------------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b1b4045370c..ecf7a556459 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -792,6 +792,12 @@ void nodeChainIterBackwards(const bNodeTree *ntree, */ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata); +/** + * A dangling reroute node is a reroute node that does *not* have a "data source", i.e. no + * non-reroute node is connected to its input. + */ +bool nodeIsDanglingReroute(const struct bNodeTree *ntree, const struct bNode *node); + struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, const struct bNodeSocket *from, const struct bNodeSocket *to); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 654eb06a781..8028f990c42 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -2157,6 +2157,38 @@ void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userd } } +bool nodeIsDanglingReroute(const bNodeTree *ntree, const bNode *node) +{ + ntree->ensure_topology_cache(); + BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*ntree)); + BLI_assert(!ntree->has_available_link_cycle()); + + const bNode *iter_node = node; + if (!iter_node->is_reroute()) { + return false; + } + + while (true) { + const blender::Span links = + iter_node->input_socket(0).directly_linked_links(); + BLI_assert(links.size() <= 1); + if (links.is_empty()) { + return true; + } + const bNodeLink &link = *links[0]; + if (!link.is_available()) { + return false; + } + if (link.is_muted()) { + return false; + } + iter_node = link.fromnode; + if (!iter_node->is_reroute()) { + return false; + } + } +} + /* ************** Add stuff ********** */ void nodeUniqueName(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 6475a16477a..5bf245f1832 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -158,8 +158,9 @@ class LazyFunctionForMultiInput : public LazyFunction { base_type_ = get_socket_cpp_type(socket); BLI_assert(base_type_ != nullptr); BLI_assert(socket.is_multi_input()); + const bNodeTree &btree = socket.owner_tree(); for (const bNodeLink *link : socket.directly_linked_links()) { - if (!link->is_muted()) { + if (!(link->is_muted() || nodeIsDanglingReroute(&btree, link->fromnode))) { inputs_.append({"Input", *base_type_}); } } @@ -1073,9 +1074,7 @@ struct GeometryNodesLazyFunctionGraphBuilder { void insert_links_from_socket(const bNodeSocket &from_bsocket, lf::OutputSocket &from_lf_socket) { - const bNode &from_bnode = from_bsocket.owner_node(); - if (this->is_dangling_reroute_input(from_bnode)) { - /* Dangling reroutes should not be used as source of values. */ + if (nodeIsDanglingReroute(&btree_, &from_bsocket.owner_node())) { return; } @@ -1145,7 +1144,8 @@ struct GeometryNodesLazyFunctionGraphBuilder { if (multi_input_link == link) { break; } - if (!multi_input_link->is_muted()) { + if (!(multi_input_link->is_muted() || + nodeIsDanglingReroute(&btree_, multi_input_link->fromnode))) { link_index++; } } @@ -1174,33 +1174,6 @@ struct GeometryNodesLazyFunctionGraphBuilder { } } - bool is_dangling_reroute_input(const bNode &node) - { - if (!node.is_reroute()) { - return false; - } - const bNode *iter_node = &node; - /* It is guaranteed at a higher level that there are no link cycles. */ - while (true) { - const Span links = iter_node->input_socket(0).directly_linked_links(); - BLI_assert(links.size() <= 1); - if (links.is_empty()) { - return true; - } - const bNodeLink &link = *links[0]; - if (!link.is_available()) { - return false; - } - if (link.is_muted()) { - return false; - } - iter_node = link.fromnode; - if (!iter_node->is_reroute()) { - return false; - } - } - } - lf::OutputSocket *insert_type_conversion_if_necessary( lf::OutputSocket &from_socket, const CPPType &to_type, -- cgit v1.2.3