Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Toenne <lukas.toenne@googlemail.com>2012-06-01 16:38:03 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2012-06-01 16:38:03 +0400
commit17935168c07937f9b1d1db1874a9f7ba5d3ae540 (patch)
treef3240b63a6eb251254435878727091fe923002e7 /source/blender
parent5fbeda7efd62e251dac2af881de9fe042f30a7a7 (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.h6
-rw-r--r--source/blender/blenkernel/intern/node.c3
-rw-r--r--source/blender/editors/space_node/drawnode.c189
-rw-r--r--source/blender/editors/space_node/node_draw.c26
-rw-r--r--source/blender/editors/space_node/node_edit.c104
-rw-r--r--source/blender/editors/space_node/node_intern.h5
-rw-r--r--source/blender/editors/space_node/node_ops.c2
-rw-r--r--source/blender/editors/space_node/node_select.c29
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c4
-rw-r--r--source/blender/nodes/intern/node_common.c49
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c4
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c4
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);
}