diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_mask_common.py | 5 | ||||
-rw-r--r-- | source/blender/editors/mask/mask_edit.c | 5 | ||||
-rw-r--r-- | source/blender/editors/mask/mask_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/mask/mask_select.c | 112 |
4 files changed, 124 insertions, 0 deletions
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index c9b1bc0ccff..d38f5f934b4 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -339,6 +339,11 @@ class MASK_MT_select(Menu): layout.separator() + layout.operator("mask.select_more") + layout.operator("mask.select_less") + + layout.separator() + layout.operator("mask.select_all").action = 'TOGGLE' layout.operator("mask.select_all", text="Inverse").action = 'INVERT' diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index cd2995be439..9ae5b436fb3 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -390,6 +390,8 @@ void ED_operatortypes_mask(void) WM_operatortype_append(MASK_OT_select_circle); WM_operatortype_append(MASK_OT_select_linked_pick); WM_operatortype_append(MASK_OT_select_linked); + WM_operatortype_append(MASK_OT_select_more); + WM_operatortype_append(MASK_OT_select_less); /* hide/reveal */ WM_operatortype_append(MASK_OT_hide_view_clear); @@ -466,6 +468,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "MASK_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "deselect", TRUE); + WM_keymap_add_item(keymap, "MASK_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); + /* hide/reveal */ WM_keymap_add_item(keymap, "MASK_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); kmi = WM_keymap_add_item(keymap, "MASK_OT_hide_view_set", HKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index fcfcfb237e9..bd148c48980 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -88,6 +88,8 @@ void MASK_OT_select_lasso(struct wmOperatorType *ot); void MASK_OT_select_circle(struct wmOperatorType *ot); void MASK_OT_select_linked_pick(struct wmOperatorType *ot); void MASK_OT_select_linked(struct wmOperatorType *ot); +void MASK_OT_select_more(struct wmOperatorType *ot); +void MASK_OT_select_less(struct wmOperatorType *ot); int ED_mask_spline_select_check(struct MaskSpline *spline); int ED_mask_layer_select_check(struct MaskLayer *masklay); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 997f170c9f9..774a920f366 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -793,3 +793,115 @@ void MASK_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/**************** Select more/less **************/ + +static int mask_select_more_less(bContext *C, bool more) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + bool start_sel, end_sel, prev_sel, cur_sel, cyclic = spline->flag & MASK_SPLINE_CYCLIC; + + // reselect point if any handle is selected to make the result more predictable + for (i = 0; i < spline->tot_point; i++) { + BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i)); + } + + // select more/less does not affect empty/single point splines + if (spline->tot_point < 2) { + continue; + } + + if (cyclic) { + start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points); + end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]); + } + + for (i = 0; i < spline->tot_point; i++) { + if (i == 0 && !cyclic) { + continue; + } + + prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel; + cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]); + + if (cur_sel != more) { + if (prev_sel == more) { + BKE_mask_point_select_set(&spline->points[i], more); + } + i++; + } + } + + for (i = spline->tot_point - 1; i >= 0; i--) { + if (i == spline->tot_point - 1 && !cyclic) { + continue; + } + + prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) : start_sel; + cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]); + + if (cur_sel != more) { + if (prev_sel == more) { + BKE_mask_point_select_set(&spline->points[i], more); + } + i--; + } + } + } + } + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; +} + +static int mask_select_more_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mask_select_more_less(C, true); +} + +void MASK_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->idname = "MASK_OT_select_more"; + ot->description = "Select more spline points connected to initial selection"; + + /* api callbacks */ + ot->exec = mask_select_more_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mask_select_less_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mask_select_more_less(C, false); +} + +void MASK_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->idname = "MASK_OT_select_less"; + ot->description = "Deselect spline points at the boundary of each selection region"; + + /* api callbacks */ + ot->exec = mask_select_less_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} |