* Tweaks for node editor Make Links (F key)
authorMatt Ebb <matt@mke3.net>
Mon, 4 Jan 2010 04:26:28 +0000 (04:26 +0000)
committerMatt Ebb <matt@mke3.net>
Mon, 4 Jan 2010 04:26:28 +0000 (04:26 +0000)
Testing a new method that hopefully will be faster to use than finicky socket
selection - now just select multiple nodes and press F - available output sockets
on the selected nodes will get automatically connected to the active node.

It works for one socket type each time, to avoid getting lots of extra connections
when you join up, but as a shortcut you can easily press F again to connect up
other socket types. For example, to connect a render layer node (with vector pass)
to a vector blur node, select the render layer then the vector blur, and press F
three times to connect up the Image, Z and Vector sockets. It now also
preferences sockets with the same name to connect up first.

There's also another option (ctrl F) which will replace existing input links, rather
than only connecting up links to available input sockets.

* Also changed socket link knife cut to a more convenient shortcut - Ctrl LMB tweak

release/scripts/ui/space_node.py
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_header.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_ops.c

index 9cf0a0c5ef3ec650316e36e675b08db45093d178..3dc26f49a6f20b015691e26ecb91574a561e2f8b 100644 (file)
@@ -120,6 +120,7 @@ class NODE_MT_node(bpy.types.Menu):
 
         layout.separator()
         layout.operator("node.link_make")
+        layout.operator("node.link_make", text="Make and Replace Links").replace=True
 
         layout.separator()
         layout.operator("node.group_edit")
index 3ed9ab8778e0b3fb897330a3462532c60bcbb9ca..8da732af2ddad3f7bf7e23a758b80288432dcd17 100644 (file)
@@ -174,6 +174,7 @@ struct bNode        *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int inte
 
 struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
 void                   nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
+void                   nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
 
 struct bNode   *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
 int                    nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
index 84ef4fb6d1c84a0f4636d1d7b1865ffecdc95027..b02225bd4299ab7138f393a4457ab755a27e91c0 100644 (file)
@@ -1063,6 +1063,18 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
        MEM_freeN(link);
 }
 
+void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
+{
+       bNodeLink *link, *next;
+       
+       for(link= ntree->links.first; link; link= next) {
+               next= link->next;
+               if(link->fromsock==sock || link->tosock==sock) {
+                       nodeRemLink(ntree, link);
+               }
+       }
+}
+
 
 bNodeTree *ntreeAddTree(int type)
 {
index f177e1a26224c7226ad5ec4ed2db30ec44b3d329..f2b3ed290678554889e5a1ca246b03a5bef84f8b 100644 (file)
@@ -1353,7 +1353,33 @@ static int node_socket_hilights(SpaceNode *snode, int in_out)
 
 /* ****************** Add *********************** */
 
-void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag)
+static bNodeSocket *get_next_outputsocket(bNodeSocket *sock, bNodeSocket **sockfrom, int totsock)
+{
+       int a;
+       
+       /* first try to find a sockets with matching name */
+       for (a=0; a<totsock; a++) {
+               if(sockfrom[a]) {
+                       if(sock->type==sockfrom[a]->type) {
+                               if (strcmp(sockfrom[a]->name, sock->name)==0)
+                                       return sockfrom[a];
+                       }
+               }
+       }
+       
+       /* otherwise settle for the first available socket of the right type */
+       for (a=0; a<totsock; a++) {
+               if(sockfrom[a]) {
+                       if(sock->type==sockfrom[a]->type) {
+                               return sockfrom[a];
+                       }
+               }
+       }
+       
+       return NULL;
+}
+
+void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag, int replace)
 {
        bNodeSocket *sock, *sockfrom[8];
        bNode *node, *nodefrom[8];
@@ -1361,14 +1387,14 @@ void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag)
 
        if(node_to==NULL || node_to->inputs.first==NULL)
                return;
-       
-       /* no inputs for node allowed (code it) */
 
-       /* connect first 1 socket type now */
-       for(sock= node_to->inputs.first; sock; sock= sock->next)
+       /* connect first 1 socket type or first available socket now */
+       for(sock= node_to->inputs.first; sock; sock= sock->next) {
+               if (!replace && nodeCountSocketLinks(snode->edittree, sock))
+                       continue;
                if(socktype<sock->type)
                        socktype= sock->type;
-
+       }
        
        /* find potential sockets, max 8 should work */
        for(node= snode->edittree->nodes.first; node; node= node->next) {
@@ -1389,17 +1415,27 @@ void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag)
 
        /* now just get matching socket types and create links */
        for(sock= node_to->inputs.first; sock; sock= sock->next) {
-               int a;
+               bNodeSocket *sock_from;
+               bNode *node_from;
                
-               for(a=0; a<totsock; a++) {
-                       if(sockfrom[a]) {
-                               if(sock->type==sockfrom[a]->type && sock->type==socktype) {
-                                       nodeAddLink(snode->edittree, nodefrom[a], sockfrom[a], node_to, sock);
-                                       sockfrom[a]= NULL;
-                                       break;
-                               }
-                       }
+               if (sock->type != socktype)
+                       continue;
+               
+               /* find a potential output socket and associated node */
+               sock_from = get_next_outputsocket(sock, sockfrom, totsock);
+               if (!sock_from)
+                       continue;
+               nodeFindNode(snode->edittree, sock_from, &node_from, NULL);
+               
+               /* then connect up the links */
+               if (replace) {
+                       nodeRemSocketLinks(snode->edittree, sock);
+                       nodeAddLink(snode->edittree, node_from, sock_from, node_to, sock);
+               } else {
+                       if (nodeCountSocketLinks(snode->edittree, sock)==0)
+                               nodeAddLink(snode->edittree, node_from, sock_from, node_to, sock);
                }
+               sock_from = NULL;
        }
        
        ntreeSolveOrder(snode->edittree);
@@ -1749,11 +1785,33 @@ static int node_make_link_exec(bContext *C, wmOperator *op)
        bNodeLink *link;
        bNodeSocket *outsock= snode->edittree->selout;
        bNodeSocket *insock= snode->edittree->selin;
+       int replace = RNA_boolean_get(op->ptr, "replace");
        
        if (!insock || !outsock) {
-               BKE_report(op->reports, RPT_ERROR, "No input or output socket(s) selected");
-               return OPERATOR_CANCELLED;
+               bNode *node;
+               
+               /* no socket selection, join nodes themselves, guessing connections */
+               tonode = nodeGetActive(snode->edittree);
+               
+               if (!tonode) {
+                       BKE_report(op->reports, RPT_ERROR, "No active node");
+                       return OPERATOR_CANCELLED;      
+               }
+               
+               /* store selection in temp test flag */
+               for(node= snode->edittree->nodes.first; node; node= node->next) {
+                       if(node->flag & NODE_SELECT) node->flag |= NODE_TEST;
+                       else node->flag &= ~NODE_TEST;
+               }
+               
+               snode_autoconnect(snode, tonode, NODE_TEST, replace);
+               node_tree_verify_groups(snode->nodetree);
+               snode_handle_recalc(C, snode);
+               
+               return OPERATOR_FINISHED;
        }
+       
+       
        if (nodeFindLink(snode->edittree, outsock, insock)) {
                BKE_report(op->reports, RPT_ERROR, "There is already a link between these sockets");
                return OPERATOR_CANCELLED;
@@ -1789,6 +1847,8 @@ void NODE_OT_link_make(wmOperatorType *ot)
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
 }
 
 /* ********************** Cut Link operator ***************** */
index 4cedbe3f6669e2984fda9e5ab105331d47a9ce17..6426856dfdd30fc700ed2d9db0152937ec469931 100644 (file)
@@ -79,7 +79,7 @@ static void do_node_add(bContext *C, void *arg, int event)
        node= node_add_node(snode, CTX_data_scene(C), event, snode->mx, snode->my);
        
        /* uses test flag */
-       snode_autoconnect(snode, node, NODE_TEST);
+       snode_autoconnect(snode, node, NODE_TEST, 0);
                
        snode_handle_recalc(C, snode);
 }
index 84729dd18ec169ca2e4dd4ccd9a462e66e018dba..ff88b4fde77150f9bc8c1688147ea349fec33641 100644 (file)
@@ -81,7 +81,7 @@ void node_deselectall(SpaceNode *snode);
 void snode_composite_job(const struct bContext *C, ScrArea *sa);
 bNode *node_tree_get_editgroup(bNodeTree *ntree);
 void node_tree_verify_groups(bNodeTree *nodetree);
-void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag);
+void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag, int replace);
 int node_has_hidden_sockets(bNode *node);
 
 void NODE_OT_duplicate(struct wmOperatorType *ot);
index 534ca0aa99ce035e4b41905956b798ee4a47e731..1bb38e9aad411fa2faaab8bb656b0fb3c5407151 100644 (file)
@@ -115,8 +115,9 @@ void node_keymap(struct wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0);
        
-       WM_keymap_add_item(keymap, "NODE_OT_links_cut", RIGHTMOUSE, KM_PRESS, KM_ALT, 0);
+       WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0);
+       RNA_boolean_set(WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "replace", 1);
        
        WM_keymap_add_menu(keymap, "NODE_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0);
        WM_keymap_add_item(keymap, "NODE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);