Fix #105601: Remove duplicates when inserting links into multi inputs #105631

Merged
Leon Schittek merged 3 commits from lone_noel/blender:fix-105601-multi-input-node-links into blender-v3.5-release 2023-03-11 08:28:07 +01:00
1 changed files with 49 additions and 28 deletions

View File

@ -898,27 +898,31 @@ static void displace_links(bNodeTree *ntree, const bNode *node, bNodeLink *inser
bNodeSocket *replacement_socket = node_find_linkable_socket(*ntree, node, linked_socket);
if (linked_socket->is_input()) {
if (linked_socket->limit + 1 < nodeSocketLinkLimit(linked_socket)) {
BLI_assert(!linked_socket->is_multi_input());
ntree->ensure_topology_cache();
bNodeLink *displaced_link = linked_socket->runtime->directly_linked_links.first();
if (!replacement_socket) {
nodeRemLink(ntree, displaced_link);
return;
lone_noel marked this conversation as resolved

The nodeRemLink function is already calling BKE_ntree_update_tag_link_removed

The `nodeRemLink` function is already calling `BKE_ntree_update_tag_link_removed`
Review

Good catch! That one slipped through the last review. :)

Good catch! That one slipped through the last review. :)
}
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->tosock == linked_socket) {
if (!replacement_socket) {
nodeRemLink(ntree, link);
BKE_ntree_update_tag_link_removed(ntree);
displaced_link->tosock = replacement_socket;
if (replacement_socket->is_multi_input()) {
/* Check for duplicate links when linking to multi input sockets. */
for (bNodeLink *existing_link : replacement_socket->runtime->directly_linked_links) {
if (existing_link->fromsock == displaced_link->fromsock) {
nodeRemLink(ntree, displaced_link);
return;
}
link->tosock = replacement_socket;
if (replacement_socket->is_multi_input()) {
link->multi_input_socket_index = node_socket_count_links(*ntree, *replacement_socket) -
1;
}
BKE_ntree_update_tag_link_changed(ntree);
return;
}
const int multi_input_index = node_socket_count_links(*ntree, *replacement_socket) - 1;
displaced_link->multi_input_socket_index = multi_input_index;
}
BKE_ntree_update_tag_link_changed(ntree);
return;
}
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
@ -976,29 +980,46 @@ static void node_remove_existing_links_if_needed(bNodeLinkDrag &nldrag, bNodeTre
{
bNodeSocket &linked_socket = *nldrag.hovered_socket;
const int link_count = node_socket_count_links(ntree, linked_socket);
int link_count = node_socket_count_links(ntree, linked_socket);
const int link_limit = nodeSocketLinkLimit(&linked_socket);
Set<bNodeLink *> links_to_remove;
if (link_count < link_limit) {
return;
}
ntree.ensure_topology_cache();
if (linked_socket.is_input()) {
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
if (link->tosock == &linked_socket) {
nodeRemLink(&ntree, link);
return;
/* Remove duplicate links first. */
for (const bNodeLink dragged_link : nldrag.links) {
if (linked_socket.is_input()) {
for (bNodeLink *link : linked_socket.runtime->directly_linked_links) {
const bool duplicate_link = link->fromsock == dragged_link.fromsock;
if (duplicate_link) {
links_to_remove.add(link);
link_count--;
}
}
}
else {
for (bNodeLink *link : linked_socket.runtime->directly_linked_links) {
const bool duplicate_link = link->tosock == dragged_link.tosock;
if (duplicate_link) {
links_to_remove.add(link);
link_count--;
}
}
}
}
else {
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree.links) {
if (link->fromsock == &linked_socket) {
nodeRemLink(&ntree, link);
return;
for (bNodeLink *link : linked_socket.runtime->directly_linked_links) {
const bool link_limit_exceeded = !(link_count < link_limit);
if (link_limit_exceeded) {
if (links_to_remove.add(link)) {
link_count--;
}
}
}
for (bNodeLink *link : links_to_remove) {
nodeRemLink(&ntree, link);
}
}
static void add_dragged_links_to_tree(bContext &C, bNodeLinkDrag &nldrag)