diff options
author | Lukas Toenne <lukas.toenne@googlemail.com> | 2012-06-01 16:38:03 +0400 |
---|---|---|
committer | Lukas Toenne <lukas.toenne@googlemail.com> | 2012-06-01 16:38:03 +0400 |
commit | 17935168c07937f9b1d1db1874a9f7ba5d3ae540 (patch) | |
tree | f3240b63a6eb251254435878727091fe923002e7 /source/blender | |
parent | 5fbeda7efd62e251dac2af881de9fe042f30a7a7 (diff) |
Reroute nodes, by Jeroen Bakker (patch #28443).
By holding shift and "cutting" a node link a new reroute helper node can be inserted. This consists of a single socket that can be used to insert additional connection points into a link. This can be used to keep a connection point in the tree when deleting a node, or to control the path of long connections for layout cleanup.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 189 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.c | 26 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 104 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_select.c | 29 | ||||
-rw-r--r-- | source/blender/nodes/composite/node_composite_tree.c | 4 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_common.c | 49 | ||||
-rw-r--r-- | source/blender/nodes/shader/node_shader_tree.c | 4 | ||||
-rw-r--r-- | source/blender/nodes/texture/node_texture_tree.c | 4 |
12 files changed, 388 insertions, 37 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 9eecca1686f..d093c9108b6 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -156,6 +156,10 @@ typedef struct bNodeType { const char *(*labelfunc)(struct bNode *); /// Optional custom resize handle polling. int (*resize_area_func)(struct bNode *node, int x, int y); + /// Optional selection area polling. + int (*select_area_func)(struct bNode *node, int x, int y); + /// Optional tweak area polling (for grabbing). + int (*tweak_area_func)(struct bNode *node, int x, int y); /// Called when the node is updated in the editor. void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node); @@ -434,6 +438,7 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibility); #define NODE_FORLOOP 3 #define NODE_WHILELOOP 4 #define NODE_FRAME 5 +#define NODE_REROUTE 6 /* look up a socket on a group node by the internal group socket */ struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock); @@ -449,6 +454,7 @@ int node_group_ungroup(struct bNodeTree *ntree, struct bNode *gnode); /* in node_common.c */ void register_node_type_frame(struct bNodeTreeType *ttype); +void register_node_type_reroute(struct bNodeTreeType *ttype); /* ************** SHADER NODES *************** */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 02d0ef5ea6a..22286e57c0a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1822,6 +1822,7 @@ void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype) static void registerCompositNodes(bNodeTreeType *ttype) { register_node_type_frame(ttype); + register_node_type_reroute(ttype); register_node_type_cmp_group(ttype); // register_node_type_cmp_forloop(ttype); @@ -1914,6 +1915,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) static void registerShaderNodes(bNodeTreeType *ttype) { register_node_type_frame(ttype); + register_node_type_reroute(ttype); register_node_type_sh_group(ttype); //register_node_type_sh_forloop(ttype); @@ -1986,6 +1988,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) static void registerTextureNodes(bNodeTreeType *ttype) { register_node_type_frame(ttype); + register_node_type_reroute(ttype); register_node_type_tex_group(ttype); // register_node_type_tex_forloop(ttype); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 676b1276569..0c4cf783eba 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -681,9 +681,9 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt /* node and group socket circles */ if (sock) - node_socket_circle_draw(ntree, sock, socket_size); + node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT); if (gsock) - node_socket_circle_draw(ngroup, gsock, socket_size); + node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT); /* socket name */ offset = (in_out == SOCK_IN ? col1 : cor3); @@ -1048,6 +1048,105 @@ static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(layout, ptr, "shrink", 0, "Shrink", ICON_NONE); } + +#define NODE_REROUTE_SIZE 8.0f + +static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *nsock; + float locx, locy; + float size = NODE_REROUTE_SIZE; + + /* get "global" coords */ + nodeToView(node, 0.0f, 0.0f, &locx, &locy); + + /* reroute node has exactly one input and one output, both in the same place */ + nsock= node->outputs.first; + nsock->locx= locx; + nsock->locy= locy; + + nsock= node->inputs.first; + nsock->locx= locx; + nsock->locy= locy; + + node->width = size*2; + node->totr.xmin= locx - size; + node->totr.xmax= locx + size; + node->totr.ymax= locy + size; + node->totr.ymin= locy - size; +} + +static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node) +{ + bNodeSocket *sock; + #if 0 /* UNUSED */ + rctf *rct= &node->totr; + float size = NODE_REROUTE_SIZE; + #endif + float socket_size= NODE_SOCKSIZE; + + /* skip if out of view */ + if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax || + node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) { + + uiEndBlock(C, node->block); + node->block= NULL; + return; + } + + /* XXX only kept for debugging + * selection state is indicated by socket outline below! + */ + #if 0 + /* body */ + uiSetRoundBox(15); + UI_ThemeColor4(TH_NODE); + glEnable(GL_BLEND); + uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); + glDisable(GL_BLEND); + + /* outline active and selected emphasis */ + if( node->flag & (NODE_ACTIVE|SELECT) ) { + glEnable(GL_BLEND); + glEnable( GL_LINE_SMOOTH ); + /* using different shades of TH_TEXT_HI for the empasis, like triangle */ + if( node->flag & NODE_ACTIVE ) + UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40); + else + UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120); + uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); + + glDisable( GL_LINE_SMOOTH ); + glDisable(GL_BLEND); + } + #endif + + /* only draw input socket. as they all are placed on the same position. + * highlight also if node itself is selected, since we don't display the node body separately! + */ + for(sock= node->inputs.first; sock; sock= sock->next) { + node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT)); + } + + uiEndBlock(C, node->block); + uiDrawBlock(C, node->block); + node->block= NULL; +} + +/* Special tweak area for reroute node. + * Since this node is quite small, we use a larger tweak area for grabbing than for selection. + */ +static int node_tweak_area_reroute(bNode *node, int x, int y) +{ + /* square of tweak radius */ + static const float tweak_radius_sq = 576; /* 24*24 */ + + bNodeSocket *sock = node->inputs.first; + float dx = sock->locx - x; + float dy = sock->locy - y; + return (dx*dx + dy*dy <= tweak_radius_sq); +} + static void node_common_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -1072,6 +1171,11 @@ static void node_common_set_butfunc(bNodeType *ntype) ntype->uifuncbut = node_buts_frame_details; ntype->resize_area_func = node_resize_area_frame; break; + case NODE_REROUTE: + ntype->drawfunc= node_draw_reroute; + ntype->drawupdatefunc= node_update_reroute; + ntype->tweak_area_func= node_tweak_area_reroute; + break; } } @@ -2653,6 +2757,8 @@ void ED_init_node_butfuncs(void) /* default ui functions */ ntype->drawfunc = node_draw_default; ntype->drawupdatefunc = node_update_default; + ntype->select_area_func = node_select_area_default; + ntype->tweak_area_func = node_tweak_area_default; ntype->uifunc = NULL; ntype->uifuncbut = NULL; ntype->drawinputfunc = node_draw_input_default; @@ -2847,36 +2953,61 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) { float dist, vec[4][2]; - + float deltax, deltay; + int toreroute, fromreroute; /* in v0 and v3 we put begin/end points */ if (link->fromsock) { vec[0][0] = link->fromsock->locx; vec[0][1] = link->fromsock->locy; + fromreroute = (link->fromnode && link->fromnode->type == NODE_REROUTE); } else { if (snode == NULL) return 0; vec[0][0] = snode->mx; vec[0][1] = snode->my; + fromreroute = 0; } if (link->tosock) { vec[3][0] = link->tosock->locx; vec[3][1] = link->tosock->locy; + toreroute = (link->tonode && link->tonode->type == NODE_REROUTE); } else { if (snode == NULL) return 0; vec[3][0] = snode->mx; vec[3][1] = snode->my; + toreroute = 0; } dist = UI_GetThemeValue(TH_NODE_CURVING) * 0.10f * ABS(vec[0][0] - vec[3][0]); - + deltax = vec[3][0] - vec[0][0]; + deltay = vec[3][1] - vec[0][1]; /* check direction later, for top sockets */ - vec[1][0] = vec[0][0] + dist; - vec[1][1] = vec[0][1]; - - vec[2][0] = vec[3][0] - dist; - vec[2][1] = vec[3][1]; - + if (fromreroute) { + if (ABS(deltax)>ABS(deltay)) { + vec[1][1]= vec[0][1]; + vec[1][0]= vec[0][0]+(deltax>0?dist:-dist); + } else { + vec[1][0]= vec[0][0]; + vec[1][1]= vec[0][1]+(deltay>0?dist:-dist); + } + } else { + vec[1][0] = vec[0][0] + dist; + vec[1][1] = vec[0][1]; + } + if (toreroute) { + if (ABS(deltax)>ABS(deltay)) { + vec[2][1]= vec[3][1]; + vec[2][0]= vec[3][0]+ (deltax>0?-dist:dist); + } else { + vec[2][0]= vec[3][0]; + vec[2][1]= vec[3][1]+(deltay>0?-dist:dist); + } + + } else { + vec[2][0] = vec[3][0] - dist; + vec[2][1] = vec[3][1]; + } if (v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) ; /* clipped */ else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) ; /* clipped */ else { @@ -2891,6 +3022,8 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa } #define LINK_RESOL 24 +#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */ +#define ARROW_SIZE 7 void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3) { float coord_array[LINK_RESOL + 1][2]; @@ -2898,9 +3031,10 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) { float dist, spline_step = 0.0f; int i; - + int drawarrow; /* store current linewidth */ float linew; + float arrow[2], arrow1[2], arrow2[2]; glGetFloatv(GL_LINE_WIDTH, &linew); /* we can reuse the dist variable here to increment the GL curve eval amount*/ @@ -2908,6 +3042,22 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t glEnable(GL_LINE_SMOOTH); + drawarrow = (link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE)); + if (drawarrow) { + // draw arrow in line segment LINK_ARROW + float dx, dy, len; + dx = coord_array[LINK_ARROW][0]-coord_array[LINK_ARROW-1][0]; + dy = coord_array[LINK_ARROW][1]-coord_array[LINK_ARROW-1][1]; + len = sqrtf(dx*dx+dy*dy); + dx = dx /len*ARROW_SIZE; + dy = dy /len*ARROW_SIZE; + arrow1[0] = coord_array[LINK_ARROW][0]-dx+dy; + arrow1[1] = coord_array[LINK_ARROW][1]-dy-dx; + arrow2[0] = coord_array[LINK_ARROW][0]-dx-dy; + arrow2[1] = coord_array[LINK_ARROW][1]-dy+dx; + arrow[0] = coord_array[LINK_ARROW][0]; + arrow[1] = coord_array[LINK_ARROW][1]; + } if (do_triple) { UI_ThemeColorShadeAlpha(th_col3, -80, -120); glLineWidth(4.0f); @@ -2917,6 +3067,14 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t glVertex2fv(coord_array[i]); } glEnd(); + if (drawarrow) { + glBegin(GL_LINE_STRIP); + glVertex2fv(arrow1); + glVertex2fv(arrow); + glVertex2fv(arrow); + glVertex2fv(arrow2); + glEnd(); + } } /* XXX using GL_LINES for shaded node lines is a workaround @@ -2946,6 +3104,15 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int t glEnd(); } + if (drawarrow) { + glBegin(GL_LINE_STRIP); + glVertex2fv(arrow1); + glVertex2fv(arrow); + glVertex2fv(arrow); + glVertex2fv(arrow2); + glEnd(); + } + glDisable(GL_LINE_SMOOTH); /* restore previuos linewidth */ diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 7011d605a7e..b623e21d9cd 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -46,6 +46,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_rect.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -81,7 +82,6 @@ /* width of socket columns in group display */ #define NODE_GROUP_FRAME 120 - // XXX interface.h extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select); @@ -496,6 +496,16 @@ void node_update_default(const bContext *C, bNodeTree *ntree, bNode *node) node_update_basis(C, ntree, node); } +int node_select_area_default(bNode *node, int x, int y) +{ + return BLI_in_rctf(&node->totr, x, y); +} + +int node_tweak_area_default(bNode *node, int x, int y) +{ + return BLI_in_rctf(&node->totr, x, y); +} + int node_get_colorid(bNode *node) { if (node->typeinfo->nclass==NODE_CLASS_INPUT) @@ -585,10 +595,10 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli glLineWidth(1.0f); } -void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size) +void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight) { bNodeSocketType *stype = ntreeGetSocketType(sock->type); - node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, (sock->flag & SELECT)); + node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight); } /* ************** Socket callbacks *********** */ @@ -819,7 +829,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (nodeSocketIsHidden(sock)) continue; - node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE); + node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT); node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name), sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY); @@ -830,7 +840,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (nodeSocketIsHidden(sock)) continue; - node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE); + node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT); node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name), sock->locx-node->width+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY); @@ -935,16 +945,16 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b dx-= snode->aspect; fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f); fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f); - + /* sockets */ for (sock= node->inputs.first; sock; sock= sock->next) { if (!nodeSocketIsHidden(sock)) - node_socket_circle_draw(snode->nodetree, sock, socket_size); + node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT); } for (sock= node->outputs.first; sock; sock= sock->next) { if (!nodeSocketIsHidden(sock)) - node_socket_circle_draw(snode->nodetree, sock, socket_size); + node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT); } uiEndBlock(C, node->block); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 595a9b444f0..1b229c78e0f 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1679,7 +1679,7 @@ int node_has_hidden_sockets(bNode *node) } void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) -{ +{ bNodeSocket *sock; if (set==0) { @@ -2749,14 +2749,110 @@ void NODE_OT_link_make(wmOperatorType *ot) RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links"); } -/* ********************** Cut Link operator ***************** */ - +/* ********************** Add reroute operator ***************** */ #define LINK_RESOL 12 +static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int tot, float result[2]) +{ + float coord_array[LINK_RESOL+1][2]; + int i, b; + + if(node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) { + + for(i=0; i<tot-1; i++) + for(b=0; b<LINK_RESOL; b++) + if(isect_line_line_v2(mcoords[i], mcoords[i+1], coord_array[b], coord_array[b+1]) > 0) { + result[0] = (mcoords[i][0]+mcoords[i+1][0])/2.0f; + result[1] = (mcoords[i][1]+mcoords[i+1][1])/2.0f; + return 1; + } + } + return 0; +} + +static int add_reroute_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode= CTX_wm_space_node(C); + ARegion *ar= CTX_wm_region(C); + float mcoords[256][2]; + int i= 0; + + RNA_BEGIN(op->ptr, itemptr, "path") { + float loc[2]; + + RNA_float_get_array(&itemptr, "loc", loc); + UI_view2d_region_to_view(&ar->v2d, (short)loc[0], (short)loc[1], + &mcoords[i][0], &mcoords[i][1]); + i++; + if(i>= 256) break; + } + RNA_END; + + if(i>1) { + bNodeLink *link; + float insertPoint[2]; + + ED_preview_kill_jobs(C); + + for(link= snode->edittree->links.first; link; link=link->next) { + if(add_reroute_intersect_check(link, mcoords, i, insertPoint)) { + bNodeTemplate ntemp; + bNode *rerouteNode; + + node_deselect_all(snode); + + ntemp.type = NODE_REROUTE; + rerouteNode = nodeAddNode(snode->edittree, &ntemp); + rerouteNode->locx = insertPoint[0]; + rerouteNode->locy = insertPoint[1]; + + nodeAddLink(snode->edittree, link->fromnode, link->fromsock, rerouteNode, rerouteNode->inputs.first); + link->fromnode = rerouteNode; + link->fromsock = rerouteNode->outputs.first; + + break; // add one reroute at the time. + } + } + + ntreeUpdateTree(snode->edittree); + snode_notify(C, snode); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; +} + +void NODE_OT_add_reroute(wmOperatorType *ot) +{ + PropertyRNA *prop; + + ot->name= "Add reroute"; + ot->idname= "NODE_OT_add_reroute"; + + ot->invoke= WM_gesture_lines_invoke; + ot->modal= WM_gesture_lines_modal; + ot->exec= add_reroute_exec; + ot->cancel= WM_gesture_lines_cancel; + + ot->poll= ED_operator_node_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); + /* internal */ + RNA_def_int(ot->srna, "cursor", BC_CROSSCURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); +} + + +/* ********************** Cut Link operator ***************** */ static int cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot) { float coord_array[LINK_RESOL+1][2]; int i, b; - + if (node_link_bezier_points(NULL, NULL, link, coord_array, LINK_RESOL)) { for (i=0; i<tot-1; i++) diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 60177192e2a..87f2ac74672 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -70,11 +70,13 @@ void node_menus_register(void); /* node_draw.c */ int node_get_colorid(struct bNode *node); -void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size); +void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight); int node_get_resize_cursor(int directions); void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius); void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node); void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); +int node_select_area_default(struct bNode *node, int x, int y); +int node_tweak_area_default(struct bNode *node, int x, int y); void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety); void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree); void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d); @@ -144,6 +146,7 @@ void NODE_OT_link(struct wmOperatorType *ot); void NODE_OT_link_make(struct wmOperatorType *ot); void NODE_OT_links_cut(struct wmOperatorType *ot); void NODE_OT_links_detach(struct wmOperatorType *ot); +void NODE_OT_add_reroute(struct wmOperatorType *ot); void NODE_OT_group_make(struct wmOperatorType *ot); void NODE_OT_group_ungroup(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 781a14fca59..8a977d2f112 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -79,6 +79,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_link_make); WM_operatortype_append(NODE_OT_links_cut); WM_operatortype_append(NODE_OT_links_detach); + WM_operatortype_append(NODE_OT_add_reroute); WM_operatortype_append(NODE_OT_group_make); WM_operatortype_append(NODE_OT_group_ungroup); @@ -218,6 +219,7 @@ void node_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "detach", TRUE); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 9098c8a4255..0a3678ca901 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -38,6 +38,7 @@ #include "BKE_context.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BLI_rect.h" #include "BLI_utildefines.h" @@ -58,14 +59,28 @@ /* ****** helpers ****** */ -static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my) +static bNode *node_under_mouse_select(bNodeTree *ntree, int mx, int my) { bNode *node; for (node=ntree->nodes.last; node; node=node->prev) { - /* node body (header and scale are in other operators) */ - if (BLI_in_rctf(&node->totr, mx, my)) - return node; + if (node->typeinfo->select_area_func) { + if (node->typeinfo->select_area_func(node, mx, my)) + return node; + } + } + return NULL; +} + +static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my) +{ + bNode *node; + + for(node=ntree->nodes.last; node; node=node->prev) { + if (node->typeinfo->tweak_area_func) { + if (node->typeinfo->tweak_area_func(node, mx, my)) + return node; + } } return NULL; } @@ -350,7 +365,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i } else { /* find the closest visible node */ - node = node_under_mouse(snode->edittree, mx, my); + node = node_under_mouse_select(snode->edittree, mx, my); if (node) { node_toggle(node); @@ -363,7 +378,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i else { /* extend==0 */ /* find the closest visible node */ - node = node_under_mouse(snode->edittree, mx, my); + node = node_under_mouse_select(snode->edittree, mx, my); if (node) { for (tnode=snode->edittree->nodes.first; tnode; tnode=tnode->next) @@ -490,7 +505,7 @@ static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my); - if (node_under_mouse(snode->edittree, mx, my)) + if (node_under_mouse_tweak(snode->edittree, mx, my)) return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; } diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 5bc2e1fc004..8f8f702e8ae 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -162,11 +162,11 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) } } - /* replace muted nodes by internal links */ + /* replace muted nodes and reroute nodes by internal links */ for (node= localtree->nodes.first; node; node= node_next) { node_next = node->next; - if (node->flag & NODE_MUTED) { + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { /* make sure the update tag isn't lost when removing the muted node. * propagate this to all downstream nodes. */ diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 48ffed80e41..9f458678ae0 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -835,3 +835,52 @@ void register_node_type_frame(bNodeTreeType *ttype) ntype->needs_free = 1; nodeRegisterType(ttype, ntype); } + + +/* **************** REROUTE ******************** */ + +static bNodeSocketTemplate node_reroute_in[]= { + { SOCK_RGBA, 1, "Input", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate node_reroute_out[]= { + { SOCK_RGBA, 0, "Output", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +/* simple, only a single input and output here */ +ListBase node_reroute_internal_connect(bNodeTree *ntree, bNode *node) +{ + bNodeLink *link; + ListBase ret; + + ret.first = ret.last = NULL; + + /* Security check! */ + if(!ntree) + return ret; + + link = MEM_callocN(sizeof(bNodeLink), "internal node link"); + link->fromnode = node; + link->fromsock = node->inputs.first; + link->tonode = node; + link->tosock = node->outputs.first; + /* internal link is always valid */ + link->flag |= NODE_LINK_VALID; + BLI_addtail(&ret, link); + + return ret; +} + +void register_node_type_reroute(bNodeTreeType *ttype) +{ + /* frame type is used for all tree types, needs dynamic allocation */ + bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type"); + + node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); + node_type_socket_templates(ntype, node_reroute_in, node_reroute_out); + node_type_internal_connect(ntype, node_reroute_internal_connect); + + ntype->needs_free = 1; + nodeRegisterType(ttype, ntype); +} diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 4794a66d064..a1d873231e7 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -99,11 +99,11 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) { bNode *node, *node_next; - /* replace muted nodes by internal links */ + /* replace muted nodes and reroute nodes by internal links */ for (node= localtree->nodes.first; node; node= node_next) { node_next = node->next; - if (node->flag & NODE_MUTED) { + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { nodeInternalRelink(localtree, node); nodeFreeNode(localtree, node); } diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index ba5682ee8ad..c84436a84b7 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -81,11 +81,11 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) { bNode *node, *node_next; - /* replace muted nodes by internal links */ + /* replace muted nodes and reroute nodes by internal links */ for (node= localtree->nodes.first; node; node= node_next) { node_next = node->next; - if (node->flag & NODE_MUTED) { + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { nodeInternalRelink(localtree, node); nodeFreeNode(localtree, node); } |