[Bf-blender-cvs] [0102d57] master: Slide mask spline segment to define it's curvature

Sergey Sharybin noreply at git.blender.org
Thu Apr 3 14:20:29 CEST 2014


Commit: 0102d57c1de344fc3dd14e93d0593ed616d29d7b
Author: Sergey Sharybin
Date:   Thu Apr 3 18:15:04 2014 +0600
https://developer.blender.org/rB0102d57c1de344fc3dd14e93d0593ed616d29d7b

Slide mask spline segment to define it's curvature

This actually implements the idea used in Gimp which is grabbing
an arbitrary point on the spline and dragging it, ensuring spline
goes over this point. This is really useful way to tweak spline
curvature.

Currently only affects on a closest handle, meaning no weighting
on changes for both handles which are adjacent to the same segment
will happen just yet,

Another limitation is that currently such a slide is a big jumpy
when you start sliding. This is because projection is not used
to calculate u value because projection used to fail a lot for
me here and didn't find a nice solution for this yet. But this is
to be improved for sure!

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

M	source/blender/editors/mask/mask_add.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

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

diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index ecaa737..d2c1d84 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -54,10 +54,16 @@
 #include "mask_intern.h"  /* own include */
 
 
-static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float normal_co[2], int threshold, bool feather,
-                                    MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
-                                    float *u_r, float tangent[2],
-                                    const bool use_deform)
+bool ED_mask_find_nearest_diff_point(const bContext *C,
+                                     struct Mask *mask,
+                                     const float normal_co[2],
+                                     int threshold, bool feather,
+                                     MaskLayer **masklay_r,
+                                     MaskSpline **spline_r,
+                                     MaskSplinePoint **point_r,
+                                     float *u_r, float tangent[2],
+                                     const bool use_deform,
+                                     const bool use_project)
 {
 	ScrArea *sa = CTX_wm_area(C);
 	ARegion *ar = CTX_wm_region(C);
@@ -135,7 +141,6 @@ static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float n
 							point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
 							dist = cur_dist;
 							u = (float)j / tot_point;
-
 						}
 					}
 
@@ -159,7 +164,10 @@ static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float n
 			*point_r = point;
 
 		if (u_r) {
-			u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
+			/* TODO(sergey): Projection fails in some weirdo cases.. */
+			if (use_project) {
+				u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
+			}
 
 			*u_r = u;
 		}
@@ -332,7 +340,7 @@ static bool add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2
 	float tangent[2];
 	float u;
 
-	if (find_nearest_diff_point(C, mask, co, threshold, false, &masklay, &spline, &point, &u, tangent, true)) {
+	if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, false, &masklay, &spline, &point, &u, tangent, true, true)) {
 		MaskSplinePoint *new_point;
 		int point_index = point - spline->points;
 
@@ -617,7 +625,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
 	if (point)
 		return OPERATOR_FINISHED;
 
-	if (find_nearest_diff_point(C, mask, co, threshold, true, &masklay, &spline, &point, &u, NULL, true)) {
+	if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, &masklay, &spline, &point, &u, NULL, true, true)) {
 		Scene *scene = CTX_data_scene(C);
 		float w = BKE_mask_point_weight(spline, point, u);
 		float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index e27f36e..d94a190 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -438,6 +438,7 @@ void ED_operatortypes_mask(void)
 
 	/* shape */
 	WM_operatortype_append(MASK_OT_slide_point);
+	WM_operatortype_append(MASK_OT_slide_spline_curvature);
 	WM_operatortype_append(MASK_OT_cyclic_toggle);
 	WM_operatortype_append(MASK_OT_handle_type_set);
 
@@ -534,6 +535,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
 	/* shape */
 	WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0);
 	WM_keymap_add_item(keymap, "MASK_OT_slide_point", ACTIONMOUSE, KM_PRESS, 0, 0);
+	WM_keymap_add_item(keymap, "MASK_OT_slide_spline_curvature", ACTIONMOUSE, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
 	// WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 369d3aa..6899cf7 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -40,6 +40,17 @@ struct wmOperatorType;
 /* internal exports only */
 
 /* mask_add.c */
+bool ED_mask_find_nearest_diff_point(const struct bContext *C,
+                                     struct Mask *mask,
+                                     const float normal_co[2],
+                                     int threshold, bool feather,
+                                     struct MaskLayer **masklay_r,
+                                     struct MaskSpline **spline_r,
+                                     struct MaskSplinePoint **point_r,
+                                     float *u_r, float tangent[2],
+                                     const bool use_deform,
+                                     const bool use_project);
+
 void MASK_OT_add_vertex(struct wmOperatorType *ot);
 void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
 void MASK_OT_primitive_circle_add(struct wmOperatorType *ot);
@@ -55,6 +66,7 @@ void MASK_OT_layer_remove(struct wmOperatorType *ot);
 void MASK_OT_cyclic_toggle(struct wmOperatorType *ot);
 
 void MASK_OT_slide_point(struct wmOperatorType *ot);
+void MASK_OT_slide_spline_curvature(struct wmOperatorType *ot);
 
 void MASK_OT_delete(struct wmOperatorType *ot);
 
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 775859b..e16c747 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1031,6 +1031,254 @@ void MASK_OT_slide_point(wmOperatorType *ot)
 	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
+/******************** slide spline curvature *********************/
+
+typedef struct SlideSplineCurvatureData {
+	Mask *mask;
+	MaskSpline *spline;
+	MaskSplinePoint *point;
+	float u;
+	bool accurate;
+
+	BezTriple *adjust_bezt;
+	BezTriple bezt_backup;
+	float initial_coord[2];
+
+	float P0[2], P1[2], P2[2], P3[3];
+} SlideSplineCurvatureData;
+
+static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
+{
+	*slide_data->adjust_bezt = slide_data->bezt_backup;
+}
+
+
+static void free_slide_spline_curvature_data(SlideSplineCurvatureData *slide_data)
+{
+	MEM_freeN(slide_data);
+}
+
+static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
+{
+	Mask *mask = CTX_data_edit_mask(C);
+	float co[2];
+	const float threshold = 19;
+
+	ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+
+	if (ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL)) {
+		return false;
+	}
+
+	if (ED_mask_feather_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL, NULL)) {
+		return false;
+	}
+
+	return true;
+}
+
+static SlideSplineCurvatureData *slide_spline_curvature_customdata(
+	bContext *C, wmOperator *op, const wmEvent *event)
+{
+	const float threshold = 19;
+
+	Mask *mask = CTX_data_edit_mask(C);
+	SlideSplineCurvatureData *slide_data;
+	MaskLayer *mask_layer;
+	MaskSpline *spline;
+	MaskSplinePoint *point;
+	float u, co[2];
+	BezTriple *next_bezt;
+
+	(void) op;
+
+	ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+
+	if (!ED_mask_find_nearest_diff_point(C, mask, co, threshold, false,
+	                                     &mask_layer, &spline, &point, &u,
+	                                     NULL, true, false))
+	{
+		return NULL;
+	}
+
+	next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
+	if (next_bezt == NULL) {
+		return NULL;
+	}
+
+	slide_data = MEM_callocN(sizeof(SlideSplineCurvatureData), "slide curvature slide");
+	slide_data->mask = mask;
+	slide_data->spline = spline;
+	slide_data->point = point;
+	slide_data->u = u;
+	copy_v2_v2(slide_data->initial_coord, co);
+
+	copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
+	copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
+	copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
+	copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
+
+	/* Depending to which end we're closer to adjust either left or right side of the spline. */
+	if (u <= 0.5f) {
+		slide_data->adjust_bezt = &point->bezt;
+	}
+	else {
+		slide_data->adjust_bezt = next_bezt;
+	}
+
+	/* Data needed for restoring state. */
+	slide_data->bezt_backup = *slide_data->adjust_bezt;
+
+	/* Let's dont touch other side of the point for now, so set handle to FREE. */
+	if (u < 0.5f) {
+		if (slide_data->adjust_bezt->h2 <= HD_VECT) {
+			slide_data->adjust_bezt->h2 = HD_FREE;
+		}
+	}
+	else {
+		if (slide_data->adjust_bezt->h1 < HD_VECT) {
+			slide_data->adjust_bezt->h1 = HD_FREE;
+		}
+	}
+
+	/* Change selection */
+	ED_mask_select_toggle_all(mask, SEL_DESELECT);
+	slide_data->adjust_bezt->f2 |= SELECT;
+	if (u < 0.5f) {
+		slide_data->adjust_bezt->f3 |= SELECT;
+	}
+	else {
+		slide_data->adjust_bezt->f1 |= SELECT;
+	}
+	mask_layer->act_spline = spline;
+	mask_layer->act_point = point;
+	ED_mask_select_flush_all(mask);
+
+	return slide_data;
+}
+
+static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	Mask *mask = CTX_data_edit_mask(C);
+	SlideSplineCurvatureData *slide_data;
+
+	if (mask == NULL) {
+		return OPERATOR_CANCELLED;
+	}
+
+	/* Be sure we don't conflict with point slide here. */
+	if (!slide_spline_curvature_check(C, event)) {
+		return OPERATOR_PASS_THROUGH;
+	}
+
+	slide_data = slide_spline_curvature_customdata(C, op, event);
+	if (slide_data != NULL) {
+		op->customdata = slide_data;
+		WM_event_add_modal_handler(C, op);
+		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+		return OPERATOR_RUNNING_MODAL;
+	}
+
+	return OPERATOR_PASS_THROUGH;
+}
+
+static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *) op->customdata;
+
+	switch (event->type) {
+		case LEFTSHIFTKEY:
+		case RIGHTSHIFTKEY:
+			if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
+				slide_data->accurate = (event->val == KM_PRESS);
+
+			/*

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list