[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