Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2014-08-19 19:27:12 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-08-19 19:29:45 +0400
commit09fc5d6a37803d57051bb6a923fb1fcc96985edf (patch)
treeb361eabcabd70b1f36e6d9ef751f1b3265af4242 /source/blender/editors/mask
parent7bc87a372e40b6adc852d42c60ea6aca55aaa7fb (diff)
Roto: Add spline dragging zone in it's center
This dragging zone is visualized as the circle (the same as object origin) in the spline bounding box center and dragging that circle drags the whole spline. Pretty much basic functionality, but quite useful in practice. Requested by our roto team (Sebastian and Sean :) in IRC.
Diffstat (limited to 'source/blender/editors/mask')
-rw-r--r--source/blender/editors/mask/mask_draw.c39
-rw-r--r--source/blender/editors/mask/mask_ops.c140
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);