[Bf-blender-cvs] [09fc5d6] master: Roto: Add spline dragging zone in it's center

Sergey Sharybin noreply at git.blender.org
Tue Aug 19 17:29:52 CEST 2014


Commit: 09fc5d6a37803d57051bb6a923fb1fcc96985edf
Author: Sergey Sharybin
Date:   Tue Aug 19 21:27:12 2014 +0600
Branches: master
https://developer.blender.org/rB09fc5d6a37803d57051bb6a923fb1fcc96985edf

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.

===================================================================

M	source/blender/editors/mask/mask_draw.c
M	source/blender/editors/mask/mask_ops.c

===================================================================

diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index c2b949f..9409203 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 c9eacc8..9f8388f 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);




More information about the Bf-blender-cvs mailing list