Fix T101705: crash when connecting reroute to multi-input socket

Differential Revision: https://developer.blender.org/D16203
This commit is contained in:
Iliya Katueshenock 2022-10-17 12:00:09 +02:00 committed by Jacques Lucke
parent e5425b566d
commit a6b83617e9
Notes: blender-bot 2024-04-11 14:26:06 +02:00
Referenced by issue #101705, Regression: assert and crash on Connecting empty reroute node to multi socket
3 changed files with 43 additions and 32 deletions

View File

@ -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);

View File

@ -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<const bNodeLink *> 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)

View File

@ -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<const bNodeLink *> 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,