diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 55922da3892..a77302ff4ae 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1269,6 +1269,7 @@ class CLIP_MT_mask(Menu): layout.separator() layout.operator("mask.cyclic_toggle") layout.operator("mask.switch_direction") + layout.operator("mask.normals_make_consistent") layout.operator("mask.feather_weight_clear") # TODO, better place? layout.separator() diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 24f55f66bb8..52711c8da55 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -207,6 +207,7 @@ void ED_operatortypes_mask(void) /* geometry */ WM_operatortype_append(MASK_OT_switch_direction); + WM_operatortype_append(MASK_OT_normals_make_consistent); WM_operatortype_append(MASK_OT_delete); /* select */ @@ -307,6 +308,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0); // WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0); /* ... matches curve editmode */ RNA_enum_set(WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", TFM_MASK_SHRINKFATTEN); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index fc6089238a1..c34558d2a01 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -56,6 +56,7 @@ void MASK_OT_hide_view_clear(struct wmOperatorType *ot); void MASK_OT_hide_view_set(struct wmOperatorType *ot); void MASK_OT_feather_weight_clear(struct wmOperatorType *ot); void MASK_OT_switch_direction(struct wmOperatorType *ot); +void MASK_OT_normals_make_consistent(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 315e40380f9..b770e5e9dba 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -992,6 +992,7 @@ void MASK_OT_delete(wmOperatorType *ot) /* *** switch direction *** */ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; @@ -1000,6 +1001,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) /* do actual selection */ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; + int change_layer = FALSE; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; @@ -1009,6 +1011,13 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_mask_spline_select_check(spline)) { BKE_mask_spline_direction_switch(masklay, spline); change = TRUE; + change_layer = TRUE; + } + } + + if (change_layer) { + if (IS_AUTOKEY_ON(scene)) { + ED_mask_layer_shape_auto_key(masklay, CFRA); } } } @@ -1041,6 +1050,73 @@ void MASK_OT_switch_direction(wmOperatorType *ot) } +/* *** recalc normals *** */ +static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + int i; + + int change = FALSE; + + /* do actual selection */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + int change_layer = FALSE; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + BKE_mask_calc_handle_point_auto(spline, point, FALSE); + change = TRUE; + change_layer = TRUE; + } + } + } + + if (change_layer) { + if (IS_AUTOKEY_ON(scene)) { + ED_mask_layer_shape_auto_key(masklay, CFRA); + } + } + } + + if (change) { + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + + WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +/* named to match mesh recalc normals */ +void MASK_OT_normals_make_consistent(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Recalc Normals"; + ot->description = "Re-calculate the direction of selected handles"; + ot->idname = "MASK_OT_normals_make_consistent"; + + /* api callbacks */ + ot->exec = mask_normals_make_consistent_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + /******************** set handle type *********************/ static int set_handle_type_exec(bContext *C, wmOperator *op)