diff options
author | Charlie Jolly <charlie> | 2021-03-16 22:11:54 +0300 |
---|---|---|
committer | Charlie Jolly <mistajolly@gmail.com> | 2021-03-17 14:54:16 +0300 |
commit | 266cd7bb82ce4bfed20a3d61a84f25e2bacfca2b (patch) | |
tree | 963a983f902f5368669c1d93312b53262592e4dc /source/blender/editors/space_node | |
parent | 20bf736ff81c6fb79558796b74d50d4e7a9c8ef6 (diff) |
Nodes: Add support to mute node wires
This patch adds the ability to mute individual wires in the node editor.
This is invoked like the cut links operator but with a new shortcut.
Mute = Ctrl + Alt
Cut = Ctrl
Dragging over wires will toggle the mute state for that wire.
The muted wires are drawn in red with a bar across the center.
Red is used in the nodes context to indicate invalid links, muted links and internal links.
When a wire is muted it exposes the original node buttons which are normally hidden when a wire is connected.
Downstream and upstream links connected using reroute nodes are also muted.
Outside scope of patch:
- Add support for pynodes e.g. Animation Nodes
- Requires minor change to check for muted links using the `is_muted` link property or the `is_linked` socket property.
Maniphest Tasks: T52659
Differential Revision: https://developer.blender.org/D2807
Diffstat (limited to 'source/blender/editors/space_node')
-rw-r--r-- | source/blender/editors/space_node/drawnode.c | 53 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_relationships.c | 111 |
4 files changed, 155 insertions, 11 deletions
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0f2b2b435bc..1354c06305c 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3751,17 +3751,21 @@ bool node_link_bezier_points(const View2D *v2d, #define LINK_WIDTH (2.5f * UI_DPI_FAC) #define ARROW_SIZE (7 * UI_DPI_FAC) +/* Reroute arrow shape and mute bar. These are expanded here and shrunk in the glsl code. + * See: gpu_shader_2D_nodelink_vert.glsl */ static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}}; static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}}; +static float mute_verts[3][2] = {{0.7071f, 1.0f}, {0.7071f, 0.0f}, {0.7071f, -1.0f}}; +static float mute_expand_axis[3][2] = {{1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, -0.0f}}; static struct { GPUBatch *batch; /* for batching line together */ GPUBatch *batch_single; /* for single line */ GPUVertBuf *inst_vbo; uint p0_id, p1_id, p2_id, p3_id; - uint colid_id; + uint colid_id, muted_id; GPUVertBufRaw p0_step, p1_step, p2_step, p3_step; - GPUVertBufRaw colid_step; + GPUVertBufRaw colid_step, muted_step; uint count; bool enabled; } g_batch_link = {0}; @@ -3774,6 +3778,8 @@ static void nodelink_batch_reset(void) GPU_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step); GPU_vertbuf_attr_get_raw_data( g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step); + GPU_vertbuf_attr_get_raw_data( + g_batch_link.inst_vbo, g_batch_link.muted_id, &g_batch_link.muted_step); g_batch_link.count = 0; } @@ -3801,6 +3807,8 @@ static void nodelink_batch_init(void) int vcount = LINK_RESOL * 2; /* curve */ vcount += 2; /* restart strip */ vcount += 3 * 2; /* arrow */ + vcount += 2; /* restart strip */ + vcount += 3 * 2; /* mute */ vcount *= 2; /* shadow */ vcount += 2; /* restart strip */ GPU_vertbuf_data_alloc(vbo, vcount); @@ -3844,6 +3852,25 @@ static void nodelink_batch_init(void) } /* restart */ + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + + uv[0] = 127; + uv[1] = 0; + copy_v2_v2(pos, mute_verts[0]); + copy_v2_v2(exp, mute_expand_axis[0]); + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + /* bar */ + for (int i = 0; i < 3; ++i) { + uv[1] = 0; + copy_v2_v2(pos, mute_verts[i]); + copy_v2_v2(exp, mute_expand_axis[i]); + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + + uv[1] = 255; + set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); + } + + /* restart */ if (k == 0) { set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); } @@ -3867,6 +3894,8 @@ static void nodelink_batch_init(void) &format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); g_batch_link.colid_id = GPU_vertformat_attr_add( &format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT); + g_batch_link.muted_id = GPU_vertformat_attr_add( + &format_inst, "domuted", GPU_COMP_U8, 2, GPU_FETCH_INT); g_batch_link.inst_vbo = GPU_vertbuf_create_with_format_ex(&format_inst, GPU_USAGE_STREAM); /* Alloc max count but only draw the range we need. */ GPU_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); @@ -3941,12 +3970,13 @@ static void nodelink_batch_add_link(const SpaceNode *snode, int th_col1, int th_col2, int th_col3, - bool drawarrow) + bool drawarrow, + bool drawmuted) { /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */ BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT)); - BLI_assert(ELEM(th_col3, TH_WIRE, -1)); + BLI_assert(ELEM(th_col3, TH_WIRE, TH_REDALERT, -1)); g_batch_link.count++; copy_v2_v2(GPU_vertbuf_raw_step(&g_batch_link.p0_step), p0); @@ -3958,6 +3988,8 @@ static void nodelink_batch_add_link(const SpaceNode *snode, colid[1] = nodelink_get_color_id(th_col2); colid[2] = nodelink_get_color_id(th_col3); colid[3] = drawarrow; + char *muted = GPU_vertbuf_raw_step(&g_batch_link.muted_step); + muted[0] = drawmuted; if (g_batch_link.count == NODELINK_GROUP_SIZE) { nodelink_batch_draw(snode); @@ -3977,7 +4009,7 @@ void node_draw_link_bezier(const View2D *v2d, if (node_link_bezier_handles(v2d, snode, link, vec)) { int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE))); - + int drawmuted = (link->flag & NODE_LINK_MUTED); if (g_batch_link.batch == NULL) { nodelink_batch_init(); } @@ -3985,7 +4017,7 @@ void node_draw_link_bezier(const View2D *v2d, if (g_batch_link.enabled && !highlighted) { /* Add link to batch. */ nodelink_batch_add_link( - snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow); + snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow, drawmuted); } else { /* Draw single link. */ @@ -4009,6 +4041,7 @@ void node_draw_link_bezier(const View2D *v2d, GPU_batch_uniform_1f(batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); GPU_batch_uniform_1i(batch, "doArrow", drawarrow); + GPU_batch_uniform_1i(batch, "doMuted", drawmuted); GPU_batch_draw(batch); } } @@ -4041,8 +4074,11 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) if (link->flag & NODE_LINKFLAG_HILITE) { th_col1 = th_col2 = TH_ACTIVE; } + else if (link->flag & NODE_LINK_MUTED) { + th_col1 = th_col2 = TH_REDALERT; + } else { - /* regular link */ + /* Regular link, highlight if connected to selected node. */ if (link->fromnode && link->fromnode->flag & SELECT) { th_col1 = TH_EDGE_SELECT; } @@ -4052,7 +4088,8 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) } } else { - th_col1 = th_col2 = TH_REDALERT; + /* Invalid link. */ + th_col1 = th_col2 = th_col3 = TH_REDALERT; // th_col3 = -1; /* no shadow */ } } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 1840ec93f6f..21a36ff9683 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -234,6 +234,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_links_mute(struct wmOperatorType *ot); void NODE_OT_parent_set(struct wmOperatorType *ot); void NODE_OT_join(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index ef28cfe8a8b..e35b444aa11 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -68,6 +68,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_links_mute); WM_operatortype_append(NODE_OT_add_reroute); WM_operatortype_append(NODE_OT_group_make); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ee07ec7a55c..2cc44d72c72 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -1227,8 +1227,8 @@ void NODE_OT_link_make(wmOperatorType *ot) ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links"); } -/* ********************** Cut Link operator ***************** */ -static bool cut_links_intersect(bNodeLink *link, const float mcoords[][2], int tot) +/* ********************** Node Link Intersect ***************** */ +static bool node_links_intersect(bNodeLink *link, const float mcoords[][2], int tot) { float coord_array[NODE_LINK_RESOL + 1][2]; @@ -1244,6 +1244,7 @@ static bool cut_links_intersect(bNodeLink *link, const float mcoords[][2], int t return 0; } +/* ********************** Cut Link operator ***************** */ static int cut_links_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1276,7 +1277,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) continue; } - if (cut_links_intersect(link, mcoords, i)) { + if (node_links_intersect(link, mcoords, i)) { if (found == false) { /* TODO(sergey): Why did we kill jobs twice? */ @@ -1335,6 +1336,110 @@ void NODE_OT_links_cut(wmOperatorType *ot) RNA_def_int(ot->srna, "cursor", WM_CURSOR_KNIFE, 0, INT_MAX, "Cursor", "", 0, INT_MAX); } +/* ********************** Mute links operator ***************** */ + +static int mute_links_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + SpaceNode *snode = CTX_wm_space_node(C); + ARegion *region = CTX_wm_region(C); + bool do_tag_update = false; + + int i = 0; + float mcoords[256][2]; + RNA_BEGIN (op->ptr, itemptr, "path") { + float loc[2]; + + RNA_float_get_array(&itemptr, "loc", loc); + UI_view2d_region_to_view( + ®ion->v2d, (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]); + i++; + if (i >= 256) { + break; + } + } + RNA_END; + + if (i > 1) { + ED_preview_kill_jobs(CTX_wm_manager(C), bmain); + + /* Count intersected links and clear test flag. */ + int tot = 0; + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (nodeLinkIsHidden(link)) { + continue; + } + link->flag &= ~NODE_LINK_TEST; + if (node_links_intersect(link, mcoords, i)) { + tot++; + } + } + if (tot == 0) { + return OPERATOR_CANCELLED; + } + + /* Mute links. */ + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (nodeLinkIsHidden(link) || (link->flag & NODE_LINK_TEST)) { + continue; + } + + if (node_links_intersect(link, mcoords, i)) { + do_tag_update |= (do_tag_update || + node_connected_to_output(bmain, snode->edittree, link->tonode)); + + snode_update(snode, link->tonode); + nodeMuteLinkToggle(snode->edittree, link); + } + } + + /* Clear remaining test flags. */ + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (nodeLinkIsHidden(link)) { + continue; + } + link->flag &= ~NODE_LINK_TEST; + } + + do_tag_update |= ED_node_is_geometry(snode); + + ntreeUpdateTree(CTX_data_main(C), snode->edittree); + snode_notify(C, snode); + if (do_tag_update) { + snode_dag_update(C, snode); + } + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; +} + +void NODE_OT_links_mute(wmOperatorType *ot) +{ + ot->name = "Mute Links"; + ot->idname = "NODE_OT_links_mute"; + ot->description = "Use the mouse to mute links"; + + ot->invoke = WM_gesture_lines_invoke; + ot->modal = WM_gesture_lines_modal; + ot->exec = mute_links_exec; + ot->cancel = WM_gesture_lines_cancel; + + ot->poll = ED_operator_node_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + /* internal */ + RNA_def_int(ot->srna, "cursor", WM_CURSOR_MUTE, 0, INT_MAX, "Cursor", "", 0, INT_MAX); +} + /* ********************** Detach links operator ***************** */ static int detach_links_exec(bContext *C, wmOperator *UNUSED(op)) |