diff options
Diffstat (limited to 'source/blender/editors/mask/mask_ops.c')
-rw-r--r-- | source/blender/editors/mask/mask_ops.c | 148 |
1 files changed, 133 insertions, 15 deletions
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index a882284f5e3..9f8388f1fe0 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -458,7 +458,8 @@ enum { SLIDE_ACTION_NONE = 0, SLIDE_ACTION_POINT = 1, SLIDE_ACTION_HANDLE = 2, - SLIDE_ACTION_FEATHER = 3 + SLIDE_ACTION_FEATHER = 3, + SLIDE_ACTION_SPLINE = 4 }; typedef struct SlidePointData { @@ -497,6 +498,96 @@ typedef struct SlidePointData { float weight, weight_scalar; } SlidePointData; +static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2]) +{ + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co); + ED_clip_point_undistorted_pos(sc, r_co, r_co); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co); +} + +static bool spline_under_mouse_get(const bContext *C, + Mask *mask, const float co[2], + MaskLayer **mask_layer_r, + MaskSpline **mask_spline_r) +{ + ScrArea *sa = CTX_wm_area(C); + SpaceClip *sc = CTX_wm_space_clip(C); + MaskLayer *mask_layer; + int width, height; + float pixel_co[2]; + float closest_dist_squared; + MaskLayer *closest_layer = NULL; + MaskSpline *closest_spline = NULL; + bool undistort = false; + *mask_layer_r = NULL; + *mask_spline_r = NULL; + ED_mask_get_size(sa, &width, &height); + pixel_co[0] = co[0] * width; + pixel_co[1] = co[1] * height; + if (sc != NULL) { + undistort = (sc->clip != NULL) && + (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; + } + for (mask_layer = mask->masklayers.first; + mask_layer != NULL; + mask_layer = mask_layer->next) + { + MaskSpline *spline; + if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + continue; + } + + for (spline = mask_layer->splines.first; + spline != NULL; + spline = spline->next) + { + MaskSplinePoint *points_array; + float min[2], max[2], center[2]; + float dist_squared; + int i; + float max_bb_side; + if ((spline->flag & SELECT) == 0) { + continue; + } + + points_array = BKE_mask_spline_point_array(spline); + INIT_MINMAX2(min, max); + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point_deform = &points_array[i]; + BezTriple *bezt = &point_deform->bezt; + + float vert[2]; + + copy_v2_v2(vert, bezt->vec[1]); + + if (undistort) { + mask_point_undistort_pos(sc, vert, vert); + } + + minmax_v2v2_v2(min, max, vert); + } + + center[0] = (min[0] + max[0]) / 2.0f * width; + center[1] = (min[1] + max[1]) / 2.0f * height; + dist_squared = len_squared_v2v2(pixel_co, center); + max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height); + if (dist_squared <= max_bb_side * max_bb_side * 0.5f && + (closest_spline == NULL || dist_squared < closest_dist_squared)) + { + closest_layer = mask_layer; + closest_spline = spline; + closest_dist_squared = dist_squared; + } + } + } + if (closest_spline != NULL) { + *mask_layer_r = closest_layer; + *mask_spline_r = closest_spline; + return true; + } + return false; +} + static bool slide_point_check_initial_feather(MaskSpline *spline) { int i; @@ -607,9 +698,14 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * point = cv_point; } - if (action != SLIDE_ACTION_NONE) { - select_sliding_point(mask, masklay, spline, point, which_handle); + if (action == SLIDE_ACTION_NONE) { + if (spline_under_mouse_get(C, mask, co, &masklay, &spline)) { + action = SLIDE_ACTION_SPLINE; + point = NULL; + } + } + if (action != SLIDE_ACTION_NONE) { customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data"); customdata->event_invoke_type = event->type; customdata->mask = mask; @@ -621,12 +717,14 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * customdata->action = action; customdata->uw = uw; - customdata->old_h1 = point->bezt.h1; - customdata->old_h2 = point->bezt.h2; - customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point"); - check_sliding_handle_type(point, which_handle); + if (customdata->action != SLIDE_ACTION_SPLINE) { + customdata->old_h1 = point->bezt.h1; + customdata->old_h2 = point->bezt.h2; + select_sliding_point(mask, masklay, spline, point, which_handle); + check_sliding_handle_type(point, which_handle); + } if (uw) { float co_uw[2]; @@ -639,7 +737,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar); } - else { + else if (customdata->action != SLIDE_ACTION_SPLINE) { BezTriple *bezt = &point->bezt; customdata->weight = bezt->weight; @@ -653,10 +751,12 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * customdata->is_initial_feather = slide_point_check_initial_feather(spline); } - copy_m3_m3(customdata->vec, point->bezt.vec); - if (which_handle != MASK_WHICH_HANDLE_NONE) { - BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord); - copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord); + if (customdata->action != SLIDE_ACTION_SPLINE) { + copy_m3_m3(customdata->vec, point->bezt.vec); + if (which_handle != MASK_WHICH_HANDLE_NONE) { + BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord); + copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord); + } } customdata->which_handle = which_handle; @@ -738,7 +838,7 @@ static void cancel_slide_point(SlidePointData *data) else data->point->bezt.weight = data->weight; } - else { + else if (data->action != SLIDE_ACTION_SPLINE) { copy_m3_m3(data->point->bezt.vec, data->vec); data->point->bezt.h1 = data->old_h1; data->point->bezt.h2 = data->old_h2; @@ -935,6 +1035,20 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) copy_v2_v2(data->prev_feather_coord, offco); } } + else if (data->action == SLIDE_ACTION_SPLINE) { + int i; + + if (data->orig_spline == NULL) { + data->orig_spline = BKE_mask_spline_copy(data->spline); + } + + for (i = 0; i < data->spline->tot_point; i++) { + MaskSplinePoint *point = &data->spline->points[i]; + add_v2_v2(point->bezt.vec[0], delta); + add_v2_v2(point->bezt.vec[1], delta); + add_v2_v2(point->bezt.vec[2], delta); + } + } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); @@ -970,8 +1084,12 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) free_slide_point_data(op->customdata); /* keep this last! */ return OPERATOR_FINISHED; } - - break; + else if (event->type != data->event_invoke_type && event->val == KM_PRESS) { + /* pass to ESCKEY */ + } + else { + break; + } case ESCKEY: cancel_slide_point(op->customdata); |