GPencil: fix separate points/strokes freezing with empty selection

Code would still create an object (without setting up materials), code
for removing unused material slots would then freeze.

Now return/cancel early in case of empty selection.

This came up in T88269 [which is still not fully fixed, transforming
curve edit points clear their GP_STROKE_SELECT flag which now results in
the early exit, should be looked at separately]

Maniphest Tasks: T88269

Differential Revision: https://developer.blender.org/D11252
This commit is contained in:
Philipp Oeser 2021-05-14 13:21:10 +02:00
parent d19d79c5a6
commit c3e13d5a2b
Notes: blender-bot 2023-02-14 06:49:57 +01:00
Referenced by issue #88269, Crash in Curve Editing.
3 changed files with 53 additions and 2 deletions

View File

@ -4520,6 +4520,9 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
/* sanity checks */
if (ELEM(NULL, gpd_src)) {
return OPERATOR_CANCELLED;
@ -4530,8 +4533,22 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
/* Cancel if nothing selected. */
if (ELEM(mode, GP_SEPARATE_POINT, GP_SEPARATE_STROKE)) {
bool has_selected = false;
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
if (ED_gpencil_layer_has_selected_stroke(gpl, is_multiedit)) {
has_selected = true;
break;
}
}
CTX_DATA_END;
if (!has_selected) {
BKE_report(op->reports, RPT_ERROR, "Nothing selected");
return OPERATOR_CANCELLED;
}
}
/* Create a new object. */
/* Take into account user preferences for duplicating actions. */

View File

@ -542,6 +542,38 @@ bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0,
return false;
}
/* ******************************************************** */
/* Selection Validity Testing */
bool ED_gpencil_frame_has_selected_stroke(const bGPDframe *gpf)
{
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
return true;
}
}
return false;
}
bool ED_gpencil_layer_has_selected_stroke(const bGPDlayer *gpl, const bool is_multiedit)
{
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
if (ED_gpencil_frame_has_selected_stroke(gpf)) {
return true;
}
}
/* If not multiedit, exit loop. */
if (!is_multiedit) {
break;
}
}
return false;
}
/* ******************************************************** */
/* Stroke Validity Testing */

View File

@ -144,6 +144,8 @@ bool ED_gpencil_data_owner_is_annotation(struct PointerRNA *owner_ptr);
bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra);
/* ----------- Stroke Editing Utilities ---------------- */
bool ED_gpencil_frame_has_selected_stroke(const struct bGPDframe *gpf);
bool ED_gpencil_layer_has_selected_stroke(const struct bGPDlayer *gpl, const bool is_multiedit);
bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);