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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs