Fix #106235: use first non-dangling link of multi-input socket for internal link
Pull Request: https://projects.blender.org/blender/blender/pulls/119280
This commit is contained in:
committed by
Jacques Lucke
parent
c388ed1e53
commit
95810eec8f
@@ -616,6 +616,25 @@ class NodeTreeMainUpdater {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct InternalLink {
|
||||
bNodeSocket *from;
|
||||
bNodeSocket *to;
|
||||
int multi_input_socket_index = 0;
|
||||
|
||||
BLI_STRUCT_EQUALITY_OPERATORS_3(InternalLink, from, to, multi_input_socket_index);
|
||||
};
|
||||
|
||||
const bNodeLink *first_non_dangling_link(const bNodeTree &ntree,
|
||||
const Span<const bNodeLink *> links) const
|
||||
{
|
||||
for (const bNodeLink *link : links) {
|
||||
if (!bke::nodeIsDanglingReroute(&ntree, link->fromnode)) {
|
||||
return link;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void update_internal_links(bNodeTree &ntree)
|
||||
{
|
||||
bke::node_tree_runtime::AllowUsingOutdatedInfo allow_outdated_info{ntree};
|
||||
@@ -625,7 +644,7 @@ class NodeTreeMainUpdater {
|
||||
continue;
|
||||
}
|
||||
/* Find all expected internal links. */
|
||||
Vector<std::pair<bNodeSocket *, bNodeSocket *>> expected_internal_links;
|
||||
Vector<InternalLink> expected_internal_links;
|
||||
for (const bNodeSocket *output_socket : node->output_sockets()) {
|
||||
if (!output_socket->is_available()) {
|
||||
continue;
|
||||
@@ -637,31 +656,40 @@ class NodeTreeMainUpdater {
|
||||
continue;
|
||||
}
|
||||
const bNodeSocket *input_socket = this->find_internally_linked_input(output_socket);
|
||||
if (input_socket != nullptr) {
|
||||
expected_internal_links.append(
|
||||
{const_cast<bNodeSocket *>(input_socket), const_cast<bNodeSocket *>(output_socket)});
|
||||
if (input_socket == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Span<const bNodeLink *> connected_links = input_socket->directly_linked_links();
|
||||
const bNodeLink *connected_link = first_non_dangling_link(ntree, connected_links);
|
||||
|
||||
const int index = connected_link ? connected_link->multi_input_socket_index :
|
||||
std::max<int>(0, connected_links.size() - 1);
|
||||
expected_internal_links.append(InternalLink{const_cast<bNodeSocket *>(input_socket),
|
||||
const_cast<bNodeSocket *>(output_socket),
|
||||
index});
|
||||
}
|
||||
|
||||
/* Rebuilt internal links if they have changed. */
|
||||
if (node->runtime->internal_links.size() != expected_internal_links.size()) {
|
||||
this->update_internal_links_in_node(ntree, *node, expected_internal_links);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
for (auto &item : expected_internal_links) {
|
||||
const bNodeSocket *from_socket = item.first;
|
||||
const bNodeSocket *to_socket = item.second;
|
||||
bool found = false;
|
||||
for (const bNodeLink &internal_link : node->runtime->internal_links) {
|
||||
if (from_socket == internal_link.fromsock && to_socket == internal_link.tosock) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
this->update_internal_links_in_node(ntree, *node, expected_internal_links);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const bool all_expected_internal_links_exist = std::all_of(
|
||||
node->runtime->internal_links.begin(),
|
||||
node->runtime->internal_links.end(),
|
||||
[&](const bNodeLink &link) {
|
||||
const InternalLink internal_link{
|
||||
link.fromsock, link.tosock, link.multi_input_socket_index};
|
||||
return expected_internal_links.as_span().contains(internal_link);
|
||||
});
|
||||
|
||||
if (all_expected_internal_links_exist) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->update_internal_links_in_node(ntree, *node, expected_internal_links);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,18 +729,17 @@ class NodeTreeMainUpdater {
|
||||
|
||||
void update_internal_links_in_node(bNodeTree &ntree,
|
||||
bNode &node,
|
||||
Span<std::pair<bNodeSocket *, bNodeSocket *>> links)
|
||||
Span<InternalLink> internal_links)
|
||||
{
|
||||
node.runtime->internal_links.clear();
|
||||
node.runtime->internal_links.reserve(links.size());
|
||||
for (const auto &item : links) {
|
||||
bNodeSocket *from_socket = item.first;
|
||||
bNodeSocket *to_socket = item.second;
|
||||
node.runtime->internal_links.reserve(internal_links.size());
|
||||
for (const InternalLink &internal_link : internal_links) {
|
||||
bNodeLink link{};
|
||||
link.fromnode = &node;
|
||||
link.fromsock = from_socket;
|
||||
link.fromsock = internal_link.from;
|
||||
link.tonode = &node;
|
||||
link.tosock = to_socket;
|
||||
link.tosock = internal_link.to;
|
||||
link.multi_input_socket_index = internal_link.multi_input_socket_index;
|
||||
link.flag |= NODE_LINK_VALID;
|
||||
node.runtime->internal_links.append(link);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user