[Bf-blender-cvs] [7f759ec] master: Node callback for handling link insertion and swapping of occupied inputs.
Lukas Tönne
noreply at git.blender.org
Thu Dec 3 13:04:23 CET 2015
Commit: 7f759ec547a563284f29f7a80b96316854b37ae5
Author: Lukas Tönne
Date: Thu Dec 3 12:51:29 2015 +0100
Branches: master
https://developer.blender.org/rB7f759ec547a563284f29f7a80b96316854b37ae5
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.
===================================================================
M source/blender/blenkernel/BKE_node.h
M source/blender/editors/space_node/node_relationships.c
M source/blender/makesrna/intern/rna_nodetree.c
M source/blender/nodes/composite/node_composite_util.c
M source/blender/nodes/composite/nodes/node_composite_common.c
M source/blender/nodes/intern/node_util.c
M source/blender/nodes/intern/node_util.h
M source/blender/nodes/shader/node_shader_util.c
M source/blender/nodes/shader/nodes/node_shader_common.c
M source/blender/nodes/texture/node_texture_util.c
M source/blender/nodes/texture/nodes/node_texture_common.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 08a5503..5d03a42 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -206,6 +206,8 @@ typedef struct bNodeType {
/* can this node be added to a node tree */
int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
+ /* optional handling of link insertion */
+ void (*insert_link)(struct bNodeTree *ntree, struct bNode *node, struct bNodeLink *link);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 8a808b2..f58cfe5 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);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e7e8f6d..51592ec 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1182,6 +1182,24 @@ static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
RNA_parameter_list_free(&list);
}
+static void rna_Node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
+{
+ extern FunctionRNA rna_Node_insert_link_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create((ID *)ntree, node->typeinfo->ext.srna, node, &ptr);
+ func = &rna_Node_insert_link_func;
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "link", &link);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
static void rna_Node_init(const bContext *C, PointerRNA *ptr)
{
extern FunctionRNA rna_Node_init_func;
@@ -1384,12 +1402,13 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc
nt->poll = (have_function[0]) ? rna_Node_poll : NULL;
nt->poll_instance = (have_function[1]) ? rna_Node_poll_instance : rna_Node_poll_instance_default;
nt->updatefunc = (have_function[2]) ? rna_Node_update_reg : NULL;
- nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
- nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
- nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
- nt->draw_buttons = (have_function[6]) ? rna_Node_draw_buttons : NULL;
- nt->draw_buttons_ex = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
- nt->labelfunc = (have_function[8]) ? rna_Node_draw_label : NULL;
+ nt->insert_link = (have_function[3]) ? rna_Node_insert_link : NULL;
+ nt->initfunc_api = (have_function[4]) ? rna_Node_init : NULL;
+ nt->copyfunc_api = (have_function[5]) ? rna_Node_copy : NULL;
+ nt->freefunc_api = (have_function[6]) ? rna_Node_free : NULL;
+ nt->draw_buttons = (have_function[7]) ? rna_Node_draw_buttons : NULL;
+ nt->draw_buttons_ex = (have_function[8]) ? rna_Node_draw_buttons_ext : NULL;
+ nt->labelfunc = (have_function[9]) ? rna_Node_draw_label : NULL;
/* sanitize size values in case not all have been registered */
if (nt->maxwidth < nt->minwidth)
@@ -7706,6 +7725,13 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Update on editor changes");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ /* insert_link */
+ func = RNA_def_function(srna, "insert_link", NULL);
+ RNA_def_function_ui_description(func, "Handle creation of a link to or from the node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "link", "NodeLink", "Link", "Node link that will be inserted");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
/* init */
func = RNA_def_function(srna, "init", NULL);
RNA_def_function_ui_description(func, "Initialize a new instance of this node");
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index bbfb07a..c6b1d37 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -55,5 +55,6 @@ void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short ncla
ntype->poll = cmp_node_poll_default;
ntype->updatefunc = cmp_node_update_default;
+ ntype->insert_link = node_insert_link_default;
ntype->update_internal_links = node_update_internal_links_default;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 75e7fa8..0fbbb54 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -51,6 +51,7 @@ void register_node_type_cmp_group(void)
ntype.type = NODE_GROUP;
ntype.poll = cmp_node_poll_default;
ntype.poll_instance = node_group_poll_instance;
+ ntype.insert_link = node_insert_link_default;
ntype.update_internal_links = node_update_internal_links_default;
ntype.ext.srna = RNA_struct_find("CompositorNodeGroup");
BLI_assert(ntype.ext.srna != NULL);
diff --git a/source/blender/nod
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list