diff options
-rw-r--r-- | source/blender/editors/mask/mask_draw.c | 39 | ||||
-rw-r--r-- | source/blender/editors/mask/mask_ops.c | 140 |
2 files changed, 162 insertions, 17 deletions
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index c2b949f6acb..94092036cb9 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -133,9 +133,12 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c } static void draw_circle(const float x, const float y, - const float size, const float xscale, const float yscale) + const float size, const bool fill, + const float xscale, const float yscale) { - static GLuint displist = 0; + static GLuint wire_displist = 0; + static GLuint fill_displist = 0; + GLuint displist = fill ? fill_displist : wire_displist; /* Initialize round circle shape. */ if (displist == 0) { @@ -145,11 +148,18 @@ static void draw_circle(const float x, const float y, glNewList(displist, GL_COMPILE); qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + gluQuadricDrawStyle(qobj, fill ? GLU_FILL : GLU_SILHOUETTE); gluDisk(qobj, 0, 0.7, 8, 1); gluDeleteQuadric(qobj); glEndList(); + + if (fill) { + fill_displist = displist; + } + else { + wire_displist = displist; + } } glPushMatrix(); @@ -219,7 +229,7 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin UI_ThemeColor(TH_HANDLE_VERTEX); } - draw_circle(handle_pos[0], handle_pos[1], handle_size, xscale, yscale); + draw_circle(handle_pos[0], handle_pos[1], handle_size, false, xscale, yscale); } /* return non-zero if spline is selected */ @@ -237,6 +247,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline int i, handle_size, tot_feather_point; float (*feather_points)[2], (*fp)[2]; + float min[2], max[2]; if (!spline->tot_point) return; @@ -302,6 +313,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline } /* control points */ + INIT_MINMAX2(min, max); for (i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ @@ -354,6 +366,25 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline glBegin(GL_POINTS); glVertex2fv(vert); glEnd(); + + minmax_v2v2_v2(min, max, vert); + } + + if (is_spline_sel) { + float x = (min[0] + max[0]) / 2.0f; + float y = (min[1] + max[1]) / 2.0f; + /* TODO(sergey): Remove hardcoded colors. */ + if (masklay->act_spline == spline) { + glColor3ub(255, 255, 255); + } + else { + glColor3ub(255, 255, 0); + } + + draw_circle(x, y, 6.0f, true, xscale, yscale); + + glColor3ub(0, 0, 0); + draw_circle(x, y, 6.0f, false, xscale, yscale); } glPointSize(1.0f); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index c9eacc898b5..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); |