diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f288c955c92..07bc7ce903e 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -6371,6 +6371,9 @@ class VIEW3D_PT_overlay_edit_curve(Panel): row = col.row() row.prop(overlay, "show_curve_handles", text="Handles") + subrow = row.row() + subrow.active = overlay.show_curve_handles + subrow.prop(overlay, "handle_type", text="Type") row = col.row() row.prop(overlay, "show_curve_normals", text="") diff --git a/source/blender/draw/engines/overlay/overlay_edit_curve.c b/source/blender/draw/engines/overlay/overlay_edit_curve.c index 6456d6868a5..6d57997e619 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_curve.c +++ b/source/blender/draw/engines/overlay/overlay_edit_curve.c @@ -37,6 +37,7 @@ void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata) DRWState state; pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0; + pd->edit_curve.handle_type = v3d->overlay.handle_type; pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length; /* Run Twice for in-front passes. */ @@ -62,11 +63,13 @@ void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata) pd->edit_curve_handle_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles); + DRW_shgroup_uniform_bool_copy(grp, "curveHandleType", pd->edit_curve.handle_type); DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA); sh = OVERLAY_shader_edit_curve_point(); pd->edit_curve_points_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps); DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles); + DRW_shgroup_uniform_bool_copy(grp, "curveHandleType", pd->edit_curve.handle_type); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } } diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c index 3de0155d6e0..00e21f9f400 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_text.c +++ b/source/blender/draw/engines/overlay/overlay_edit_text.c @@ -39,6 +39,7 @@ void OVERLAY_edit_text_cache_init(OVERLAY_Data *vedata) DRWState state; pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0; + pd->edit_curve.handle_type = v3d->overlay.handle_type; pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length; /* Run Twice for in-front passes. */ diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 0c29fe9d2e4..2293e59cf14 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -296,6 +296,7 @@ typedef struct OVERLAY_PrivateData { } antialiasing; struct { bool show_handles; + int handle_type; } edit_curve; struct { int ghost_ob; diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl index b444b3b0fec..a022ddedef6 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_curve_handle_geom.glsl @@ -4,10 +4,14 @@ #define EVEN_U_BIT 1 << 4 #define COLOR_SHIFT 5 +/* Keep the same value in `handle_type` in `DNA_view3d_types.h` */ +#define CURVE_HANDLE_SELECTED 1 + layout(lines) in; layout(triangle_strip, max_vertices = 10) out; uniform bool showCurveHandles; +uniform int curveHandleType; flat in int vertFlag[]; @@ -46,6 +50,12 @@ void main() } bool edge_selected = (((vertFlag[1] | vertFlag[0]) & VERT_SELECTED) != 0); + bool handle_selected = (((vertFlag[1] | vertFlag[0]) & HANDLE_SELECTED) != 0); + + /* If handle type is only selected and the edge is not selected, don't show. */ + if ((curveHandleType == CURVE_HANDLE_SELECTED) && (!handle_selected)) { + return; + } vec4 inner_color; if (color_id == 0) { diff --git a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl index 6fa4576ae71..f6a04763ed8 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_curve_point_vert.glsl @@ -2,7 +2,11 @@ /* Keep the same value of `BEZIER_HANDLE` in `draw_cache_imp_curve.c` */ #define BEZIER_HANDLE 1 << 3 +/* Keep the same value in `handle_type` in `DNA_view3d_types.h` */ +#define CURVE_HANDLE_SELECTED 1 + uniform bool showCurveHandles; +uniform int curveHandleType; in vec3 pos; in int data; @@ -32,7 +36,12 @@ void main() world_clip_planes_calc_clip_distance(world_pos); #endif - if (!showCurveHandles && ((data & BEZIER_HANDLE) != 0)) { + bool show_handle = showCurveHandles; + if ((curveHandleType == CURVE_HANDLE_SELECTED) && ((data & HANDLE_SELECTED) == 0)) { + show_handle = false; + } + + if (!show_handle && ((data & BEZIER_HANDLE) != 0)) { /* We set the vertex at the camera origin to generate 0 fragments. */ gl_Position = vec4(0.0, 0.0, -3e36, 0.0); } diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index de0cd027ece..daa46252331 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -208,6 +208,7 @@ enum { VFLAG_EDGE_SEAM = 1 << 4, VFLAG_EDGE_SHARP = 1 << 5, VFLAG_EDGE_FREESTYLE = 1 << 6, + VFLAG_HANDLE_SELECTED = 1 << 7, /* Beware to not go over 1 << 7 (it's a byte flag) * (see gpu_shader_edit_mesh_overlay_geom.glsl) */ }; diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 72ee7fe17c1..5578e647ec4 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -685,14 +685,20 @@ static void curve_create_edit_curves_nor(CurveRenderData *rdata, GPUVertBuf *vbo BLI_assert(vbo_len_used == verts_len_capacity); } -static char beztriple_vflag_get( - CurveRenderData *rdata, char flag, char col_id, int v_idx, int nu_id, bool handle_point) +static char beztriple_vflag_get(CurveRenderData *rdata, + char flag, + char col_id, + int v_idx, + int nu_id, + bool handle_point, + const bool handle_selected) { char vflag = 0; SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); + SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_HANDLE_SELECTED); /* handle color id */ vflag |= col_id << COLOR_SHIFT; return vflag; @@ -754,11 +760,13 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata, for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, nu_id++) { const BezTriple *bezt = nu->bezt; const BPoint *bp = nu->bp; + if (bezt) { for (int a = 0; a < nu->pntsu; a++, bezt++) { if (bezt->hide == true) { continue; } + const bool handle_selected = BEZT_ISSEL_ANY(bezt); if (elbp_verts) { GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0); @@ -771,9 +779,9 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata, } if (vbo_data) { const char vflag[3] = { - beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true), - beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false), - beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true), + beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected), + beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected), + beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected), }; for (int j = 0; j < 3; j++) { GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]); diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl index 9dfd48cc21a..a479a87e14b 100644 --- a/source/blender/draw/intern/shaders/common_globals_lib.glsl +++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl @@ -140,3 +140,4 @@ layout(std140) uniform globalsBlock #define EDGE_SEAM (1 << 4) #define EDGE_SHARP (1 << 5) #define EDGE_FREESTYLE (1 << 6) +#define HANDLE_SELECTED (1 << 7) diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index d6256f67066..bcb34aacc55 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4824,6 +4824,8 @@ bool ED_curve_editnurb_select_pick( view3d_operator_needs_opengl(C); ED_view3d_viewcontext_init(C, &vc, depsgraph); copy_v2_v2_int(vc.mval, mval); + View3D *v3d = vc.v3d; + const bool only_selected = v3d->overlay.handle_type == CURVE_HANDLE_SELECTED; if (ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact)) { Object *obedit = basact->object; @@ -4955,6 +4957,11 @@ bool ED_curve_editnurb_select_pick( ED_object_base_activate(C, basact); } + if (only_selected && ((bezt->flag & BEZT_HANDLER_VISIBLE) == 0) && (bezt->f2 == 0)) { + bezt->f1 = 0; + bezt->f3 = 0; + } + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c index 0b15d9e55b9..e0f161ca0cf 100644 --- a/source/blender/editors/curve/editcurve_query.c +++ b/source/blender/editors/curve/editcurve_query.c @@ -44,8 +44,13 @@ /** \name Cursor Picking API * \{ */ -static void ED_curve_pick_vert__do_closest( - void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +static void ED_curve_pick_vert__do_closest(void *userData, + Nurb *nu, + BPoint *bp, + BezTriple *bezt, + int beztindex, + bool handles_visible, + const float screen_co[2]) { struct { BPoint *bp; @@ -64,6 +69,8 @@ static void ED_curve_pick_vert__do_closest( flag = bp->f1; } else { + BLI_assert(handles_visible || beztindex == 1); + if (beztindex == 0) { flag = bezt->f1; } diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 9cf61d02677..91309ad4f49 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -196,6 +196,19 @@ bool ED_curve_nurb_select_all(const Nurb *nu) return changed; } +void ED_curve_synch_visibility(EditNurb *editnurb) +{ + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + int i; + if (nu->bezt) { + BezTriple *bezt; + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + SET_FLAG_FROM_TEST(bezt->flag, bezt->f1 || bezt->f2 || bezt->f3, BEZT_HANDLER_VISIBLE); + } + } + } +} + bool ED_curve_select_all(EditNurb *editnurb) { bool changed = false; @@ -251,6 +264,8 @@ bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) return true; } } + /* Synchronize visible flag. */ + ED_curve_synch_visibility(editnurb); return false; } @@ -406,6 +421,13 @@ static void select_adjacent_cp(ListBase *editnurb, bp -= (next - next / abs(next)); } } + /* Synchronize visible flag. */ + int i; + if (nu->bezt) { + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + SET_FLAG_FROM_TEST(bezt->flag, bezt->f1 || bezt->f2 || bezt->f3, BEZT_HANDLER_VISIBLE); + } + } } } @@ -486,6 +508,9 @@ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap } } } + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); } static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) @@ -595,6 +620,11 @@ static int de_select_all_exec(bContext *C, wmOperator *op) break; } + /* Synchronize visible flag. */ + if (changed) { + ED_curve_synch_visibility(cu->editnurb); + } + if (changed) { DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -648,6 +678,11 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) } } + /* Synchronize visible flag. */ + if (changed) { + ED_curve_synch_visibility(editnurb); + } + if (changed) { DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -720,6 +755,9 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent } Object *obedit = basact->object; + /* Synchronize visible flag. */ + Curve *cu = obedit->data; + ED_curve_synch_visibility(cu->editnurb); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -793,6 +831,8 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) } } } + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -826,8 +866,14 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, 1, 0, SELECT); + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -861,8 +907,14 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); select_adjacent_cp(editnurb, -1, 0, SELECT); + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -971,7 +1023,13 @@ static int curve_select_more_exec(bContext *C, wmOperator *UNUSED(op)) view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + curve_select_more(obedit); + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1186,7 +1244,13 @@ static int curve_select_less_exec(bContext *C, wmOperator *UNUSED(op)) view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + curve_select_less(obedit); + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1264,6 +1328,7 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; ListBase *editnurb = object_editcurve_get(obedit); int seed_iter = seed; @@ -1275,6 +1340,9 @@ static int curve_select_random_exec(bContext *C, wmOperator *op) curve_select_random(editnurb, randfac, seed_iter, select); BKE_curve_nurb_vert_active_validate(obedit->data); + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1392,6 +1460,10 @@ static int select_nth_exec(bContext *C, wmOperator *op) if (ed_curve_select_nth(obedit->data, &op_params) == true) { changed = true; + + /* Synchronize visible flag. */ + ED_curve_synch_visibility(cu->editnurb); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } @@ -1755,6 +1827,15 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) obedit, nu, optype, tree_1d, tree_3d, thresh, compare); break; } + + /* Synchronize visible flag. */ + int i; + if (nu->bezt) { + BezTriple *bezt; + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + SET_FLAG_FROM_TEST(bezt->flag, bezt->f1 || bezt->f2 || bezt->f3, BEZT_HANDLER_VISIBLE); + } + } } if (changed) { @@ -2013,6 +2094,15 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE ED_object_base_activate(C, basact); } + /* Synchronize visible flag. */ + int i; + if (nu_dst->bezt) { + BezTriple *bezt; + for (i = nu_dst->pntsu, bezt = nu_dst->bezt; i--; bezt++) { + SET_FLAG_FROM_TEST(bezt->flag, bezt->f1 || bezt->f2 || bezt->f3, BEZT_HANDLER_VISIBLE); + } + } + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 95c454043da..c5f3d568c56 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -76,6 +76,7 @@ bool ED_curve_deselect_all_multi(struct bContext *C); bool ED_curve_select_all(struct EditNurb *editnurb); bool ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles); int ED_curve_select_count(struct View3D *v3d, struct EditNurb *editnurb); +void ED_curve_synch_visibility(struct EditNurb *editnurb); /* editcurve_undo.c */ void ED_curve_undosys_type(struct UndoType *ut); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 668ca3c6437..be07a01f7f9 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -246,6 +246,7 @@ void nurbs_foreachScreenVert(struct ViewContext *vc, struct BPoint *bp, struct BezTriple *bezt, int beztindex, + bool handle_visible, const float screen_co[2]), void *userData, const eV3DProjTest clip_flag); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 08e68c9174e..c609b6d80e4 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -406,6 +406,7 @@ void nurbs_foreachScreenVert(ViewContext *vc, BPoint *bp, BezTriple *bezt, int beztindex, + bool handles_visible, const float screen_co_b[2]), void *userData, const eV3DProjTest clip_flag) @@ -414,6 +415,8 @@ void nurbs_foreachScreenVert(ViewContext *vc, Nurb *nu; int i; ListBase *nurbs = BKE_curve_editNurbs_get(cu); + /* If no point in the triple is selected, the handles are invisible. */ + const bool only_selected = (vc->v3d->overlay.handle_type == CURVE_HANDLE_SELECTED); ED_view3d_check_mats_rv3d(vc->rv3d); @@ -427,15 +430,18 @@ void nurbs_foreachScreenVert(ViewContext *vc, BezTriple *bezt = &nu->bezt[i]; if (bezt->hide == 0) { + const bool handles_visible = (vc->v3d->overlay.edit_flag & + V3D_OVERLAY_EDIT_CU_HANDLES) && + (!only_selected || BEZT_ISSEL_ANY(bezt)); float screen_co[2]; - if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { + if (!handles_visible) { if (ED_view3d_project_float_object(vc->region, bezt->vec[1], screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) { - func(userData, nu, NULL, bezt, 1, screen_co); + func(userData, nu, NULL, bezt, 1, false, screen_co); } } else { @@ -444,21 +450,21 @@ void nurbs_foreachScreenVert(ViewContext *vc, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) { - func(userData, nu, NULL, bezt, 0, screen_co); + func(userData, nu, NULL, bezt, 0, true, screen_co); } if (ED_view3d_project_float_object(vc->region, bezt->vec[1], screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) { - func(userData, nu, NULL, bezt, 1, screen_co); + func(userData, nu, NULL, bezt, 1, true, screen_co); } if (ED_view3d_project_float_object(vc->region, bezt->vec[2], screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) { - func(userData, nu, NULL, bezt, 2, screen_co); + func(userData, nu, NULL, bezt, 2, true, screen_co); } } } @@ -473,7 +479,7 @@ void nurbs_foreachScreenVert(ViewContext *vc, if (ED_view3d_project_float_object( vc->region, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) { - func(userData, nu, bp, NULL, -1, screen_co); + func(userData, nu, bp, NULL, -1, false, screen_co); } } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 2ce2edb98fe..c2631cf0159 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -903,6 +903,7 @@ static void do_lasso_select_curve__doSelect(void *userData, BPoint *bp, BezTriple *bezt, int beztindex, + bool handles_visible, const float screen_co[2]) { LassoSelectUserData *data = userData; @@ -918,8 +919,8 @@ static void do_lasso_select_curve__doSelect(void *userData, } } else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ + if (!handles_visible) { + /* can only be (beztindex == 1) here since handles are hidden */ const bool is_select = bezt->f2 & SELECT; const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2423,6 +2424,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op) if (!retval && deselect_all) { retval = ED_curve_deselect_all_multi(C); } + /* Synchronize visible flag. */ + Curve *cu = obedit->data; + ED_curve_synch_visibility(cu->editnurb); } else if (obedit->type == OB_MBALL) { retval = ED_mball_select_pick(C, location, extend, deselect, toggle); @@ -2707,6 +2711,7 @@ static void do_nurbs_box_select__doSelect(void *userData, BPoint *bp, BezTriple *bezt, int beztindex, + bool handles_visible, const float screen_co[2]) { BoxSelectUserData *data = userData; @@ -2721,8 +2726,8 @@ static void do_nurbs_box_select__doSelect(void *userData, } } else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ + if (!handles_visible) { + /* can only be (beztindex == 1) here since handles are hidden */ const bool is_select = bezt->f2 & SELECT; const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -3650,6 +3655,7 @@ static void nurbscurve_circle_doSelect(void *userData, BPoint *bp, BezTriple *bezt, int beztindex, + bool handles_visible, const float screen_co[2]) { CircleSelectUserData *data = userData; @@ -3659,8 +3665,8 @@ static void nurbscurve_circle_doSelect(void *userData, bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); } else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ + if (!handles_visible) { + /* can only be (beztindex == 1) here since handles are hidden */ bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT); } else { diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 6a081a7f5a7..2e77aae76df 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -131,9 +131,17 @@ typedef struct BezTriple { /** F5: used for auto handle to distinguish between normal handle and exception (extrema). */ char f5; - char _pad[3]; + /** General flag */ + char flag; + char _pad[2]; } BezTriple; +/* BezTriple->flag. */ +typedef enum eBezTripleFlag { + /** Used to display only selected. */ + BEZT_HANDLER_VISIBLE = 1 << 0, +} eBezTripleFlag; + /** * \note #BPoint.tilt location in struct is abused by Key system. */ diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index 20b491c47f2..58f6da0009a 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -66,6 +66,7 @@ V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES | \ V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS | \ V3D_OVERLAY_EDIT_CU_HANDLES, \ + .handle_type = CURVE_HANDLE_ALL, \ \ .gpencil_paper_opacity = 0.5f, \ .gpencil_grid_opacity = 0.9f, \ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 6d8d16c4313..24c36e1bf0e 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -228,9 +228,18 @@ typedef struct View3DOverlay { /** Factor for mixing vertex paint with original color */ float gpencil_vertex_paint_opacity; - char _pad4[4]; + /** Handles display type for curves. */ + int handle_type; } View3DOverlay; +/* View3DOverlay->handle_type */ +typedef enum eHandleType { + /* Display all handles. */ + CURVE_HANDLE_ALL = 0, + /* Display only selected points. */ + CURVE_HANDLE_SELECTED = 1, +} eHandleType; + typedef struct View3D_Runtime { /** Nkey panel stores stuff here. */ void *properties_storage; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index c719aa99fd8..82b11ccce76 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -483,6 +483,12 @@ const EnumPropertyItem rna_enum_file_sort_items[] = { {0, NULL, 0, NULL, NULL}, }; +static EnumPropertyItem rna_enum_curve_handles_items[] = { + {CURVE_HANDLE_ALL, "ALL", 0, "All", ""}, + {CURVE_HANDLE_SELECTED, "SELECTED", 0, "Selected", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME # include "DNA_anim_types.h" @@ -3822,6 +3828,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Handles", "Display Bezier handles in editmode"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "overlay.handle_type"); + RNA_def_property_enum_items(prop, rna_enum_curve_handles_items); + RNA_def_property_ui_text(prop, "Handle Type", "Type of handle displayed in edit mode"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_curve_normals", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_CU_NORMALS); RNA_def_property_ui_text(prop, "Draw Normals", "Display 3D curve normals in editmode");