[Bf-committers] [Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25732] trunk/blender/source/blender/ editors/space_node: * Modifications to node editor 'make links' tool, after some requests by Soenke

Pablo Vazquez - www.venomgfx.com.ar venomgfx at gmail.com
Tue Jan 5 20:20:24 CET 2010


Thank you Matt!, I've been missing this one, we had it (simpler) back
in Plumiferos and I almost forgotten how useful it was, but is so much
better now, I love how it connects automatically per socket type.

Is there any plan to add the Ctrl + LMB/RMB to automatically connect
the active Viewer back? or any other implementation of it? without it
compositing workflow is so slow =/

Cheers!

* Pablo Vazquez
CG Artist
info at venomgfx.com.ar
http://www.venomgfx.com.ar



On Tue, Jan 5, 2010 at 07:49, Matt Ebb <matt at mke3.net> wrote:
> Revision: 25732
>          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25732
> Author:   broken
> Date:     2010-01-05 07:49:29 +0100 (Tue, 05 Jan 2010)
>
> Log Message:
> -----------
> * Modifications to node editor 'make links' tool, after some requests by Soenke
>
> Now it automatically decides how to connect the nodes up, based on the node positions. This lets you do fun stuff like in this video: http://www.vimeo.com/8548698
>
> Modified Paths:
> --------------
>    trunk/blender/source/blender/editors/space_node/node_edit.c
>    trunk/blender/source/blender/editors/space_node/node_header.c
>    trunk/blender/source/blender/editors/space_node/node_intern.h
>
> Modified: trunk/blender/source/blender/editors/space_node/node_edit.c
> ===================================================================
> --- trunk/blender/source/blender/editors/space_node/node_edit.c 2010-01-05 03:31:57 UTC (rev 25731)
> +++ trunk/blender/source/blender/editors/space_node/node_edit.c 2010-01-05 06:49:29 UTC (rev 25732)
> @@ -1353,95 +1353,155 @@
>
>  /* ****************** Add *********************** */
>
> -static bNodeSocket *get_next_outputsocket(bNodeSocket *sock, bNodeSocket **sockfrom, int totsock)
> +
> +typedef struct bNodeListItem {
> +       struct bNodeListItem *next, *prev;
> +       struct bNode *node;
> +} bNodeListItem;
> +
> +int sort_nodes_locx(void *a, void *b)
>  {
> -       int a;
> +       bNodeListItem *nli1 = (bNodeListItem *)a;
> +       bNodeListItem *nli2 = (bNodeListItem *)b;
> +       bNode *node1 = nli1->node;
> +       bNode *node2 = nli2->node;
>
> -       /* 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];
> -                       }
> +       if (node1->locx > node2->locx)
> +               return 1;
> +       else
> +               return 0;
> +}
> +
> +static int socket_is_available(bNodeTree *ntree, bNodeSocket *sock, int allow_used)
> +{
> +       if (sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))
> +               return 0;
> +
> +       if (!allow_used) {
> +               if (nodeCountSocketLinks(ntree, sock) > 0)
> +                       return 0;
> +       }
> +       return 1;
> +}
> +
> +static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple)
> +{
> +       bNodeSocket *sock;
> +
> +       /* first try to find a socket with a matching name */
> +       for (sock=node->outputs.first; sock; sock=sock->next) {
> +
> +               if (!socket_is_available(ntree, sock, allow_multiple))
> +                       continue;
> +
> +               /* check for same types */
> +               if (sock->type == sock_target->type) {
> +                       if (strcmp(sock->name, sock_target->name)==0)
> +                               return sock;
>                }
>        }
>
>        /* 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];
> -                       }
> +       for (sock=node->outputs.first; sock; sock=sock->next) {
> +
> +               if (!socket_is_available(ntree, sock, allow_multiple))
> +                       continue;
> +
> +               /* check for same types */
> +               if (sock->type == sock_target->type) {
> +                       return sock;
>                }
>        }
>
>        return NULL;
>  }
>
> -void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag, int replace)
> +/* this is a bit complicated, but designed to prioritise finding
> + * sockets of higher types, such as image, first */
> +static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
>  {
> -       bNodeSocket *sock, *sockfrom[8];
> -       bNode *node, *nodefrom[8];
> -       int totsock= 0, socktype=0;
> -
> -       if(node_to==NULL || node_to->inputs.first==NULL)
> -               return;
> -
> -       /* 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;
> +       bNodeSocket *sock;
> +       int socktype, maxtype=0;
> +       int a;
> +
> +       for (sock=node->inputs.first; sock; sock=sock->next) {
> +               maxtype = MAX2(sock->type, maxtype);
>        }
>
> -       /* find potential sockets, max 8 should work */
> -       for(node= snode->edittree->nodes.first; node; node= node->next) {
> -               if((node->flag & flag) && node!=node_to) {
> -                       for(sock= node->outputs.first; sock; sock= sock->next) {
> -                               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
> -                                       sockfrom[totsock]= sock;
> -                                       nodefrom[totsock]= node;
> -                                       totsock++;
> -                                       if(totsock>7)
> -                                               break;
> -                               }
> +       /* find sockets of higher 'types' first (i.e. image) */
> +       for (socktype=maxtype; socktype >= 0; socktype--) {
> +               for (sock=node->inputs.first; sock; sock=sock->next) {
> +
> +                       if (!socket_is_available(ntree, sock, replace)) {
> +                               a++;
> +                               continue;
>                        }
> +
> +                       if (sock->type == socktype) {
> +                               /* increment to make sure we don't keep finding
> +                                * the same socket on every attempt running this function */
> +                               a++;
> +                               if (a > num)
> +                                       return sock;
> +                       }
>                }
> -               if(totsock>7)
> -                       break;
>        }
> +
> +       return NULL;
> +}
>
> -       /* now just get matching socket types and create links */
> -       for(sock= node_to->inputs.first; sock; sock= sock->next) {
> -               bNodeSocket *sock_from;
> -               bNode *node_from;
> +void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace)
> +{
> +       ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
> +       bNodeListItem *nli;
> +       bNode *node;
> +       int i;
> +
> +       for(node= snode->edittree->nodes.first; node; node= node->next) {
> +               if(node->flag & NODE_SELECT) {
> +                       nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
> +                       nli->node = node;
> +                       BLI_addtail(nodelist, nli);
> +               }
> +       }
> +
> +       /* sort nodes left to right */
> +       BLI_sortlist(nodelist, sort_nodes_locx);
> +
> +       for (nli=nodelist->first; nli; nli=nli->next) {
> +               bNode *node_fr, *node_to;
> +               bNodeSocket *sock_fr, *sock_to;
>
> -               if (sock->type != socktype)
> -                       continue;
> +               if (nli->next == NULL) break;
>
> -               /* 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);
> +               node_fr = nli->node;
> +               node_to = nli->next->node;
>
> -               /* 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);
> +               /* check over input sockets first */
> +               for (i=0; i<BLI_countlist(&node_to->inputs); i++) {
> +
> +                       /* find the best guess input socket */
> +                       sock_to = best_socket_input(snode->edittree, node_to, i, replace);
> +                       if (!sock_to) continue;
> +
> +                       /* check for an appropriate output socket to connect from */
> +                       sock_fr = best_socket_output(snode->edittree, node_fr, sock_to, allow_multiple);
> +                       if (!sock_fr) continue;
> +
> +                       /* then we can connect */
> +                       if (replace)
> +                               nodeRemSocketLinks(snode->edittree, sock_to);
> +                       nodeAddLink(snode->edittree, node_fr, sock_fr, node_to, sock_to);
> +                       break;
>                }
> -               sock_from = NULL;
>        }
>
>        ntreeSolveOrder(snode->edittree);
> +
> +       BLI_freelistN(nodelist);
> +       MEM_freeN(nodelist);
>  }
>
> -
>  /* can be called from menus too, but they should do own undopush and redraws */
>  bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float locy)
>  {
> @@ -1781,53 +1841,10 @@
>  static int node_make_link_exec(bContext *C, wmOperator *op)
>  {
>        SpaceNode *snode= CTX_wm_space_node(C);
> -       bNode *fromnode, *tonode;
> -       bNodeLink *link;
> -       bNodeSocket *outsock= snode->edittree->selout;
> -       bNodeSocket *insock= snode->edittree->selin;
>        int replace = RNA_boolean_get(op->ptr, "replace");
> -
> -       if (!insock || !outsock) {
> -               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;
> -       }
>
> -       if (nodeFindNode(snode->edittree, outsock, &fromnode, NULL) &&
> -               nodeFindNode(snode->edittree, insock, &tonode, NULL))
> -       {
> -               link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock);
> -               NodeTagChanged(snode->edittree, tonode);
> -               node_remove_extra_links(snode, insock, link);
> -       }
> -       else
> -               return OPERATOR_CANCELLED;
> +       snode_autoconnect(snode, 0, replace);
>
> -       ntreeSolveOrder(snode->edittree);
>        node_tree_verify_groups(snode->nodetree);
>        snode_handle_recalc(C, snode);
>
>
> Modified: trunk/blender/source/blender/editors/space_node/node_header.c
> ===================================================================
> --- trunk/blender/source/blender/editors/space_node/node_header.c       2010-01-05 03:31:57 UTC (rev 25731)
> +++ trunk/blender/source/blender/editors/space_node/node_header.c       2010-01-05 06:49:29 UTC (rev 25732)
> @@ -78,8 +78,17 @@
>
>        node= node_add_node(snode, CTX_data_scene(C), event, snode->mx, snode->my);
>
> -       /* uses test flag */
> -       snode_autoconnect(snode, node, NODE_TEST, 0);
> +       /* select previous selection before autoconnect */
> +       for(node= snode->edittree->nodes.first; node; node= node->next) {
> +               if(node->flag & NODE_TEST) node->flag |= NODE_SELECT;
> +       }
> +
> +       snode_autoconnect(snode, 1, 0);
> +
> +       /* deselect after autoconnection */
> +       for(node= snode->edittree->nodes.first; node; node= node->next) {
> +               if(node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
> +       }
>
>        snode_handle_recalc(C, snode);
>  }
>
> Modified: trunk/blender/source/blender/editors/space_node/node_intern.h
> ===================================================================
> --- trunk/blender/source/blender/editors/space_node/node_intern.h       2010-01-05 03:31:57 UTC (rev 25731)
> +++ trunk/blender/source/blender/editors/space_node/node_intern.h       2010-01-05 06:49:29 UTC (rev 25732)
> @@ -81,7 +81,7 @@
>  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, int replace);
> +void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace);
>  int node_has_hidden_sockets(bNode *node);
>
>  void NODE_OT_duplicate(struct wmOperatorType *ot);
>
>
> _______________________________________________
> Bf-blender-cvs mailing list
> Bf-blender-cvs at blender.org
> http://lists.blender.org/mailman/listinfo/bf-blender-cvs
>


More information about the Bf-committers mailing list