Page MenuHome
Paste P1404

D7754 with own changes (Curves: Implement Handles for selected points only)
ActivePublic

Authored by Julian Eisel (Severin) on May 19 2020, 12:47 PM.
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");