Index: source/blender/blenkernel/BKE_node.h =================================================================== --- source/blender/blenkernel/BKE_node.h (revision 11098) +++ source/blender/blenkernel/BKE_node.h (working copy) @@ -143,11 +143,13 @@ void nodeAddToPreview(struct bNode *, float *, int, int); +void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeAddNodeType(struct bNodeTree *ntree, int type, struct bNodeTree *ngroup); void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node); struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); +struct bNodeLink *nodeAddLink2(struct bNodeTree *ntree, struct bNodeSocket *fromsock, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to); Index: source/blender/blenkernel/intern/node.c =================================================================== --- source/blender/blenkernel/intern/node.c (revision 11098) +++ source/blender/blenkernel/intern/node.c (working copy) @@ -843,6 +843,24 @@ return link; } +/* version without bNodes */ +bNodeLink *nodeAddLink2(bNodeTree *ntree, bNodeSocket *fromsock, bNodeSocket *tosock) +{ + bNode *fromnode, *tonode; + int index; /* just for find_node_with_socket */ + + /* figure out in which nodes sockets belong */ + find_node_with_socket(ntree, fromsock, &fromnode, &index); + printf("index: %d \n", index); + find_node_with_socket(ntree, tosock, &tonode, &index); + printf("index: %d \n", index); + + if(fromnode) printf("fromnode ok \n"); + if(tonode) printf("tonode ok \n"); + + return nodeAddLink(ntree, fromnode, fromsock, tonode, tosock); +} + void nodeRemLink(bNodeTree *ntree, bNodeLink *link) { BLI_remlink(&ntree->links, link); @@ -941,7 +959,7 @@ /* ************** Free stuff ********** */ /* goes over entire tree */ -static void node_unlink_node(bNodeTree *ntree, bNode *node) +void nodeUnlinkNode(bNodeTree *ntree, bNode *node) { bNodeLink *link, *next; bNodeSocket *sock; @@ -985,7 +1003,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) { - node_unlink_node(ntree, node); + nodeUnlinkNode(ntree, node); BLI_remlink(&ntree->nodes, node); /* since it is called while free database, node->id is undefined */ Index: source/blender/makesdna/DNA_node_types.h =================================================================== --- source/blender/makesdna/DNA_node_types.h (revision 11098) +++ source/blender/makesdna/DNA_node_types.h (working copy) @@ -92,7 +92,8 @@ #define SOCK_IN_USE 4 /* unavailable is for dynamic sockets */ #define SOCK_UNAVAIL 8 - + /* flag for selection status */ +#define SOCK_SEL 16 # # typedef struct bNodePreview { @@ -167,6 +168,10 @@ ListBase alltypes; /* type definitions */ struct bNodeType *owntype; /* for groups or dynamic trees, no read/write */ + /* selected input/output socket */ + bNodeSocket *selin; + bNodeSocket *selout; + /* callbacks */ void (*timecursor)(int nr); void (*stats_draw)(char *str); Index: source/blender/src/editnode.c =================================================================== --- source/blender/src/editnode.c (revision 11098) +++ source/blender/src/editnode.c (working copy) @@ -500,6 +500,23 @@ } } +/* returns 1 if one was found */ +static int node_get_active_viewer(SpaceNode *snode, bNode **actnode) +{ + bNode *node; + + for(node= snode->nodetree->nodes.first; node; node= node->next) { + if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if(node->flag & NODE_DO_OUTPUT) { + *actnode= node; + return 1; + } + } + } + + return 0; +} + void snode_make_group_editable(SpaceNode *snode, bNode *gnode) { bNode *node; @@ -826,6 +843,23 @@ window_set_cursor(win, oldcursor); } +static void reset_sel_socket(SpaceNode *snode, int in_out) +{ + bNode *node; + bNodeSocket *sock; + + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(in_out & SOCK_IN) { + for(sock= node->inputs.first; sock; sock= sock->next) + if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; + } + if(in_out & SOCK_OUT) { + for(sock= node->outputs.first; sock; sock= sock->next) + if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL; + } + } +} + /* checks mouse position, and returns found node/socket */ /* type is SOCK_IN and/or SOCK_OUT */ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out) @@ -1334,6 +1368,43 @@ return 0; } +/* in_out can be used to limit socket type to input or output */ +static int mouse_over_socket(SpaceNode *snode, int in_out, bNode **socknode, bNodeSocket **sockover) { + bNode *node; + bNodeSocket *sock, *tsock, *sockinsel= NULL, *sockoutsel= NULL; + float mx, my; + short mval[2]; + + if(snode->edittree==NULL) return 0; + + getmouseco_areawin(mval); + areamouseco_to_ipoco(G.v2d, mval, &mx, &my); + + for(node= snode->edittree->nodes.first; node; node= node->next) { + for(sock= node->inputs.first; sock; sock= sock->next) { + if(sock->flag & SELECT) sockinsel= sock; + } + for(sock= node->outputs.first; sock; sock= sock->next) { + if(sock->flag & SELECT) sockoutsel= sock; + } + } + + if(find_indicated_socket(snode, &node, &tsock, in_out)) { + if(tsock==sockinsel) { + *socknode= node; + *sockover= tsock; + return SOCK_IN; + } + if(tsock==sockoutsel) { + *socknode= node; + *sockover= tsock; + return SOCK_OUT; + } + } + + return 0; +} + static int node_socket_hilights(SpaceNode *snode, int in_out) { bNode *node; @@ -2047,8 +2118,12 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) { SpaceNode *snode= spacedata; + bNode *actnode, *socknode; + bNodeSocket *actsock; + bNodeLink *remlink; unsigned short event= evt->event; - short val= evt->val, doredraw=0, fromlib= 0; + short val= evt->val, doredraw=0, doendchecks=0, fromlib= 0; + char *undostr; if(sa->win==0) return; if(snode->nodetree==NULL) return; @@ -2074,7 +2149,29 @@ break; case RIGHTMOUSE: - if(!node_mouse_select(snode, event)) + if(find_indicated_socket(snode, &actnode, &actsock, SOCK_IN)) { + if(actsock->flag & SOCK_SEL) { + snode->edittree->selin= NULL; + actsock->flag&= ~SOCK_SEL; + } + else { + snode->edittree->selin= actsock; + reset_sel_socket(snode, SOCK_IN); + actsock->flag|= SOCK_SEL; + } + } + else if(find_indicated_socket(snode, &actnode, &actsock, SOCK_OUT)) { + if(actsock->flag & SOCK_SEL) { + snode->edittree->selout= NULL; + actsock->flag&= ~SOCK_SEL; + } + else { + snode->edittree->selout= actsock; + reset_sel_socket(snode, SOCK_OUT); + actsock->flag|= SOCK_SEL; + } + } + else if(!node_mouse_select(snode, event)) toolbox_n(); break; @@ -2150,6 +2247,17 @@ case EKEY: snode_handle_recalc(snode); break; + case FKEY: + if(snode->edittree->selin && snode->edittree->selout) { + remlink= nodeFindLink(snode->edittree, snode->edittree->selout, snode->edittree->selin); + + if(remlink) nodeRemLink(snode->edittree, remlink); + else nodeAddLink2(snode->edittree, snode->edittree->selout, snode->edittree->selin); + + undostr= "Toggle Link"; + doendchecks= 1; + } + break; case GKEY: if(fromlib) fromlib= -1; else { @@ -2181,6 +2289,20 @@ if(okee("Read saved Render Layers")) node_read_renderlayers(snode); break; + case VKEY: + if(mouse_over_socket(snode, SOCK_OUT, &socknode, &actsock)) { + if(node_get_active_viewer(snode, &actnode)) { + /* remove old connections of active viewer node. could handle better? */ + nodeUnlinkNode(snode->edittree, actnode); + + /* connect output socket to input of active viewer node */ + nodeAddLink(snode->edittree, socknode, actsock, actnode, actnode->inputs.first); + + undostr= "Connect to Active Viewer"; + doendchecks= 1; + } + } + break; case DELKEY: case XKEY: if(fromlib) fromlib= -1; @@ -2195,6 +2317,16 @@ scrarea_queue_winredraw(sa); if(doredraw==2) scrarea_queue_headredraw(sa); + if(doendchecks) { + node_get_active_viewer(snode, &actnode); + NodeTagChanged(snode->edittree, actnode); /* check for viewer */ + ntreeSolveOrder(snode->edittree); + snode_verify_groups(snode); + snode_handle_recalc(snode); + + allqueue(REDRAWNODE, 0); + BIF_undo_push(undostr); + } } Index: source/blender/src/drawnode.c =================================================================== --- source/blender/src/drawnode.c (revision 11098) +++ source/blender/src/drawnode.c (working copy) @@ -1750,7 +1750,7 @@ } /* nice AA filled circle */ -static void socket_circle_draw(float x, float y, float size, int type, int select) +static void socket_circle_draw(float x, float y, float size, int type, int col[3]) { /* 16 values of sin function */ static float si[16] = { @@ -1768,28 +1768,7 @@ }; int a; - if(select==0) { - if(type==-1) - glColor3ub(0, 0, 0); - else if(type==SOCK_VALUE) - glColor3ub(160, 160, 160); - else if(type==SOCK_VECTOR) - glColor3ub(100, 100, 200); - else if(type==SOCK_RGBA) - glColor3ub(200, 200, 40); - else - glColor3ub(100, 200, 100); - } - else { - if(type==SOCK_VALUE) - glColor3ub(200, 200, 200); - else if(type==SOCK_VECTOR) - glColor3ub(140, 140, 240); - else if(type==SOCK_RGBA) - glColor3ub(240, 240, 100); - else - glColor3ub(140, 240, 140); - } + glColor3ub(col[0], col[1], col[2]); glBegin(GL_POLYGON); for(a=0; a<16; a++) @@ -1807,6 +1786,40 @@ glDisable(GL_BLEND); } +/* wrapper for socket_circle_draw */ +static void socket_circle_draw_wrapper(bNodeSocket *sock, float size) +{ + int col[3]; + + /* choose color based on sock flags */ + if(sock->flag & SELECT) { + if(sock->type==SOCK_VALUE) { + col[0]= 200; col[1]= 200; col[2]= 200;} + else if(sock->type==SOCK_VECTOR) { + col[0]= 140; col[1]= 140; col[2]= 240;} + else if(sock->type==SOCK_RGBA) { + col[0]= 240; col[1]= 240; col[2]= 100;} + else { + col[0]= 140; col[1]= 240; col[2]= 140;} + } + else if(sock->flag & SOCK_SEL) { + col[0]= 255; col[1]= 160; col[2]= 0;} + else { + if(sock->type==-1) { + col[0]= 0; col[1]= 0; col[2]= 0;} + else if(sock->type==SOCK_VALUE) { + col[0]= 160; col[1]= 160; col[2]= 160;} + else if(sock->type==SOCK_VECTOR) { + col[0]= 100; col[1]= 100; col[2]= 200;} + else if(sock->type==SOCK_RGBA) { + col[0]= 200; col[1]= 200; col[2]= 40;} + else { + col[0]= 100; col[1]= 200; col[2]= 100;} + } + + socket_circle_draw(sock->locx, sock->locy, size, sock->type, col); +} + /* not a callback */ static void node_draw_preview(bNodePreview *preview, rctf *prv) { @@ -2214,7 +2227,7 @@ /* socket inputs, buttons */ for(sock= node->inputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); if(block && sock->link==NULL) { float *butpoin= sock->ns.vec; @@ -2256,7 +2269,7 @@ /* socket outputs */ for(sock= node->outputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); BIF_ThemeColor(TH_TEXT); ofs= 0; @@ -2344,12 +2357,12 @@ /* sockets */ for(sock= node->inputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); } for(sock= node->outputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); } } @@ -2560,10 +2573,10 @@ /* group sockets */ for(sock= gnode->inputs.first; sock; sock= sock->next) if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); for(sock= gnode->outputs.first; sock; sock= sock->next) if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + socket_circle_draw_wrapper(sock, NODE_SOCKSIZE); /* and finally the whole tree */ node_draw_nodetree(sa, snode, ngroup);