diff options
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_select.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_select.c | 1487 |
1 files changed, 751 insertions, 736 deletions
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index c33b43247fd..e4f397be20e 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -132,27 +132,6 @@ 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) { @@ -162,33 +141,32 @@ static void deselect_all_selected(bContext *C) gpd->select_last_index = 0; 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; + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; - /* deselect points */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - pt->flag &= ~GP_SPOINT_SELECT; + if (gpc->flag & GP_CURVE_SELECT) { + /* Deselect the curve points. */ + for (uint32_t i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + 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; - BKE_gpencil_stroke_select_index_reset(gps); } - - /* 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); + else { + if (gps->flag & GP_STROKE_SELECT) { + /* Deselect the points. */ + for (uint32_t i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + pt->flag &= ~GP_SPOINT_SELECT; + } + gps->flag &= ~GP_STROKE_SELECT; } - - gpc->flag &= ~GP_CURVE_SELECT; } + + BKE_gpencil_stroke_select_index_reset(gps); } CTX_DATA_END; } @@ -210,12 +188,10 @@ static void select_all_curve_points(bGPdata *gpd, bGPDstroke *gps, bGPDcurve *gp if (deselect == false) { gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; BKE_gpencil_stroke_select_index_set(gpd, gps); } else { gpc->flag &= ~GP_CURVE_SELECT; - gps->flag &= ~GP_STROKE_SELECT; BKE_gpencil_stroke_select_index_reset(gps); } } @@ -244,7 +220,6 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); int action = RNA_enum_get(op->ptr, "action"); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); @@ -264,12 +239,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) } } - if (is_curve_edit) { - ED_gpencil_select_curve_toggle_all(C, action); - } - else { - ED_gpencil_select_toggle_all(C, action); - } + ED_gpencil_select_toggle_all(C, action); /* updates */ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); @@ -308,7 +278,6 @@ void GPENCIL_OT_select_all(wmOperatorType *ot) static int gpencil_select_linked_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); @@ -320,9 +289,11 @@ static int gpencil_select_linked_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (is_curve_edit) { - GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) - { + bool changed = false; + /* select all points in selected strokes */ + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; if (gpc->flag & GP_CURVE_SELECT) { for (int i = 0; i < gpc->tot_curve_points; i++) { bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; @@ -330,13 +301,10 @@ static int gpencil_select_linked_exec(bContext *C, wmOperator *op) gpc_pt->flag |= GP_CURVE_POINT_SELECT; BEZT_SEL_ALL(bezt); } + changed = true; } } - GP_EDITABLE_CURVES_END(gps_iter); - } - else { - /* select all points in selected strokes */ - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + else { if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; @@ -344,19 +312,24 @@ static int gpencil_select_linked_exec(bContext *C, wmOperator *op) for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag |= GP_SPOINT_SELECT; } + + changed = true; } } - CTX_DATA_END; } + CTX_DATA_END; - /* updates */ - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); + if (changed) { + /* updates */ + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); - /* copy on write tag is needed, or else no refresh happens */ - DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE); + /* copy on write tag is needed, or else no refresh happens */ + DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE); + + WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL); + } - WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL); return OPERATOR_FINISHED; } @@ -385,7 +358,6 @@ static int gpencil_select_alternate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends"); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); @@ -398,10 +370,10 @@ static int gpencil_select_alternate_exec(bContext *C, wmOperator *op) } bool changed = false; - if (is_curve_edit) { - GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) - { - if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) { + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + if ((gpc->flag & GP_CURVE_SELECT) && (gpc->tot_curve_points > 1)) { int idx = 0; int start = 0; if (unselect_ends) { @@ -435,11 +407,7 @@ static int gpencil_select_alternate_exec(bContext *C, wmOperator *op) changed = true; } } - GP_EDITABLE_CURVES_END(gps_iter); - } - else { - /* select all points in selected strokes */ - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + else { if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) { bGPDspoint *pt; int row = 0; @@ -471,8 +439,8 @@ static int gpencil_select_alternate_exec(bContext *C, wmOperator *op) changed = true; } } - CTX_DATA_END; } + CTX_DATA_END; if (changed) { /* updates */ @@ -535,7 +503,6 @@ static bool gpencil_select_same_layer(bContext *C) { Scene *scene = CTX_data_scene(C); bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); bool changed = false; CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { @@ -549,49 +516,46 @@ static bool gpencil_select_same_layer(bContext *C) /* Search for a selected stroke */ for (gps = gpf->strokes.first; gps; gps = gps->next) { - if (ED_gpencil_stroke_can_use(C, gps)) { - if (gps->flag & GP_STROKE_SELECT) { - found = true; - break; - } + if (!ED_gpencil_stroke_can_use(C, gps)) { + continue; + } + + if (gps->flag & GP_STROKE_SELECT || + (GPENCIL_STROKE_TYPE_BEZIER(gps) && gps->editcurve->flag & GP_CURVE_SELECT)) { + found = true; + break; } } /* Select all if found */ if (found) { - if (is_curve_edit) { - for (gps = gpf->strokes.first; gps; gps = gps->next) { - if (gps->editcurve != NULL && ED_gpencil_stroke_can_use(C, gps)) { - bGPDcurve *gpc = gps->editcurve; - for (int i = 0; i < gpc->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - gpc_pt->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(&gpc_pt->bezt); - } - gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); + for (gps = gpf->strokes.first; gps; gps = gps->next) { + if (!ED_gpencil_stroke_can_use(C, gps)) { + continue; + } - changed = true; + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + for (int i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + gpc_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(&gpc_pt->bezt); } + gpc->flag |= GP_CURVE_SELECT; } - } - else { - for (gps = gpf->strokes.first; gps; gps = gps->next) { - if (ED_gpencil_stroke_can_use(C, gps)) { - bGPDspoint *pt; - int i; - - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - pt->flag |= GP_SPOINT_SELECT; - } - - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); + else { + bGPDspoint *pt; + int i; - changed = true; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + pt->flag |= GP_SPOINT_SELECT; } + + gps->flag |= GP_STROKE_SELECT; } + + BKE_gpencil_stroke_select_index_set(gpd, gps); + changed = true; } } } @@ -604,14 +568,12 @@ static bool gpencil_select_same_layer(bContext *C) static bool gpencil_select_same_material(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* First, build set containing all the colors of selected strokes */ GSet *selected_colors = BLI_gset_str_new("GP Selected Colors"); - bool changed = false; - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - if (gps->flag & GP_STROKE_SELECT) { + if (gps->flag & GP_STROKE_SELECT || + (GPENCIL_STROKE_TYPE_BEZIER(gps) && gps->editcurve->flag & GP_CURVE_SELECT)) { /* add instead of insert here, otherwise the uniqueness check gets skipped, * and we get many duplicate entries... */ @@ -620,28 +582,22 @@ static bool gpencil_select_same_material(bContext *C) } CTX_DATA_END; + bool changed = false; + /* Second, select any visible stroke that uses these colors */ - if (is_curve_edit) { - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - if (gps->editcurve != NULL && BLI_gset_haskey(selected_colors, &gps->mat_nr)) { + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (BLI_gset_haskey(selected_colors, &gps->mat_nr)) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { bGPDcurve *gpc = gps->editcurve; for (int i = 0; i < gpc->tot_curve_points; i++) { bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; gpc_pt->flag |= GP_CURVE_POINT_SELECT; BEZT_SEL_ALL(&gpc_pt->bezt); } - gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - changed = true; + gpc->flag |= GP_CURVE_SELECT; } - } - CTX_DATA_END; - } - else { - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - if (BLI_gset_haskey(selected_colors, &gps->mat_nr)) { + else { /* select this stroke */ bGPDspoint *pt; int i; @@ -651,13 +607,13 @@ static bool gpencil_select_same_material(bContext *C) } gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - - changed = true; } + + BKE_gpencil_stroke_select_index_set(gpd, gps); + changed = true; } - CTX_DATA_END; } + CTX_DATA_END; /* Free memory. */ if (selected_colors != NULL) { @@ -741,7 +697,6 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot) static int gpencil_select_first_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* If not edit/sculpt mode, the event has been caught but not processed. */ if (GPENCIL_NONE_EDIT_MODE(gpd)) { @@ -754,36 +709,33 @@ static int gpencil_select_first_exec(bContext *C, wmOperator *op) bool changed = false; CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { /* skip stroke if we're only manipulating selected strokes */ - if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { + if (only_selected && + !((gps->flag & GP_STROKE_SELECT) || + (GPENCIL_STROKE_TYPE_BEZIER(gps) && gps->editcurve->flag & GP_CURVE_SELECT))) { continue; } /* select first point */ BLI_assert(gps->totpoints >= 1); - if (is_curve_edit) { - if (gps->editcurve != NULL) { - bGPDcurve *gpc = gps->editcurve; - gpc->curve_points[0].flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(&gpc->curve_points[0].bezt); - gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; - if ((extend == false) && (gps->totpoints > 1)) { - for (int i = 1; i < gpc->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(&gpc_pt->bezt); - } + gpc->curve_points[0].flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(&gpc->curve_points[0].bezt); + gpc->flag |= GP_CURVE_SELECT; + + if ((extend == false) && (gpc->tot_curve_points > 1)) { + for (int i = 1; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(&gpc_pt->bezt); } - changed = true; } } else { gps->points->flag |= GP_SPOINT_SELECT; gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); /* deselect rest? */ if ((extend == false) && (gps->totpoints > 1)) { @@ -795,8 +747,10 @@ static int gpencil_select_first_exec(bContext *C, wmOperator *op) pt->flag &= ~GP_SPOINT_SELECT; } } - changed = true; } + + BKE_gpencil_stroke_select_index_set(gpd, gps); + changed = true; } CTX_DATA_END; @@ -851,7 +805,6 @@ void GPENCIL_OT_select_first(wmOperatorType *ot) static int gpencil_select_last_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* If not edit/sculpt mode, the event has been caught but not processed. */ if (GPENCIL_NONE_EDIT_MODE(gpd)) { @@ -864,35 +817,33 @@ static int gpencil_select_last_exec(bContext *C, wmOperator *op) bool changed = false; CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { /* skip stroke if we're only manipulating selected strokes */ - if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { + if (only_selected && + !((gps->flag & GP_STROKE_SELECT) || + (GPENCIL_STROKE_TYPE_BEZIER(gps) && gps->editcurve->flag & GP_CURVE_SELECT))) { continue; } /* select last point */ BLI_assert(gps->totpoints >= 1); - if (is_curve_edit) { - if (gps->editcurve != NULL) { - bGPDcurve *gpc = gps->editcurve; - gpc->curve_points[gpc->tot_curve_points - 1].flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(&gpc->curve_points[gpc->tot_curve_points - 1].bezt); - gpc->flag |= GP_CURVE_SELECT; - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); - if ((extend == false) && (gps->totpoints > 1)) { - for (int i = 0; i < gpc->tot_curve_points - 1; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(&gpc_pt->bezt); - } + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + + gpc->curve_points[gpc->tot_curve_points - 1].flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(&gpc->curve_points[gpc->tot_curve_points - 1].bezt); + gpc->flag |= GP_CURVE_SELECT; + BKE_gpencil_stroke_select_index_set(gpd, gps); + if ((extend == false) && (gps->totpoints > 1)) { + for (int i = 0; i < gpc->tot_curve_points - 1; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(&gpc_pt->bezt); } - changed = true; } } else { gps->points[gps->totpoints - 1].flag |= GP_SPOINT_SELECT; gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); /* deselect rest? */ if ((extend == false) && (gps->totpoints > 1)) { @@ -904,9 +855,10 @@ static int gpencil_select_last_exec(bContext *C, wmOperator *op) pt->flag &= ~GP_SPOINT_SELECT; } } - - changed = true; } + + BKE_gpencil_stroke_select_index_set(gpd, gps); + changed = true; } CTX_DATA_END; @@ -961,106 +913,98 @@ void GPENCIL_OT_select_last(wmOperatorType *ot) static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* If not edit/sculpt mode, the event has been caught but not processed. */ if (GPENCIL_NONE_EDIT_MODE(gpd)) { return OPERATOR_CANCELLED; } bool changed = false; - if (is_curve_edit) { - GP_EDITABLE_STROKES_BEGIN (gp_iter, C, gpl, gps) { - if (gps->editcurve != NULL && gps->flag & GP_STROKE_SELECT) { - bGPDcurve *editcurve = gps->editcurve; - - bool prev_sel = false; - for (int i = 0; i < editcurve->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &editcurve->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; - if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { - /* selected point - just set flag for next point */ - prev_sel = true; - } - else { - /* unselected point - expand selection if previous was selected... */ - if (prev_sel) { - gpc_pt->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(bezt); - changed = true; - } - prev_sel = false; + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps) && (gps->editcurve->flag & GP_CURVE_SELECT)) { + bGPDcurve *gpc = gps->editcurve; + + bool prev_sel = 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 (gpc_pt->flag & GP_CURVE_POINT_SELECT) { + /* selected point - just set flag for next point */ + prev_sel = true; + } + else { + /* unselected point - expand selection if previous was selected... */ + if (prev_sel) { + gpc_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(bezt); + changed = true; } + prev_sel = false; } + } - prev_sel = false; - for (int i = editcurve->tot_curve_points - 1; i >= 0; i--) { - bGPDcurve_point *gpc_pt = &editcurve->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; - if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { - prev_sel = true; - } - else { - /* unselected point - expand selection if previous was selected... */ - if (prev_sel) { - gpc_pt->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(bezt); - changed = true; - } - prev_sel = false; + prev_sel = false; + for (int i = gpc->tot_curve_points - 1; i >= 0; i--) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + BezTriple *bezt = &gpc_pt->bezt; + if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { + prev_sel = true; + } + else { + /* unselected point - expand selection if previous was selected... */ + if (prev_sel) { + gpc_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(bezt); + changed = true; } + prev_sel = false; } } } - GP_EDITABLE_STROKES_END(gp_iter); - } - else { - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - if (gps->flag & GP_STROKE_SELECT) { - bGPDspoint *pt; - int i; - bool prev_sel; + else if (gps->flag & GP_STROKE_SELECT) { + bGPDspoint *pt; + int i; + bool prev_sel; - /* First Pass: Go in forward order, - * expanding selection if previous was selected (pre changes). - * - This pass covers the "after" edges of selection islands - */ - prev_sel = false; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - /* selected point - just set flag for next point */ - prev_sel = true; - } - else { - /* unselected point - expand selection if previous was selected... */ - if (prev_sel) { - pt->flag |= GP_SPOINT_SELECT; - changed = true; - } - prev_sel = false; + /* First Pass: Go in forward order, + * expanding selection if previous was selected (pre changes). + * - This pass covers the "after" edges of selection islands + */ + prev_sel = false; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->flag & GP_SPOINT_SELECT) { + /* selected point - just set flag for next point */ + prev_sel = true; + } + else { + /* unselected point - expand selection if previous was selected... */ + if (prev_sel) { + pt->flag |= GP_SPOINT_SELECT; + changed = true; } + prev_sel = false; } + } - /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) - * - This pass covers the "before" edges of selection islands - */ - prev_sel = false; - for (pt -= 1; i > 0; i--, pt--) { - if (pt->flag & GP_SPOINT_SELECT) { - prev_sel = true; - } - else { - /* unselected point - expand selection if previous was selected... */ - if (prev_sel) { - pt->flag |= GP_SPOINT_SELECT; - changed = true; - } - prev_sel = false; + /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) + * - This pass covers the "before" edges of selection islands + */ + prev_sel = false; + for (pt -= 1; i > 0; i--, pt--) { + if (pt->flag & GP_SPOINT_SELECT) { + prev_sel = true; + } + else { + /* unselected point - expand selection if previous was selected... */ + if (prev_sel) { + pt->flag |= GP_SPOINT_SELECT; + changed = true; } + prev_sel = false; } } } - CTX_DATA_END; } + CTX_DATA_END; if (changed) { /* updates */ @@ -1100,7 +1044,6 @@ void GPENCIL_OT_select_more(wmOperatorType *ot) static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* If not edit/sculpt mode, the event has been caught but not processed. */ if (GPENCIL_NONE_EDIT_MODE(gpd)) { @@ -1108,105 +1051,115 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op)) } bool changed = false; - if (is_curve_edit) { - GP_EDITABLE_STROKES_BEGIN (gp_iter, C, gpl, gps) { - if (gps->editcurve != NULL && gps->flag & GP_STROKE_SELECT) { - bGPDcurve *editcurve = gps->editcurve; - int i; + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps) && (gps->editcurve->flag & GP_CURVE_SELECT)) { + bGPDcurve *gpc = gps->editcurve; + int tot_selected = 0, num_deselected = 0; - bool prev_sel = false; - for (i = 0; i < editcurve->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &editcurve->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; - if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { - /* shrink if previous wasn't selected */ - if (prev_sel == false) { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(bezt); - changed = true; - } - prev_sel = true; - } - else { - /* mark previous as being unselected - and hence, is trigger for shrinking */ - prev_sel = false; + bool prev_sel = false; + int i; + for (i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + BezTriple *bezt = &gpc_pt->bezt; + if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { + /* shrink if previous wasn't selected */ + if (prev_sel == false) { + gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(bezt); + changed = true; + num_deselected++; } + prev_sel = true; + tot_selected++; + } + else { + /* mark previous as being unselected - and hence, is trigger for shrinking */ + prev_sel = false; } + } - /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) - * - This pass covers the "before" edges of selection islands - */ - prev_sel = false; - for (i = editcurve->tot_curve_points - 1; i > 0; i--) { - bGPDcurve_point *gpc_pt = &editcurve->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; - if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { - /* shrink if previous wasn't selected */ - if (prev_sel == false) { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(bezt); - changed = true; - } - prev_sel = true; - } - else { - /* mark previous as being unselected - and hence, is trigger for shrinking */ - prev_sel = false; + /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) + * - This pass covers the "before" edges of selection islands + */ + prev_sel = false; + for (i = gpc->tot_curve_points - 1; i > 0; i--) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + BezTriple *bezt = &gpc_pt->bezt; + if (gpc_pt->flag & GP_CURVE_POINT_SELECT) { + /* shrink if previous wasn't selected */ + if (prev_sel == false) { + gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(bezt); + changed = true; + num_deselected++; } + prev_sel = true; + } + else { + /* mark previous as being unselected - and hence, is trigger for shrinking */ + prev_sel = false; } } + + /* Deselect curve if all points are deselected. */ + if (tot_selected - num_deselected == 0) { + gpc->flag &= ~GP_CURVE_SELECT; + } } - GP_EDITABLE_STROKES_END(gp_iter); - } - else { - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - if (gps->flag & GP_STROKE_SELECT) { - bGPDspoint *pt; - int i; - bool prev_sel; + else if (gps->flag & GP_STROKE_SELECT) { + bGPDspoint *pt; + int i, tot_selected = 0, num_deselected = 0; + bool prev_sel; - /* First Pass: Go in forward order, shrinking selection - * if previous was not selected (pre changes). - * - This pass covers the "after" edges of selection islands - */ - prev_sel = false; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) { - /* shrink if previous wasn't selected */ - if (prev_sel == false) { - pt->flag &= ~GP_SPOINT_SELECT; - changed = true; - } - prev_sel = true; - } - else { - /* mark previous as being unselected - and hence, is trigger for shrinking */ - prev_sel = false; + /* First Pass: Go in forward order, shrinking selection + * if previous was not selected (pre changes). + * - This pass covers the "after" edges of selection islands + */ + prev_sel = false; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->flag & GP_SPOINT_SELECT) { + /* shrink if previous wasn't selected */ + if (prev_sel == false) { + pt->flag &= ~GP_SPOINT_SELECT; + changed = true; + num_deselected++; } + prev_sel = true; + tot_selected++; + } + else { + /* mark previous as being unselected - and hence, is trigger for shrinking */ + prev_sel = false; } + } - /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) - * - This pass covers the "before" edges of selection islands - */ - prev_sel = false; - for (pt -= 1; i > 0; i--, pt--) { - if (pt->flag & GP_SPOINT_SELECT) { - /* shrink if previous wasn't selected */ - if (prev_sel == false) { - pt->flag &= ~GP_SPOINT_SELECT; - changed = true; - } - prev_sel = true; - } - else { - /* mark previous as being unselected - and hence, is trigger for shrinking */ - prev_sel = false; + /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) + * - This pass covers the "before" edges of selection islands + */ + prev_sel = false; + for (pt -= 1; i > 0; i--, pt--) { + if (pt->flag & GP_SPOINT_SELECT) { + /* shrink if previous wasn't selected */ + if (prev_sel == false) { + pt->flag &= ~GP_SPOINT_SELECT; + changed = true; + num_deselected++; } + prev_sel = true; + } + else { + /* mark previous as being unselected - and hence, is trigger for shrinking */ + prev_sel = false; } } + + /* Deselect curve if all points are deselected. */ + if (tot_selected - num_deselected == 0) { + gps->flag &= ~GP_STROKE_SELECT; + } } - CTX_DATA_END; } + CTX_DATA_END; if (changed) { /* updates */ @@ -1261,8 +1214,7 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd, rcti *rect, const float diff_mat[4][4], const int selectmode, - const float scale, - const bool is_curve_edit) + const float scale) { bGPDspoint *pt = NULL; int x0 = 0, y0 = 0; @@ -1328,23 +1280,13 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd, } } - /* If curve edit mode, generate the curve. */ - if (is_curve_edit && hit && gps_active->editcurve == NULL) { - BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps_active); - gps_active->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - /* Select all curve points. */ - select_all_curve_points(gpd, gps_active, gps_active->editcurve, false); - BKE_gpencil_stroke_geometry_update(gpd, gps_active); - changed = true; - } - /* Ensure that stroke selection is in sync with its points. */ BKE_gpencil_stroke_sync_selection(gpd, gps_active); return changed; } -static bool gpencil_do_curve_circle_sel(bContext *C, +static bool gpencil_curve_do_circle_sel(bContext *C, bGPDstroke *gps, bGPDcurve *gpc, const int mx, @@ -1366,6 +1308,9 @@ static bool gpencil_do_curve_circle_sel(bContext *C, for (int i = 0; i < gpc->tot_curve_points; i++) { bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; BezTriple *bezt = &gpc_pt->bezt; + bGPDcurve_point *gpc_active_pt = (gpc_pt->runtime.gpc_pt_orig) ? gpc_pt->runtime.gpc_pt_orig : + gpc_pt; + BezTriple *bezt_active = &gpc_active_pt->bezt; if (bezt->hide == 1) { continue; @@ -1403,13 +1348,13 @@ static bool gpencil_do_curve_circle_sel(bContext *C, hit = true; /* change selection */ if (select) { - gpc_pt->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_IDX(bezt, j); + gpc_active_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_IDX(bezt_active, j); } else { - BEZT_DESEL_IDX(bezt, j); - if (!BEZT_ISSEL_ANY(bezt)) { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_IDX(bezt_active, j); + if (!BEZT_ISSEL_ANY(bezt_active)) { + gpc_active_pt->flag &= ~GP_CURVE_POINT_SELECT; } } } @@ -1420,20 +1365,31 @@ static bool gpencil_do_curve_circle_sel(bContext *C, if (hit && (selectmode == GP_SELECTMODE_STROKE)) { for (int i = 0; i < gpc->tot_curve_points; i++) { bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; + bGPDcurve_point *gpc_active_pt = (gpc_pt->runtime.gpc_pt_orig) ? + gpc_pt->runtime.gpc_pt_orig : + gpc_pt; + BezTriple *bezt_active = &gpc_active_pt->bezt; if (select) { - gpc_pt->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_ALL(bezt); + gpc_active_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(bezt_active); } else { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(bezt); + gpc_active_pt->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(bezt_active); } } - } - BKE_gpencil_curve_sync_selection(gpd, gps); + if (select) { + gpc->flag |= GP_CURVE_SELECT; + } + else { + gpc->flag &= ~GP_CURVE_SELECT; + } + } + else { + BKE_gpencil_curve_sync_selection(gpd, gps); + } return hit; } @@ -1443,7 +1399,6 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); int selectmode; if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) { @@ -1487,32 +1442,24 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) rect.xmax = mx + radius; rect.ymax = my + radius; - if (is_curve_edit) { - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - ED_gpencil_select_curve_toggle_all(C, SEL_DESELECT); - changed = true; - } + GP_SpaceConversion gsc = {NULL}; + /* init space conversion stuff */ + gpencil_point_conversion_init(C, &gsc); - GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) - { - changed |= gpencil_do_curve_circle_sel( - C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode); - } - GP_EDITABLE_CURVES_END(gps_iter); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + // ED_gpencil_select_curve_toggle_all(C, SEL_DESELECT); + ED_gpencil_select_toggle_all(C, SEL_DESELECT); + changed = true; } - if (changed == false) { - 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; + /* find visible strokes, and select if hit */ + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + changed |= gpencil_curve_do_circle_sel( + C, gps, gpc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode); } - - /* find visible strokes, and select if hit */ - GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + else { changed |= gpencil_stroke_do_circle_sel(gpd, gpl, gps, @@ -1524,11 +1471,10 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) &rect, gpstroke_iter.diff_mat, selectmode, - scale, - is_curve_edit); + scale); } - GP_EVALUATED_STROKES_END(gpstroke_iter); } + GP_EVALUATED_STROKES_END(gpstroke_iter); /* updates */ if (changed) { @@ -1604,7 +1550,7 @@ static bool gpencil_stroke_fill_isect_rect(ARegion *region, int *pt2d = points2d[i]; int screen_co[2]; - gpencil_3d_point_to_screen_space(region, diff_mat, &pt->x, screen_co); + ED_gpencil_3d_point_to_screen_space(region, NULL, diff_mat, &pt->x, screen_co); DO_MINMAX2(screen_co, min, max); copy_v2_v2_int(pt2d, screen_co); @@ -1654,278 +1600,251 @@ static bool gpencil_stroke_fill_isect_rect(ARegion *region, static bool gpencil_generic_curve_select(bContext *C, Object *ob, + bGPdata *gpd, + bGPDstroke *gps, + bGPDcurve *gpc, + struct GP_EditableStrokes_Iter *gpstroke_iter, + GP_SpaceConversion *gsc, GPencilTestFn is_inside_fn, - rcti UNUSED(box), + 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); - bGPdata *gpd = ob->data; + bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; + const bool handle_only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED); const bool handle_all = (v3d->overlay.handle_display == CURVE_HANDLE_ALL); bool hit = false; bool changed = false; bool whole = false; + 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; - 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; + bGPDcurve_point *gpc_pt_active = (gpc_pt->runtime.gpc_pt_orig) ? gpc_pt->runtime.gpc_pt_orig : + gpc_pt; + BezTriple *bezt_active = &gpc_pt_active->bezt; - if (bezt->hide == 1) { - continue; - } + if (bezt_active->hide == 1) { + continue; + } - const bool handles_visible = (handle_all || (handle_only_selected && - (gpc_pt->flag & GP_CURVE_POINT_SELECT))); + 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 (handles_visible) { + for (int j = 0; j < 3; j++) { + const bool is_select = BEZT_ISSEL_IDX(bezt_active, j); + bool is_inside = is_inside_fn( + gsc->region, gpstroke_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->f2 |= SELECT; + gpc_pt_active->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_IDX(bezt_active, j); any_select = true; } else { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - bezt->f2 &= ~SELECT; + gpc_pt_active->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_IDX(bezt_active, j); } changed = true; hit = true; } else { if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - bezt->f2 &= ~SELECT; + gpc_pt_active->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_IDX(bezt_active, j); } } } } } - - /* TODO: Fix selection for filled in curves. */ -#if 0 - 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; + /* if the handles are not visible only check ctrl point (vec[1])*/ + else { + const bool is_select = bezt_active->f2; + bool is_inside = is_inside_fn(gsc->region, gpstroke_iter->diff_mat, bezt->vec[1], user_data); + if (strokemode) { + if (is_inside) { + hit = true; + any_select = true; + } } - - whole = gpencil_stroke_fill_isect_rect(region, gps, gps_iter.diff_mat, box); - } -#endif - /* select the entire curve */ - if (strokemode || whole) { - const int sel_op_result = ED_select_op_action_deselected(sel_op, any_select, hit || whole); - 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; - + 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_ALL(bezt); + gpc_pt_active->flag |= GP_CURVE_POINT_SELECT; + bezt_active->f2 |= SELECT; + any_select = true; } else { - gpc_pt->flag &= ~GP_CURVE_POINT_SELECT; - BEZT_DESEL_ALL(bezt); + gpc_pt_active->flag &= ~GP_CURVE_POINT_SELECT; + bezt_active->f2 &= ~SELECT; + } + changed = true; + hit = true; + } + else { + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + gpc_pt_active->flag &= ~GP_CURVE_POINT_SELECT; + bezt_active->f2 &= ~SELECT; } } + } + } + } + + if (!hit) { + /* check if we selected the inside of a filled curve */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps_active->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + return changed; + } + int mval[2]; + mval[0] = (box.xmax + box.xmin) / 2; + mval[1] = (box.ymax + box.ymin) / 2; + + whole = ED_gpencil_stroke_point_is_inside(gps_active, gsc, mval, gpstroke_iter->diff_mat); + } + + /* select the entire curve */ + if (strokemode || whole) { + const int sel_op_result = ED_select_op_action_deselected(sel_op, any_select, hit || whole); + if (sel_op_result != -1) { + for (int i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + bGPDcurve_point *gpc_pt_active = (gpc_pt->runtime.gpc_pt_orig) ? + gpc_pt->runtime.gpc_pt_orig : + gpc_pt; + BezTriple *bezt_active = &gpc_pt_active->bezt; if (sel_op_result) { - gpc->flag |= GP_CURVE_SELECT; + gpc_pt_active->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(bezt_active); } else { - gpc->flag &= ~GP_CURVE_SELECT; + gpc_pt_active->flag &= ~GP_CURVE_POINT_SELECT; + BEZT_DESEL_ALL(bezt_active); } - changed = true; } - } - BKE_gpencil_curve_sync_selection(gpd, gps); + if (sel_op_result) { + gpc->flag |= GP_CURVE_SELECT; + } + else { + gpc->flag &= ~GP_CURVE_SELECT; + } + changed = true; + } + } + else { + BKE_gpencil_curve_sync_selection(gpd, gps_active); } - GP_EDITABLE_CURVES_END(gps_iter); return changed; } -static bool gpencil_generic_stroke_select(bContext *C, - Object *ob, +static bool gpencil_generic_stroke_select(Object *ob, bGPdata *gpd, + bGPDlayer *gpl, + bGPDstroke *gps, + struct GP_EditableStrokes_Iter *gpstroke_iter, + GP_SpaceConversion *gsc, GPencilTestFn is_inside_fn, rcti box, GP_SelectUserData *user_data, const bool strokemode, const bool segmentmode, const eSelectOp sel_op, - const float scale, - const bool is_curve_edit) + const float scale) { - GP_SpaceConversion gsc = {NULL}; bool changed = false; - /* init space conversion stuff */ - gpencil_point_conversion_init(C, &gsc); - - /* deselect all strokes first? */ - if (SEL_OP_USE_PRE_DESELECT(sel_op) || (GPENCIL_PAINT_MODE(gpd))) { - /* Set selection index to 0. */ - gpd->select_last_index = 0; - - CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - bGPDspoint *pt; - int i; - - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - pt->flag &= ~GP_SPOINT_SELECT; - } - - gps->flag &= ~GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_reset(gps); - } - CTX_DATA_END; - - changed = true; - } - - /* select/deselect points */ - GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; - bool whole = false; + bool whole = false; + bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; - bGPDspoint *pt; - int i; - bool hit = false; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + bGPDspoint *pt; + int i; + bool hit = false; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; - /* convert point coords to screenspace */ - const bool is_inside = is_inside_fn(gsc.region, gpstroke_iter.diff_mat, &pt->x, user_data); - if (strokemode == false) { - const bool is_select = (pt_active->flag & GP_SPOINT_SELECT) != 0; - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT); - changed = true; - hit = true; + /* convert point coords to screenspace */ + const bool is_inside = is_inside_fn(gsc->region, gpstroke_iter->diff_mat, &pt->x, user_data); + if (strokemode == false) { + const bool is_select = (pt_active->flag & GP_SPOINT_SELECT) != 0; + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT); + changed = true; + hit = true; - /* Expand selection to segment. */ - if (segmentmode) { - bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT); - float r_hita[3], r_hitb[3]; - ED_gpencil_select_stroke_segment( - gpd, gpl, gps_active, pt_active, hit_select, false, scale, r_hita, r_hitb); - } - } - } - else { - if (is_inside) { - hit = true; - break; + /* Expand selection to segment. */ + if (segmentmode) { + bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT); + float r_hita[3], r_hitb[3]; + ED_gpencil_select_stroke_segment( + gpd, gpl, gps_active, pt_active, hit_select, false, scale, r_hita, r_hitb); } } } - - /* If nothing hit, check if the mouse is inside a filled stroke using the center or - * Box or lasso area. */ - if (!hit) { - /* Only check filled strokes. */ - MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); - if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { - continue; + else { + if (is_inside) { + hit = true; + break; } - int mval[2]; - mval[0] = (box.xmax + box.xmin) / 2; - mval[1] = (box.ymax + box.ymin) / 2; + } + } - whole = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat); + /* If nothing hit, check if the mouse is inside a filled stroke using the center or + * Box or lasso area. */ + if (!hit) { + /* Only check filled strokes. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps_active->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + return changed; } + int mval[2]; + mval[0] = (box.xmax + box.xmin) / 2; + mval[1] = (box.ymax + box.ymin) / 2; - /* if stroke mode expand selection. */ - if ((strokemode) || (whole)) { - const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole; - const bool is_inside = hit || whole; - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + whole = ED_gpencil_stroke_point_is_inside(gps_active, gsc, mval, gpstroke_iter->diff_mat); + } - if (sel_op_result) { - pt_active->flag |= GP_SPOINT_SELECT; - } - else { - pt_active->flag &= ~GP_SPOINT_SELECT; - } + /* if stroke mode expand selection. */ + if ((strokemode) || (whole)) { + const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole; + const bool is_inside = hit || whole; + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) { + bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + + if (sel_op_result) { + pt_active->flag |= GP_SPOINT_SELECT; + } + else { + pt_active->flag &= ~GP_SPOINT_SELECT; } - changed = true; } - } - - /* If curve edit mode, generate the curve. */ - if (is_curve_edit && (hit || whole) && gps_active->editcurve == NULL) { - BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps_active); - gps_active->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - /* Select all curve points. */ - select_all_curve_points(gpd, gps_active, gps_active->editcurve, false); - BKE_gpencil_stroke_geometry_update(gpd, gps_active); changed = true; } - - /* Ensure that stroke selection is in sync with its points */ - BKE_gpencil_stroke_sync_selection(gpd, gps_active); } - GP_EVALUATED_STROKES_END(gpstroke_iter); + + /* Ensure that stroke selection is in sync with its points */ + BKE_gpencil_stroke_sync_selection(gpd, gps_active); return changed; } @@ -1940,7 +1859,6 @@ static int gpencil_generic_select_exec(bContext *C, bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *area = CTX_wm_area(C); - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); int selectmode; if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) { @@ -1961,38 +1879,69 @@ static int gpencil_generic_select_exec(bContext *C, const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const float scale = ts->gp_sculpt.isect_threshold; - bool changed = false; - /* sanity checks */ if (area == NULL) { BKE_report(op->reports, RPT_ERROR, "No active area"); return OPERATOR_CANCELLED; } - if (is_curve_edit) { - changed = gpencil_generic_curve_select( - C, ob, is_inside_fn, box, user_data, strokemode, sel_op); + bool changed = false; + GP_SpaceConversion gsc = {NULL}; + /* init space conversion stuff */ + gpencil_point_conversion_init(C, &gsc); + + /* deselect all strokes first? */ + if (SEL_OP_USE_PRE_DESELECT(sel_op) || (GPENCIL_PAINT_MODE(gpd))) { + /* Set selection index to 0. */ + gpd->select_last_index = 0; + + deselect_all_selected(C); + changed = true; } - if (changed == false) { - changed = gpencil_generic_stroke_select(C, - ob, - gpd, - is_inside_fn, - box, - user_data, - strokemode, - segmentmode, - sel_op, - scale, - is_curve_edit); + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + if (gpencil_generic_curve_select(C, + ob, + gpd, + gps, + gpc, + &gpstroke_iter, + &gsc, + is_inside_fn, + box, + user_data, + strokemode, + sel_op)) { + changed = true; + } + } + else { + if (gpencil_generic_stroke_select(ob, + gpd, + gpl, + gps, + &gpstroke_iter, + &gsc, + is_inside_fn, + box, + user_data, + strokemode, + segmentmode, + sel_op, + scale)) { + changed = true; + } + } } + GP_EVALUATED_STROKES_END(gpstroke_iter); /* if paint mode,delete selected points */ if (GPENCIL_PAINT_MODE(gpd)) { gpencil_delete_selected_point_wrap(C); - changed = true; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + changed = true; } /* updates */ @@ -2020,7 +1969,7 @@ static bool gpencil_test_box(ARegion *region, GP_SelectUserData *user_data) { int co[2] = {0}; - if (gpencil_3d_point_to_screen_space(region, diff_mat, pt, co)) { + if (ED_gpencil_3d_point_to_screen_space(region, NULL, diff_mat, pt, co)) { return BLI_rcti_isect_pt(&user_data->rect, co[0], co[1]); } return false; @@ -2069,7 +2018,7 @@ static bool gpencil_test_lasso(ARegion *region, GP_SelectUserData *user_data) { int co[2] = {0}; - if (gpencil_3d_point_to_screen_space(region, diff_mat, pt, co)) { + if (ED_gpencil_3d_point_to_screen_space(region, NULL, diff_mat, pt, co)) { /* test if in lasso boundbox + within the lasso noose */ return (BLI_rcti_isect_pt(&user_data->rect, co[0], co[1]) && BLI_lasso_is_point_inside( @@ -2125,56 +2074,93 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot) /** \name Mouse Pick Select Operator * \{ */ -static void gpencil_select_curve_point(bContext *C, - const int mval[2], - const int radius_squared, - bGPDlayer **r_gpl, - bGPDstroke **r_gps, - bGPDcurve **r_gpc, - bGPDcurve_point **r_pt, - char *handle) +static bool gpencil_select_curve_point_closest(bContext *C, + bGPDcurve *gpc, + struct GP_EditableStrokes_Iter *gps_iter, + const int mval[2], + const int radius_squared, + bGPDcurve_point **r_pt, + int *handle_idx, + int *hit_distance) { + bool hit = false; ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); const bool only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED); - int hit_distance = radius_squared; + for (int i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + BezTriple *bezt = &gpc_pt->bezt; - GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) - { - for (int i = 0; i < gpc->tot_curve_points; i++) { - bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; - BezTriple *bezt = &gpc_pt->bezt; + bGPDcurve_point *gpc_pt_active = (gpc_pt->runtime.gpc_pt_orig) ? gpc_pt->runtime.gpc_pt_orig : + gpc_pt; + BezTriple *bezt_active = &gpc_pt_active->bezt; - if (bezt->hide == 1) { - continue; + if (bezt_active->hide == 1) { + continue; + } + + const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) && + (!only_selected || BEZT_ISSEL_ANY(bezt)); + + /* if the handles are not visible only check ctrl point (vec[1])*/ + int from = (!handles_visible) ? 1 : 0; + int to = (!handles_visible) ? 2 : 3; + + for (int j = from; j < to; j++) { + int screen_co[2]; + if (ED_gpencil_3d_point_to_screen_space( + region, NULL, gps_iter->diff_mat, bezt->vec[j], screen_co)) { + const int pt_distance = len_manhattan_v2v2_int(mval, screen_co); + + if (pt_distance <= radius_squared && pt_distance < *hit_distance) { + *r_pt = gpc_pt_active; + *handle_idx = j; + *hit_distance = pt_distance; + hit = true; + } } + } + } - const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) && - (!only_selected || BEZT_ISSEL_ANY(bezt)); + return hit; +} + +static bool gpencil_select_stroke_point_closest(bGPDstroke *gps, + struct GP_EditableStrokes_Iter *gps_iter, + GP_SpaceConversion *gsc, + const int mval[2], + const int radius_squared, + bGPDspoint **r_pt, + int *hit_distance) +{ + bool hit = false; + bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; - /* If the handles are not visible only check control point (vec[1]). */ - int from = (!handles_visible) ? 1 : 0; - int to = (!handles_visible) ? 2 : 3; + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; + int xy[2]; - for (int j = from; j < to; j++) { - int screen_co[2]; - if (gpencil_3d_point_to_screen_space(region, gps_iter.diff_mat, bezt->vec[j], screen_co)) { - const int pt_distance = len_manhattan_v2v2_int(mval, screen_co); + bGPDspoint pt2; + gpencil_point_to_parent_space(pt, gps_iter->diff_mat, &pt2); + gpencil_point_to_xy(gsc, gps_active, &pt2, &xy[0], &xy[1]); - if (pt_distance <= radius_squared && pt_distance < hit_distance) { - *r_gpl = gpl; - *r_gps = gps; - *r_gpc = gpc; - *r_pt = gpc_pt; - *handle = j; - hit_distance = pt_distance; - } - } + /* do boundbox check first */ + if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) { + const int pt_distance = len_manhattan_v2v2_int(mval, xy); + + /* check if point is inside */ + if (pt_distance <= radius_squared && pt_distance < *hit_distance) { + /* only use this point if it is a better match than the current hit - T44685 */ + *r_pt = pt_active; + *hit_distance = pt_distance; + hit = true; } } } - GP_EDITABLE_CURVES_END(gps_iter); + + return hit; } static int gpencil_select_exec(bContext *C, wmOperator *op) @@ -2184,7 +2170,6 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; - const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd); /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */ const float radius = 0.4f * U.widget_unit; @@ -2201,14 +2186,12 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* get mouse location */ RNA_int_get_array(op->ptr, "location", mval); - GP_SpaceConversion gsc = {NULL}; - bGPDlayer *hit_layer = NULL; bGPDstroke *hit_stroke = NULL; bGPDspoint *hit_point = NULL; bGPDcurve *hit_curve = NULL; bGPDcurve_point *hit_curve_point = NULL; - char hit_curve_handle = 0; + int hit_curve_handle_idx = 0; int hit_distance = radius_squared; /* sanity checks */ @@ -2230,62 +2213,45 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE); } - if (is_curve_edit) { - gpencil_select_curve_point(C, - mval, - radius_squared, - &hit_layer, - &hit_stroke, - &hit_curve, - &hit_curve_point, - &hit_curve_handle); - } - - if (hit_curve == NULL) { - /* init space conversion stuff */ - gpencil_point_conversion_init(C, &gsc); - - /* First Pass: Find stroke point which gets hit */ - GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; - bGPDspoint *pt; - int i; + GP_SpaceConversion gsc = {NULL}; + /* init space conversion stuff */ + gpencil_point_conversion_init(C, &gsc); - /* firstly, check for hit-point */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - int xy[2]; - - bGPDspoint pt2; - gpencil_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2); - gpencil_point_to_xy(&gsc, gps_active, &pt2, &xy[0], &xy[1]); - - /* do boundbox check first */ - if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) { - const int pt_distance = len_manhattan_v2v2_int(mval, xy); - - /* check if point is inside */ - if (pt_distance <= radius_squared) { - /* only use this point if it is a better match than the current hit - T44685 */ - if (pt_distance < hit_distance) { - hit_layer = gpl; - hit_stroke = gps_active; - hit_point = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; - hit_distance = pt_distance; - } - } - } + /* First Pass: Find point which gets hit */ + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { + bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + if (gpencil_select_curve_point_closest(C, + gpc, + &gpstroke_iter, + mval, + radius_squared, + &hit_curve_point, + &hit_curve_handle_idx, + &hit_distance)) { + hit_layer = gpl; + hit_stroke = gps_active; + hit_point = &gps_active->points[hit_curve_point->point_index]; + hit_curve = gps_active->editcurve; + } + } + else { + if (gpencil_select_stroke_point_closest( + gps, &gpstroke_iter, &gsc, mval, radius_squared, &hit_point, &hit_distance)) { + hit_layer = gpl; + hit_stroke = gps_active; } } - GP_EVALUATED_STROKES_END(gpstroke_iter); } + GP_EVALUATED_STROKES_END(gpstroke_iter); /* Abort if nothing hit... */ - if (!hit_curve && !hit_curve_point && !hit_point && !hit_stroke) { - + if ((hit_curve == NULL && hit_curve_point == NULL) && + (hit_point == NULL && hit_stroke == NULL)) { if (deselect_all) { /* since left mouse select change, deselect all if click outside any hit */ deselect_all_selected(C); - /* copy on write tag is needed, or else no refresh happens */ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE); @@ -2298,23 +2264,17 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* select all handles if the click was on the curve but not on a handle */ - if (is_curve_edit && hit_point != NULL) { - whole = true; - hit_curve = hit_stroke->editcurve; - } - /* adjust selection behavior - for toggle option */ if (toggle) { if (hit_curve_point != NULL) { BezTriple *bezt = &hit_curve_point->bezt; - if ((bezt->f1 & SELECT) && (hit_curve_handle == 0)) { + if ((bezt->f1 & SELECT) && (hit_curve_handle_idx == 0)) { deselect = true; } - if ((bezt->f2 & SELECT) && (hit_curve_handle == 1)) { + if ((bezt->f2 & SELECT) && (hit_curve_handle_idx == 1)) { deselect = true; } - if ((bezt->f3 & SELECT) && (hit_curve_handle == 2)) { + if ((bezt->f3 & SELECT) && (hit_curve_handle_idx == 2)) { deselect = true; } } @@ -2330,13 +2290,6 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* Perform selection operations... */ if (whole) { - /* Generate editcurve if it does not exist */ - if (is_curve_edit && hit_curve == NULL) { - BKE_gpencil_stroke_editcurve_update(gpd, hit_layer, hit_stroke); - hit_stroke->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; - BKE_gpencil_stroke_geometry_update(gpd, hit_stroke); - hit_curve = hit_stroke->editcurve; - } /* select all curve points */ if (hit_curve != NULL) { select_all_curve_points(gpd, hit_stroke, hit_curve, deselect); @@ -2371,9 +2324,8 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) if (deselect == false) { if (hit_curve_point != NULL) { hit_curve_point->flag |= GP_CURVE_POINT_SELECT; - BEZT_SEL_IDX(&hit_curve_point->bezt, hit_curve_handle); + BEZT_SEL_IDX(&hit_curve_point->bezt, hit_curve_handle_idx); hit_curve->flag |= GP_CURVE_SELECT; - hit_stroke->flag |= GP_STROKE_SELECT; BKE_gpencil_stroke_select_index_set(gpd, hit_stroke); } else { @@ -2404,7 +2356,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } else { if (hit_curve_point != NULL) { - BEZT_DESEL_IDX(&hit_curve_point->bezt, hit_curve_handle); + BEZT_DESEL_IDX(&hit_curve_point->bezt, hit_curve_handle_idx); if (!BEZT_ISSEL_ANY(&hit_curve_point->bezt)) { hit_curve_point->flag &= ~GP_CURVE_POINT_SELECT; } @@ -2487,8 +2439,12 @@ void GPENCIL_OT_select(wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "use_shift_extend", false, "Extend", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select by Vertex Color + * \{ */ -/* Select by Vertex Color. */ /* Helper to create a hash of colors. */ static void gpencil_selected_hue_table(bContext *C, Object *ob, @@ -2508,22 +2464,43 @@ static void gpencil_selected_hue_table(bContext *C, if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } - if ((gps->flag & GP_STROKE_SELECT) == 0) { - continue; - } /* Read all points to get all colors selected. */ - bGPDspoint *pt; - int i; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (((pt->flag & GP_SPOINT_SELECT) == 0) || (pt->vert_color[3] == 0.0f)) { + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + if ((gpc->flag & GP_CURVE_SELECT) == 0) { + continue; + } + + for (int i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + if (((gpc_pt->flag & GP_CURVE_POINT_SELECT) == 0) || (gpc_pt->vert_color[3] == 0.0f)) { + continue; + } + /* Round Hue value. */ + rgb_to_hsv_compat_v(gpc_pt->vert_color, hsv); + uint key = truncf(hsv[0] * range); + if (!BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { + BLI_ghash_insert(hue_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + } + } + } + else { + if ((gps->flag & GP_STROKE_SELECT) == 0) { continue; } - /* Round Hue value. */ - rgb_to_hsv_compat_v(pt->vert_color, hsv); - uint key = truncf(hsv[0] * range); - if (!BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { - BLI_ghash_insert(hue_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + if (((pt->flag & GP_SPOINT_SELECT) == 0) || (pt->vert_color[3] == 0.0f)) { + continue; + } + /* Round Hue value. */ + rgb_to_hsv_compat_v(pt->vert_color, hsv); + uint key = truncf(hsv[0] * range); + if (!BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { + BLI_ghash_insert(hue_table, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + } } } } @@ -2577,39 +2554,77 @@ static int gpencil_select_vertex_color_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + deselect_all_selected(C); + /* Select any visible stroke that uses any of these colors. */ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { - bGPDspoint *pt; - int i; - bool gps_selected = false; - /* Check all stroke points. */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->vert_color[3] == 0.0f) { - continue; + if (GPENCIL_STROKE_TYPE_BEZIER(gps)) { + bGPDcurve *gpc = gps->editcurve; + bool gpc_selected = false; + for (int i = 0; i < gpc->tot_curve_points; i++) { + bGPDcurve_point *gpc_pt = &gpc->curve_points[i]; + if (gpc_pt->vert_color[3] == 0.0f) { + continue; + } + + /* Only check Hue to get value and saturation full ranges. */ + float hsv[3]; + /* Round Hue value. */ + rgb_to_hsv_compat_v(gpc_pt->vert_color, hsv); + uint key = truncf(hsv[0] * range); + + if (BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { + gpc_pt->flag |= GP_CURVE_POINT_SELECT; + BEZT_SEL_ALL(&gpc_pt->bezt); + gpc_selected = true; + changed = true; + } } - /* Only check Hue to get value and saturation full ranges. */ - float hsv[3]; - /* Round Hue value. */ - rgb_to_hsv_compat_v(pt->vert_color, hsv); - uint key = truncf(hsv[0] * range); + if (gpc_selected) { + gpc->flag |= GP_CURVE_SELECT; + BKE_gpencil_stroke_select_index_set(gpd, gps); - if (BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { - pt->flag |= GP_SPOINT_SELECT; - gps_selected = true; + /* Extend selection. */ + if (selectmode == GP_SELECTMODE_STROKE) { + select_all_curve_points(gpd, gps, gpc, false); + } } } + else { + bGPDspoint *pt; + int i; + bool gps_selected = false; + /* Check all stroke points. */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->vert_color[3] == 0.0f) { + continue; + } - if (gps_selected) { - gps->flag |= GP_STROKE_SELECT; - BKE_gpencil_stroke_select_index_set(gpd, gps); + /* Only check Hue to get value and saturation full ranges. */ + float hsv[3]; + /* Round Hue value. */ + rgb_to_hsv_compat_v(pt->vert_color, hsv); + uint key = truncf(hsv[0] * range); - /* Extend stroke selection. */ - if (selectmode == GP_SELECTMODE_STROKE) { - bGPDspoint *pt1 = NULL; + if (BLI_ghash_haskey(hue_table, POINTER_FROM_INT(key))) { + pt->flag |= GP_SPOINT_SELECT; + gps_selected = true; + changed = true; + } + } - for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) { - pt1->flag |= GP_SPOINT_SELECT; + if (gps_selected) { + gps->flag |= GP_STROKE_SELECT; + BKE_gpencil_stroke_select_index_set(gpd, gps); + + /* Extend stroke selection. */ + if (selectmode == GP_SELECTMODE_STROKE) { + bGPDspoint *pt1 = NULL; + + for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) { + pt1->flag |= GP_SPOINT_SELECT; + } } } } |