[Bf-blender-cvs] [5122c75fd62] soc-2020-greasepencil-curve: GPencil: Implement box and lasso curve select
Falk David
noreply at git.blender.org
Tue Jul 14 16:53:19 CEST 2020
Commit: 5122c75fd62c244473e10e3242f3312378bebca9
Author: Falk David
Date: Tue Jul 14 16:52:35 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rB5122c75fd62c244473e10e3242f3312378bebca9
GPencil: Implement box and lasso curve select
===================================================================
M source/blender/editors/gpencil/gpencil_select.c
===================================================================
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index d348b849f5b..d2f15f667b4 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -128,6 +128,61 @@ static bool gpencil_select_poll(bContext *C)
return false;
}
+static bool gpencil_3d_point_to_screen_space(ARegion *region,
+ const float diff_mat[4][4],
+ const float co[3],
+ int r_co[2])
+{
+ float parent_co[3];
+ mul_v3_m4v3(parent_co, diff_mat, co);
+ int screen_co[2];
+ if (ED_view3d_project_int_global(
+ region, parent_co, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
+ V3D_PROJ_RET_OK) {
+ if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
+ copy_v2_v2_int(r_co, screen_co);
+ return true;
+ }
+ }
+ r_co[0] = V2D_IS_CLIPPED;
+ r_co[1] = V2D_IS_CLIPPED;
+ return false;
+}
+
+/* helper to deselect all selected strokes/points */
+static void deselect_all_selected(bContext *C)
+{
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* deselect stroke and its points if selected */
+ if (gps->flag & GP_STROKE_SELECT) {
+ bGPDspoint *pt;
+ int i;
+
+ /* deselect points */
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ /* deselect curve and curve points */
+ if (gps->editcurve != NULL) {
+ bGPDcurve *gpc = gps->editcurve;
+ for (int j = 0; j < gpc->tot_curve_points; j++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[j];
+ BezTriple *bezt = &gpc_pt->bezt;
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_ALL(bezt);
+ }
+
+ gpc->flag &= ~GP_CURVE_SELECT;
+ }
+
+ /* deselect stroke itself too */
+ gps->flag &= ~GP_STROKE_SELECT;
+ }
+ }
+ CTX_DATA_END;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1137,8 +1192,6 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd,
}
static bool gpencil_do_curve_circle_sel(bContext *C,
- bGPdata *gpd,
- bGPDlayer *gpl,
bGPDstroke *gps,
bGPDcurve *gpc,
const int mx,
@@ -1278,25 +1331,24 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
rect.xmax = mx + radius;
rect.ymax = my + radius;
- GP_SpaceConversion gsc = {NULL};
- /* init space conversion stuff */
- gpencil_point_conversion_init(C, &gsc);
-
if (is_curve_edit) {
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
ED_gpencil_select_curve_toggle_all(C, SEL_DESELECT);
changed = true;
}
- /* TODO: do curve circle select */
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
changed |= gpencil_do_curve_circle_sel(
- C, gpd, gpl, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode);
+ C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode);
}
GP_EDITABLE_CURVES_END(gps_iter);
}
else {
+ GP_SpaceConversion gsc = {NULL};
+ /* init space conversion stuff */
+ gpencil_point_conversion_init(C, &gsc);
+
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
ED_gpencil_select_toggle_all(C, SEL_DESELECT);
changed = true;
@@ -1365,18 +1417,203 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
*
* \{ */
-typedef bool (*GPencilTestFn)(bGPDstroke *gps,
- bGPDspoint *pt,
- const GP_SpaceConversion *gsc,
+typedef struct GP_SelectUserData {
+ int mx, my, radius;
+ /* Bounding box rect */
+ rcti rect;
+ const int (*lasso_coords)[2];
+ int lasso_coords_len;
+} GP_SelectUserData;
+
+typedef bool (*GPencilTestFn)(ARegion *region,
const float diff_mat[4][4],
- void *user_data);
+ const float pt[3],
+ GP_SelectUserData *user_data);
+
+static bool gpencil_generic_curve_select(bContext *C,
+ Object *ob,
+ bGPdata *gpd,
+ GPencilTestFn is_inside_fn,
+ rcti box,
+ GP_SelectUserData *user_data,
+ const bool strokemode,
+ const eSelectOp sel_op)
+{
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const bool handle_only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
+ const bool handle_all = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
+
+ // /* deselect handles first */
+ // if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ // GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+ // {
+ // /* deselect stroke and its points if selected */
+ // if (gps->flag & GP_STROKE_SELECT) {
+ // if (gps->editcurve != NULL) {
+ // bGPDcurve *gpc = gps->editcurve;
+ // for (int j = 0; j < gpc->tot_curve_points; j++) {
+ // bGPDcurve_point *gpc_pt = &gpc->curve_points[j];
+ // BezTriple *bezt = &gpc_pt->bezt;
+ // if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
+ // bezt->f1 &= ~SELECT;
+ // bezt->f3 &= ~SELECT;
+ // }
+
+ // SET_FLAG_FROM_TEST(gpc_pt->flag, bezt->f1 || bezt->f3, GP_CURVE_POINT_SELECT);
+ // }
+
+ // gpc->flag &= ~GP_CURVE_SELECT;
+ // }
+
+ // /* deselect stroke itself too */
+ // gps->flag &= ~GP_STROKE_SELECT;
+ // }
+ // }
+ // GP_EDITABLE_CURVES_END(gps_iter);
+ // }
+
+ bool hit = false;
+ bool changed = false;
+
+ GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+ {
+ bool any_select = false;
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ BezTriple *bezt = &gpc_pt->bezt;
+
+ if (bezt->hide == 1) {
+ continue;
+ }
+
+ const bool handles_visible = (handle_all || (handle_only_selected &&
+ (gpc_pt->flag & GP_CURVE_POINT_SELECT)));
+
+ if (handles_visible) {
+ for (int j = 0; j < 3; j++) {
+ const bool is_select = BEZT_ISSEL_IDX(bezt, j);
+ bool is_inside = is_inside_fn(region, gps_iter.diff_mat, bezt->vec[j], user_data);
+ if (strokemode) {
+ if (is_inside) {
+ hit = true;
+ any_select = true;
+ break;
+ }
+ }
+ else {
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result) {
+ gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+ BEZT_SEL_IDX(bezt, j);
+ any_select = true;
+ }
+ else {
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_IDX(bezt, j);
+ }
+ changed = true;
+ hit = true;
+ }
+ else {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_IDX(bezt, j);
+ }
+ }
+ }
+ }
+ }
+ /* if the handles are not visible only check ctrl point (vec[1])*/
+ else {
+ const bool is_select = bezt->f2;
+ bool is_inside = is_inside_fn(region, gps_iter.diff_mat, bezt->vec[1], user_data);
+ if (strokemode) {
+ if (is_inside) {
+ hit = true;
+ any_select = true;
+ }
+ }
+ else {
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ if (sel_op_result) {
+ gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+ bezt->f2 |= SELECT;
+ any_select = true;
+ }
+ else {
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ bezt->f2 &= ~SELECT;
+ }
+ changed = true;
+ hit = true;
+ }
+ else {
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ bezt->f2 &= ~SELECT;
+ }
+ }
+ }
+ }
+ }
+
+ if (!hit) {
+ /* check if we selected the inside of a filled curve */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+ continue;
+ }
+ int mval[2];
+ mval[0] = (box.xmax + box.xmin) / 2;
+ mval[1] = (box.ymax + box.ymin) / 2;
+
+ hit = false;
+ }
+
+ /* select the entire curve */
+ if (strokemode) {
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, any_select, hit);
+ if (sel_op_result != -1) {
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ BezTriple *bezt = &gpc_pt->bezt;
+
+ if (sel_op_result) {
+ gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+ BEZT_SEL_ALL(bezt);
+ }
+ else {
+ gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+ BEZT_DESEL_ALL(bezt);
+ }
+ }
+
+ if(sel_op_result) {
+ gpc->flag |= GP_CURVE_SELECT;
+ }
+ else {
+ gpc->flag &= ~GP_CURVE_SELECT;
+ }
+ changed = true;
+ }
+ }
+
+ BKE_gpencil_curve_sync_selection(gps);
+ }
+ GP_EDITABLE_CURVES_END(gps_iter);
+
+ return changed;
+}
static bool gpencil_ge
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list