diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2015-12-03 14:51:29 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-12-03 15:04:04 +0300 |
commit | 7f759ec547a563284f29f7a80b96316854b37ae5 (patch) | |
tree | 2205f1a7d6c8a7f31691b227858ad165be070dde /source/blender/editors/space_node/node_relationships.c | |
parent | 762aad37779e9e0654b4746df35710f850438329 (diff) |
Node callback for handling link insertion and swapping of occupied inputs.
Nodes have a feature for moving existing links to unoccupied sockets when connecting
to an already used input. This is based on the standard legacy socket types (value/float,
vector, color/rgba) and works reasonably well for shader, compositor and texture nodes.
For new pynode systems, however, the hardcoded nature of that feature has major drawbacks:
* It does not take different type systems into account, leading to meaningless connections
when sockets are swapped and making the feature useless or outright debilitating.
* Advanced socket behaviors would be possible with a registerable callback, e.g. creating
extensible input lists that move existing connections down to make room for a new link.
Now any handling of new links is done via the 'insert_links' callback, which can also be
registered through the RNA API. For the legacy shader/compo/tex nodes the behavior is the
same, using a C callback.
Note on the 'use_swap' flag: this has been removed because it was meaningless anyway:
It was disabled only for the insert-node-on-link feature, which works only for
completely unconnected nodes anyway, so there would be nothing to swap in the first place.
Diffstat (limited to 'source/blender/editors/space_node/node_relationships.c')
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 90 |
1 files changed, 17 insertions, 73 deletions
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 8a808b2ae9d..f58cfe55f34 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -29,8 +29,6 @@ * \ingroup spnode */ -#include <ctype.h> - #include "MEM_guardedalloc.h" #include "DNA_node_types.h" @@ -420,7 +418,6 @@ static void node_link_update_header(bContext *C, bNodeLinkDrag *UNUSED(nldrag)) #undef HEADER_LENGTH } -/* update link_count fields to avoid repeated link counting */ static int node_count_links(bNodeTree *ntree, bNodeSocket *sock) { bNodeLink *link; @@ -434,64 +431,13 @@ static int node_count_links(bNodeTree *ntree, bNodeSocket *sock) return count; } -/* test if two sockets are interchangeable - * XXX this could be made into a tree-type callback for flexibility - */ -static bool node_link_socket_match(bNodeSocket *a, bNodeSocket *b) -{ - /* tests if alphabetic prefix matches - * this allows for imperfect matches, such as numeric suffixes, - * like Color1/Color2 - */ - int prefix_len = 0; - char *ca = a->name, *cb = b->name; - for (; *ca != '\0' && *cb != '\0'; ++ca, ++cb) { - /* end of common prefix? */ - if (*ca != *cb) { - /* prefix delimited by non-alphabetic char */ - if (isalpha(*ca) || isalpha(*cb)) - return false; - break; - } - ++prefix_len; - } - return prefix_len > 0; -} - -/* find an eligible socket for linking */ -static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree, bNode *node, bNodeSocket *cur, bool use_swap) -{ - int cur_link_count = node_count_links(ntree, cur); - if (cur_link_count <= cur->limit) { - /* current socket is fine, use it */ - return cur; - } - else if (use_swap) { - /* link swapping: try to find a free slot with a matching name */ - - bNodeSocket *first = cur->in_out == SOCK_IN ? node->inputs.first : node->outputs.first; - bNodeSocket *sock; - - sock = cur->next ? cur->next : first; /* wrap around the list end */ - while (sock != cur) { - if (!nodeSocketIsHidden(sock) && node_link_socket_match(sock, cur)) { - int link_count = node_count_links(ntree, sock); - /* take +1 into account since we would add a new link */ - if (link_count + 1 <= sock->limit) - return sock; /* found a valid free socket we can swap to */ - } - - sock = sock->next ? sock->next : first; /* wrap around the list end */ - } - } - return NULL; -} - -static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link, bool use_swap) +static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) { bNodeTree *ntree = snode->edittree; bNodeSocket *from = link->fromsock, *to = link->tosock; bNodeLink *tlink, *tlink_next; + int to_count = node_count_links(ntree, to); + int from_count = node_count_links(ntree, from); for (tlink = ntree->links.first; tlink; tlink = tlink_next) { tlink_next = tlink->next; @@ -499,28 +445,18 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link, bool use_ continue; if (tlink && tlink->fromsock == from) { - bNodeSocket *new_from = node_find_linkable_socket(ntree, tlink->fromnode, from, use_swap); - if (new_from && new_from != from) { - /* redirect existing link */ - tlink->fromsock = new_from; - } - else if (!new_from) { - /* no possible replacement, remove tlink */ + if (from_count > from->limit) { nodeRemLink(ntree, tlink); tlink = NULL; + --from_count; } } if (tlink && tlink->tosock == to) { - bNodeSocket *new_to = node_find_linkable_socket(ntree, tlink->tonode, to, use_swap); - if (new_to && new_to != to) { - /* redirect existing link */ - tlink->tosock = new_to; - } - else if (!new_to) { - /* no possible replacement, remove tlink */ + if (to_count > to->limit) { nodeRemLink(ntree, tlink); tlink = NULL; + --to_count; } } } @@ -537,6 +473,14 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) bNodeLink *link = linkdata->data; if (apply_links && link->tosock && link->fromsock) { + /* before actually adding the link, + * let nodes perform special link insertion handling + */ + if (link->fromnode->typeinfo->insert_link) + link->fromnode->typeinfo->insert_link(ntree, link->fromnode, link); + if (link->tonode->typeinfo->insert_link) + link->tonode->typeinfo->insert_link(ntree, link->tonode, link); + /* add link to the node tree */ BLI_addtail(&ntree->links, link); @@ -546,7 +490,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) link->tonode->update |= NODE_UPDATE; /* we might need to remove a link */ - node_remove_extra_links(snode, link, true); + node_remove_extra_links(snode, link); } else nodeRemLink(ntree, link); @@ -1746,7 +1690,7 @@ void ED_node_link_insert(ScrArea *sa) link->tonode = select; link->tosock = best_input; - node_remove_extra_links(snode, link, false); + node_remove_extra_links(snode, link); link->flag &= ~NODE_LINKFLAG_HILITE; nodeAddLink(snode->edittree, select, best_output, node, sockto); |