Fix T88807: crash when there are multiple links between the same sockets

This commit does two things:

* Disallows creating more than one link from one socket to a multi socket input.
* Properly count links if there happen to be more than one link between the same sockets.

The new link counting should also be more efficient asymptotically.

Differential Revision: https://developer.blender.org/D11570
This commit is contained in:
Jacques Lucke 2021-06-14 10:04:32 +02:00 • committed by Jeroen Bakker
parent 4e14fe167d
commit 1fa73076ca
2 changed files with 27 additions and 18 deletions

View file

@ -82,6 +82,7 @@
# include "COM_compositor.h"
#endif
using blender::Map;
using blender::Set;
using blender::Span;
using blender::Vector;
@ -1767,26 +1768,27 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode)
{
Map<bNodeSocket *, int> counts;
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
if (link->tosock->flag & SOCK_MULTI_INPUT) {
int &count = counts.lookup_or_add(link->tosock, 0);
count++;
}
}
/* Count temporary links going into this socket. */
LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
bNodeLink *link = (bNodeLink *)linkdata->data;
if (link->tosock && (link->tosock->flag & SOCK_MULTI_INPUT)) {
int &count = counts.lookup_or_add(link->tosock, 0);
count++;
}
}
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
LISTBASE_FOREACH (struct bNodeSocket *, socket, &node->inputs) {
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
if (socket->flag & SOCK_MULTI_INPUT) {
Set<bNodeSocket *> visited_from_sockets;
socket->total_inputs = 0;
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
if (link->tosock == socket) {
visited_from_sockets.add(link->fromsock);
}
}
/* Count temporary links going into this socket. */
LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) {
LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) {
bNodeLink *link = (bNodeLink *)linkdata->data;
if (link->tosock == socket) {
visited_from_sockets.add(link->fromsock);
}
}
}
socket->total_inputs = visited_from_sockets.size();
socket->total_inputs = counts.lookup_default(socket, 0);
}
}
}

View file

@ -1223,6 +1223,13 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
if (nodeCountSocketLinks(ntree, tosock) + 1 > nodeSocketLinkLimit(tosock)) {
nodeRemSocketLinks(ntree, tosock);
}
if (tosock->flag & SOCK_MULTI_INPUT) {
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromsock == fromsock && link->tosock == tosock) {
nodeRemLink(ntree, link);
}
}
}
}
ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);