[Bf-blender-cvs] [1af69b6] master: Implement asymmetric and free handles type for masks

Sergey Sharybin noreply at git.blender.org
Fri Mar 28 12:57:23 CET 2014


Commit: 1af69b6df3c538bd329201520abaa5058a1ff0ca
Author: Sergey Sharybin
Date:   Wed Oct 30 10:38:45 2013 +0100
https://developer.blender.org/rB1af69b6df3c538bd329201520abaa5058a1ff0ca

Implement asymmetric and free handles type for masks

Summary:
The title actually says it all, it's just possible to
have independent free handles for mask splines. Also
it's now possible to have aligned handles displayed
as independent handles.

Required changes in quite a few places, but they're
rather straightforward.

>From user perspective there's one really visible change
which is removed Handle Type menu from the panel. With
asymmetric handles it's not clear which handle type to
display there. So now the only way to change handle type
is via V-key menu.

Rewrote normal evaluation function to make it deal
with new type of handles we support. Now it works in
the following way:

- Offset the original spline by maximal weight
- Calculate vector between corresponding U positions
  on offset and original spline
- Normalize this vector.

Seems to be giving more adequate results and doesn't
tend to self-intersect as much as old behavior used to,

There're still some changes which needed to be done, but
which are planned for further patch:

- Support colors and handle size via themes.
- Make handles color-coded, just the same as done for
  regular bezier splines in 3D viewport.

Additional changes to make roto workflow even better:
- Use circles to draw handles
- Support AA for handles
- Change click-create-drag to change curvature of the
  spline instead of adjusting point position.

Reviewers: campbellbarton

CC: sebastian_k, hype, cronk

Differential Revision: http://developer.blender.org/D121

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

M	release/scripts/startup/bl_ui/properties_mask_common.py
M	source/blender/blenkernel/BKE_mask.h
M	source/blender/blenkernel/intern/curve.c
M	source/blender/blenkernel/intern/mask.c
M	source/blender/editors/interface/resources.c
M	source/blender/editors/mask/mask_add.c
M	source/blender/editors/mask/mask_draw.c
M	source/blender/editors/mask/mask_edit.c
M	source/blender/editors/mask/mask_intern.h
M	source/blender/editors/mask/mask_ops.c
M	source/blender/editors/mask/mask_select.c
M	source/blender/editors/transform/transform_conversions.c
M	source/blender/makesdna/DNA_curve_types.h
M	source/blender/makesrna/intern/rna_mask.c
M	source/blender/makesrna/intern/rna_userdef.c

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

diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index cd659e1..eef7b00 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -173,9 +173,6 @@ class MASK_PT_point():
         parent = point.parent
 
         col = layout.column()
-        col.prop(point, "handle_type")
-
-        col = layout.column()
         # Currently only parenting yo movie clip is allowed, so do not
         # ver-oplicate things for now and use single template_ID
         #col.template_any_ID(parent, "id", "id_type", text="")
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 691afaf..5dd0b14 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -47,6 +47,20 @@ struct MovieClip;
 struct MovieClipUser;
 struct Scene;
 
+/* mask_ops.c */
+typedef enum {
+	MASK_WHICH_HANDLE_NONE  = 0,
+	MASK_WHICH_HANDLE_STICK = 1,
+	MASK_WHICH_HANDLE_LEFT  = 2,
+	MASK_WHICH_HANDLE_RIGHT = 3,
+	MASK_WHICH_HANDLE_BOTH  = 4,
+} eMaskWhichHandle;
+
+typedef enum {
+	MASK_HANDLE_MODE_STICK = 1,
+	MASK_HANDLE_MODE_INDIVIDUAL_HANDLES = 2,
+} eMaskhandleMode;
+
 struct MaskSplinePoint *BKE_mask_spline_point_array(struct MaskSpline *spline);
 struct MaskSplinePoint *BKE_mask_spline_point_array_from_point(struct MaskSpline *spline, struct MaskSplinePoint *point_ref);
 
@@ -87,9 +101,9 @@ float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoi
                                  float start_u, const float co[2], const eMaskSign sign);
 
 /* point */
-bool BKE_mask_point_has_handle(struct MaskSplinePoint *point);
-void BKE_mask_point_handle(struct MaskSplinePoint *point, float handle[2]);
-void BKE_mask_point_set_handle(struct MaskSplinePoint *point, float loc[2], bool keep_direction,
+eMaskhandleMode BKE_mask_point_handles_mode_get(struct MaskSplinePoint *point);
+void BKE_mask_point_handle(struct MaskSplinePoint *point, eMaskWhichHandle which_handle, float handle[2]);
+void BKE_mask_point_set_handle(struct MaskSplinePoint *point, eMaskWhichHandle which_handle, float loc[2], bool keep_direction,
                                float orig_handle[2], float orig_vec[3][3]);
 
 void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2]);
@@ -101,7 +115,7 @@ struct MaskSplinePointUW *BKE_mask_point_sort_uw(struct MaskSplinePoint *point,
 void BKE_mask_point_add_uw(struct MaskSplinePoint *point, float u, float w);
 
 void BKE_mask_point_select_set(struct MaskSplinePoint *point, const bool do_select);
-void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const bool do_select);
+void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMaskWhichHandle which_handle, const bool do_select);
 
 /* general */
 struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
@@ -176,16 +190,18 @@ void BKE_mask_clipboard_paste_to_layer(struct Main *bmain, struct MaskLayer *mas
 
 #define MASKPOINT_ISSEL_ANY(p)          ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f3) & SELECT)
 #define MASKPOINT_ISSEL_KNOT(p)         ( (p)->bezt.f2 & SELECT)
-#define MASKPOINT_ISSEL_HANDLE_ONLY(p)  ( (((p)->bezt.f1 | (p)->bezt.f3) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) )
-#define MASKPOINT_ISSEL_HANDLE(p)       ( (((p)->bezt.f1 | (p)->bezt.f3) & SELECT) )
+
+#define MASKPOINT_ISSEL_HANDLE(point, which_handle) \
+	((which_handle == MASK_WHICH_HANDLE_STICK) ? \
+	((((point)->bezt.f1 | (point)->bezt.f3) & SELECT)) : \
+	((which_handle == MASK_WHICH_HANDLE_LEFT) ? \
+	((point)->bezt.f1 & SELECT) : \
+	((point)->bezt.f3 & SELECT)))
 
 #define MASKPOINT_SEL_ALL(p)    { (p)->bezt.f1 |=  SELECT; (p)->bezt.f2 |=  SELECT; (p)->bezt.f3 |=  SELECT; } (void)0
 #define MASKPOINT_DESEL_ALL(p)  { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0
 #define MASKPOINT_INVSEL_ALL(p) { (p)->bezt.f1 ^=  SELECT; (p)->bezt.f2 ^=  SELECT; (p)->bezt.f3 ^=  SELECT; } (void)0
 
-#define MASKPOINT_SEL_HANDLE(p)     { (p)->bezt.f1 |=  SELECT; (p)->bezt.f3 |=  SELECT; } (void)0
-#define MASKPOINT_DESEL_HANDLE(p)   { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0
-
 #define MASK_RESOL_MAX 128
 
 
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 44c9bc9..0ce2953 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -3080,7 +3080,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
 		madd_v3_v3v3fl(p2_h2, p2, dvec_b,  1.0f / 3.0f);
 	}
 
-	if (skip_align || !ELEM(HD_ALIGN, bezt->h1, bezt->h2)) {
+	if (skip_align || (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) {
 		/* handles need to be updated during animation and applying stuff like hooks,
 		 * but in such situations it's quite difficult to distinguish in which order
 		 * align handles should be aligned so skip them for now */
@@ -3095,7 +3095,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
 		len_b = 1.0f;
 
 	if (bezt->f1 & SELECT) { /* order of calculation */
-		if (bezt->h2 == HD_ALIGN) { /* aligned */
+		if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) { /* aligned */
 			if (len_a > eps) {
 				len = len_b / len_a;
 				p2_h2[0] = p2[0] + len * (p2[0] - p2_h1[0]);
@@ -3103,7 +3103,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
 				p2_h2[2] = p2[2] + len * (p2[2] - p2_h1[2]);
 			}
 		}
-		if (bezt->h1 == HD_ALIGN) {
+		if (ELEM(bezt->h1, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
 			if (len_b > eps) {
 				len = len_a / len_b;
 				p2_h1[0] = p2[0] + len * (p2[0] - p2_h2[0]);
@@ -3113,7 +3113,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
 		}
 	}
 	else {
-		if (bezt->h1 == HD_ALIGN) {
+		if (ELEM(bezt->h1, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
 			if (len_b > eps) {
 				len = len_a / len_b;
 				p2_h1[0] = p2[0] + len * (p2[0] - p2_h2[0]);
@@ -3121,7 +3121,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n
 				p2_h1[2] = p2[2] + len * (p2[2] - p2_h2[2]);
 			}
 		}
-		if (bezt->h2 == HD_ALIGN) {   /* aligned */
+		if (ELEM(bezt->h2, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {   /* aligned */
 			if (len_a > eps) {
 				len = len_b / len_a;
 				p2_h2[0] = p2[0] + len * (p2[0] - p2_h1[0]);
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index d08b731..8ea035e 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -435,58 +435,87 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point,
 
 /* point */
 
-bool BKE_mask_point_has_handle(MaskSplinePoint *point)
+eMaskhandleMode BKE_mask_point_handles_mode_get(MaskSplinePoint *point)
 {
 	BezTriple *bezt = &point->bezt;
 
-	return bezt->h1 == HD_ALIGN;
+	if (bezt->h1 == bezt->h2 && bezt->h1 == HD_ALIGN) {
+		return MASK_HANDLE_MODE_STICK;
+	}
+
+	return MASK_HANDLE_MODE_INDIVIDUAL_HANDLES;
 }
 
-void BKE_mask_point_handle(MaskSplinePoint *point, float handle[2])
+void BKE_mask_point_handle(MaskSplinePoint *point, eMaskWhichHandle which_handle, float handle[2])
 {
-	float vec[2];
+	BezTriple *bezt = &point->bezt;
+
+	if (which_handle == MASK_WHICH_HANDLE_STICK) {
+		float vec[2];
 
-	sub_v2_v2v2(vec, point->bezt.vec[0], point->bezt.vec[1]);
+		sub_v2_v2v2(vec, bezt->vec[0], bezt->vec[1]);
 
-	handle[0] = (point->bezt.vec[1][0] + vec[1]);
-	handle[1] = (point->bezt.vec[1][1] - vec[0]);
+		handle[0] = (bezt->vec[1][0] + vec[1]);
+		handle[1] = (bezt->vec[1][1] - vec[0]);
+	}
+	else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+		copy_v2_v2(handle, bezt->vec[0]);
+	}
+	else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+		copy_v2_v2(handle, bezt->vec[2]);
+	}
+	else {
+		BLI_assert(!"Unknown handle passed to BKE_mask_point_handle");
+	}
 }
 
-void BKE_mask_point_set_handle(MaskSplinePoint *point, float loc[2], bool keep_direction,
+void BKE_mask_point_set_handle(MaskSplinePoint *point, eMaskWhichHandle which_handle,
+                               float loc[2], bool keep_direction,
                                float orig_handle[2], float orig_vec[3][3])
 {
 	BezTriple *bezt = &point->bezt;
-	float v1[2], v2[2], vec[2];
 
-	if (keep_direction) {
-		sub_v2_v2v2(v1, loc, orig_vec[1]);
-		sub_v2_v2v2(v2, orig_handle, orig_vec[1]);
+	if (which_handle == MASK_WHICH_HANDLE_STICK) {
+		float v1[2], v2[2], vec[2];
+		if (keep_direction) {
+			sub_v2_v2v2(v1, loc, orig_vec[1]);
+			sub_v2_v2v2(v2, orig_handle, orig_vec[1]);
 
-		project_v2_v2v2(vec, v1, v2);
+			project_v2_v2v2(vec, v1, v2);
 
-		if (dot_v2v2(v2, vec) > 0) {
-			float len = len_v2(vec);
+			if (dot_v2v2(v2, vec) > 0) {
+				float len = len_v2(vec);
 
-			sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]);
+				sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]);
 
-			mul_v2_fl(v1, len / len_v2(v1));
+				mul_v2_fl(v1, len / len_v2(v1));
 
-			add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1);
-			sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1);
+				add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1);
+				sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1);
+			}
+			else {
+				copy_v3_v3(bezt->vec[0], bezt->vec[1]);
+				copy_v3_v3(bezt->vec[2], bezt->vec[1]);
+			}
 		}
 		else {
-			copy_v3_v3(bezt->vec[0], bezt->vec[1]);
-			copy_v3_v3(bezt->vec[2], bezt->vec[1]);
+			sub_v2_v2v2(v1, loc, bezt->vec[1]);
+
+			v2[0] = -v1[1];
+			v2[1] =  v1[0];
+
+			add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2);
+			sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2);
 		}
 	}
+	else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+		copy_v2_v2(bezt->vec[0], loc);
+	}
+	else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+		copy_v2_v2(bezt->vec[2], loc);
+	}
 	else {
-		sub_v2_v2v2(v1, loc, bezt->vec[1]);
-
-		v2[0] = -v1[1];
-		v2[1] =  v1[0];
-
-		add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2);
-		sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2);
+		BLI_assert(!"unknown handle passed to BKE_mask_point_set_handle");
 	}
 }
 
@@ -514,36 +543,68 @@ void BKE_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list