diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index a1ab5277744..72328333732 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -1234,7 +1234,8 @@ static void add_nodes(Scene *scene, for (BL::NodeLink &b_link : b_ntree.links) { /* Ignore invalid links to avoid unwanted cycles created in graph. * Also ignore links with unavailable sockets. */ - if (!(b_link.is_valid() && b_link.from_socket().enabled() && b_link.to_socket().enabled())) { + if (!(b_link.is_valid() && b_link.from_socket().enabled() && b_link.to_socket().enabled()) || + b_link.is_muted()) { continue; } /* get blender link data */ diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 3471a8d0db0..feba4e3bd09 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -1844,6 +1844,7 @@ def km_node_editor(params): ("node.resize", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None), ("node.add_reroute", {"type": 'EVT_TWEAK_L' if params.legacy else 'EVT_TWEAK_R', "value": 'ANY', "shift": True}, None), ("node.links_cut", {"type": 'EVT_TWEAK_L' if params.legacy else 'EVT_TWEAK_R', "value": 'ANY', "ctrl": True}, None), + ("node.links_mute", {"type": 'EVT_TWEAK_R', "value": 'ANY', "ctrl": True, "alt": True}, None), ("node.select_link_viewer", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("node.backimage_move", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None), ("node.backimage_zoom", {"type": 'V', "value": 'PRESS', "repeat": True}, diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index c8fc6abe10a..91f153a0f42 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -1113,6 +1113,7 @@ def km_node_editor(params): ("node.resize", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None), ("node.add_reroute", {"type": params.action_tweak, "value": 'ANY', "shift": True}, None), ("node.links_cut", {"type": params.action_tweak, "value": 'ANY', "ctrl": True}, None), + ("node.links_mute", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None), ("node.select_link_viewer", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True, "ctrl": True}, None), ("node.backimage_fit", {"type": 'A', "value": 'PRESS', "alt": True}, None), ("node.backimage_sample", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, None), diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index a9934850acd..7f66cdd3d74 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -331,6 +331,7 @@ class NODE_MT_node(Menu): layout.operator("node.link_make", text="Make and Replace Links").replace = True layout.operator("node.links_cut") layout.operator("node.links_detach") + layout.operator("node.links_mute") layout.separator() diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index ced76e65ada..04a9855de68 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -627,6 +627,7 @@ struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); +void nodeMuteLinkToggle(struct bNodeTree *ntree, struct bNodeLink *link); bool nodeLinkIsHidden(const struct bNodeLink *link); void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index bbc655d7fc8..ca973bd9d65 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -107,6 +107,9 @@ static void node_free_node(bNodeTree *ntree, bNode *node); static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock, const bool do_id_user); +static void nodeMuteRerouteOutputLinks(struct bNodeTree *ntree, + struct bNode *node, + const bool mute); static void ntree_init_data(ID *id) { @@ -2215,6 +2218,106 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link) } } +/* Check if all output links are muted or not. */ +static bool nodeMuteFromSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock) +{ + int tot = 0; + int muted = 0; + LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) { + if (link->fromsock == sock) { + tot++; + if (link->flag & NODE_LINK_MUTED) { + muted++; + } + } + } + return tot == muted; +} + +static void nodeMuteLink(bNodeLink *link) +{ + link->flag |= NODE_LINK_MUTED; + link->flag |= NODE_LINK_TEST; + if (!(link->tosock->flag & SOCK_MULTI_INPUT)) { + link->tosock->flag &= ~SOCK_IN_USE; + } +} + +static void nodeUnMuteLink(bNodeLink *link) +{ + link->flag &= ~NODE_LINK_MUTED; + link->flag |= NODE_LINK_TEST; + link->tosock->flag |= SOCK_IN_USE; +} + +/* Upstream muting. Always happens when unmuting but checks when muting. O(n^2) algorithm.*/ +static void nodeMuteRerouteInputLinks(bNodeTree *ntree, bNode *node, const bool mute) +{ + if (node->type != NODE_REROUTE) { + return; + } + if (!mute || nodeMuteFromSocketLinks(ntree, (bNodeSocket *)node->outputs.first)) { + bNodeSocket *sock = (bNodeSocket *)node->inputs.first; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (!(link->flag & NODE_LINK_VALID) || (link->tosock != sock)) { + continue; + } + if (mute) { + nodeMuteLink(link); + } + else { + nodeUnMuteLink(link); + } + nodeMuteRerouteInputLinks(ntree, link->fromnode, mute); + } + } +} + +/* Downstream muting propagates when reaching reroute nodes. O(n^2) algorithm.*/ +static void nodeMuteRerouteOutputLinks(bNodeTree *ntree, bNode *node, const bool mute) +{ + if (node->type != NODE_REROUTE) { + return; + } + bNodeSocket *sock; + sock = (bNodeSocket *)node->outputs.first; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (!(link->flag & NODE_LINK_VALID) || (link->fromsock != sock)) { + continue; + } + if (mute) { + nodeMuteLink(link); + } + else { + nodeUnMuteLink(link); + } + nodeMuteRerouteOutputLinks(ntree, link->tonode, mute); + } +} + +void nodeMuteLinkToggle(bNodeTree *ntree, bNodeLink *link) +{ + if (link->tosock) { + bool mute = !(link->flag & NODE_LINK_MUTED); + if (mute) { + nodeMuteLink(link); + } + else { + nodeUnMuteLink(link); + } + if (link->tonode->type == NODE_REROUTE) { + nodeMuteRerouteOutputLinks(ntree, link->tonode, mute); + } + if (link->fromnode->type == NODE_REROUTE) { + nodeMuteRerouteInputLinks(ntree, link->fromnode, mute); + } + } + + if (ntree) { + ntree->update |= NTREE_UPDATE_LINKS; + } +} + void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) { LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { @@ -2257,6 +2360,10 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node) link->flag &= ~NODE_LINK_VALID; } + if (fromlink->flag & NODE_LINK_MUTED) { + link->flag |= NODE_LINK_MUTED; + } + ntree->update |= NTREE_UPDATE_LINKS; } else { @@ -4014,7 +4121,9 @@ void ntreeTagUsedSockets(bNodeTree *ntree) LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { link->fromsock->flag |= SOCK_IN_USE; - link->tosock->flag |= SOCK_IN_USE; + if (!(link->flag & NODE_LINK_MUTED)) { + link->tosock->flag |= SOCK_IN_USE; + } } } diff --git a/source/blender/compositor/intern/COM_NodeGraph.cc b/source/blender/compositor/intern/COM_NodeGraph.cc index f932acfa49e..d8220099f1f 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cc +++ b/source/blender/compositor/intern/COM_NodeGraph.cc @@ -188,7 +188,8 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink if (!(b_nodelink->flag & NODE_LINK_VALID)) { return; } - if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL)) { + if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL) || + (b_nodelink->flag & NODE_LINK_MUTED)) { return; } 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); @@ -3843,6 +3851,25 @@ static void nodelink_batch_init(void) set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp); } + /* 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)) diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl index 4567429f645..9ce2a1be015 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl @@ -2,7 +2,7 @@ * 2D Quadratic Bezier thick line drawing */ -#define MID_VERTEX 57 +#define MID_VERTEX 65 /* u is position along the curve, defining the tangent space. * v is "signed" distance (compressed to [0..1] range) from the pos in expand direction */ @@ -17,6 +17,7 @@ in vec2 P1; in vec2 P2; in vec2 P3; in ivec4 colid_doarrow; +in ivec2 domuted; uniform vec4 colors[6]; @@ -24,6 +25,7 @@ uniform vec4 colors[6]; # define colEnd colors[colid_doarrow[1]] # define colShadow colors[colid_doarrow[2]] # define doArrow (colid_doarrow[3] != 0) +# define doMuted (domuted[0] != 0) #else /* Single curve drawcall, use uniform. */ @@ -36,6 +38,7 @@ uniform vec2 bezierPts[4]; uniform vec4 colors[3]; uniform bool doArrow; +uniform bool doMuted; # define colShadow colors[0] # define colStart colors[1] @@ -90,13 +93,18 @@ void main(void) /* Second pass */ finalColor = mix(colStart, colEnd, uv.x); expand_dist *= 0.5; + if (doMuted) { + finalColor[3] = 0.65; + } } /* Expand into a line */ gl_Position.xy += exp_axis * expandSize * expand_dist; - /* if arrow */ - if (expand.y != 1.0 && !doArrow) { + /* If the link is not muted or is not a reroute arrow the points are squashed to the center of + * the line. Magic numbers are defined in drawnode.c */ + if ((expand.x == 1.0 && !doMuted) || + (expand.y != 1.0 && (pos.x < 0.70 || pos.x > 0.71) && !doArrow)) { gl_Position.xy *= 0.0; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 06ee22b1452..acbe9da45fd 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -402,6 +402,7 @@ typedef struct bNodeLink { #define NODE_LINK_VALID (1 << 1) #define NODE_LINK_TEST (1 << 2) /* free test flag, undefined */ #define NODE_LINK_TEMP_HIGHLIGHT (1 << 3) /* Link is highlighted for picking. */ +#define NODE_LINK_MUTED (1 << 4) /* Link is muted. */ /* tree->edit_quality/tree->render_quality */ #define NTREE_QUALITY_HIGH 0 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 04ff181d9b5..fc1f692a8bf 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -10872,6 +10872,11 @@ static void rna_def_node_link(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Valid", "Link is valid"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL); + prop = RNA_def_property(srna, "is_muted", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_LINK_MUTED); + RNA_def_struct_ui_text(srna, "Muted", "Link is muted and can be ignored"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL); + prop = RNA_def_property(srna, "from_node", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "fromnode"); RNA_def_property_struct_type(prop, "Node"); diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 6207a1bf024..dd9d0b6796a 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -71,7 +71,8 @@ void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack static void node_init_input_index(bNodeSocket *sock, int *index) { /* Only consider existing link if from socket is valid! */ - if (sock->link && sock->link->fromsock && sock->link->fromsock->stack_index >= 0) { + if (sock->link && !(sock->link->flag & NODE_LINK_MUTED) && sock->link->fromsock && + sock->link->fromsock->stack_index >= 0) { sock->stack_index = sock->link->fromsock->stack_index; } else { @@ -131,7 +132,7 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, } /* don't mess with remote socket stacks, these are initialized by other nodes! */ - if (sock->link) { + if (sock->link && !(sock->link->flag & NODE_LINK_MUTED)) { return ns; } diff --git a/source/blender/nodes/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc index a66b7b1d2fe..8d979ffac9c 100644 --- a/source/blender/nodes/intern/node_tree_ref.cc +++ b/source/blender/nodes/intern/node_tree_ref.cc @@ -77,6 +77,9 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) } LISTBASE_FOREACH (bNodeLink *, blink, &btree->links) { + if (blink->flag & NODE_LINK_MUTED) { + continue; + } OutputSocketRef &from_socket = this->find_output_socket( node_mapping, blink->fromnode, blink->fromsock); InputSocketRef &to_socket = this->find_input_socket( diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index a385cb7039f..3fb4d10979d 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -388,7 +388,7 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) if (is_group || is_group_output) { LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { - if (socket->link != NULL) { + if (socket->link != NULL && !(socket->link->flag & NODE_LINK_MUTED)) { bNodeLink *link = socket->link; /* Fix the case where the socket is actually converting the data. (see T71374) * We only do the case of lossy conversion to float.*/ @@ -557,7 +557,7 @@ static bool ntree_shader_has_displacement(bNodeTree *ntree, /* Non-cycles node is used as an output. */ return false; } - if (displacement->link != NULL) { + if ((displacement->link != NULL) && !(displacement->link->flag & NODE_LINK_MUTED)) { *r_node = displacement->link->fromnode; *r_socket = displacement->link->fromsock; *r_link = displacement->link; diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index d6e4a93f6a6..cdb7b591907 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -520,13 +520,37 @@ void wm_init_cursor_data(void) BlenderCursor[WM_CURSOR_WAIT] = &WaitCursor; END_CURSOR_BLOCK; + /********************** Mute Cursor ***********************/ + BEGIN_CURSOR_BLOCK; + static char mute_bitmap[] = { + 0x00, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x03, 0x14, 0x03, 0x22, + 0x03, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x7c, 0xf8, 0x7c, 0x00, 0x03, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, + }; + + static char mute_mask[] = { + 0x63, 0x00, 0x77, 0x00, 0x3e, 0x03, 0x1c, 0x03, 0x3e, 0x03, 0x77, + 0x03, 0x63, 0x03, 0x80, 0x07, 0xfc, 0xfc, 0xfc, 0xfc, 0x80, 0x07, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, + }; + + static BCursor MuteCursor = { + mute_bitmap, + mute_mask, + 9, + 8, + true, + }; + + BlenderCursor[WM_CURSOR_MUTE] = &MuteCursor; + END_CURSOR_BLOCK; + /****************** Normal Cross Cursor ************************/ BEGIN_CURSOR_BLOCK; static char cross_bitmap[] = { 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x3e, 0x7c, 0x3e, 0x7c, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, - }; static char cross_mask[] = { diff --git a/source/blender/windowmanager/wm_cursors.h b/source/blender/windowmanager/wm_cursors.h index b85616deda5..2842538ebf1 100644 --- a/source/blender/windowmanager/wm_cursors.h +++ b/source/blender/windowmanager/wm_cursors.h @@ -72,6 +72,7 @@ typedef enum WMCursorType { WM_CURSOR_ZOOM_OUT, WM_CURSOR_NONE, + WM_CURSOR_MUTE, /* --- ALWAYS LAST ----- */ WM_CURSOR_NUM,