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-04-04 14:43:20 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-04-04 14:44:09 +0400
commit68bc675af45bb35e671020b6de816e5b68dcb82d (patch)
tree98519d058ed0e0065fb6f47d24b3e9476bb8ac5f /source/blender/editors/mask/mask_ops.c
parent7cb90a611faa506d7576f1f27f42be6936a45f5e (diff)
Mask spline segment slide improvement
This implements weighted slide of second handle, just the same exact way as it works in Gimp.
Diffstat (limited to 'source/blender/editors/mask/mask_ops.c')
-rw-r--r--source/blender/editors/mask/mask_ops.c122
1 files changed, 100 insertions, 22 deletions
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 14345424757..2abfd9a9ea0 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1016,8 +1016,8 @@ typedef struct SlideSplineCurvatureData {
float u;
bool accurate;
- BezTriple *adjust_bezt;
- BezTriple bezt_backup;
+ BezTriple *adjust_bezt, *other_bezt;
+ BezTriple bezt_backup, other_bezt_backup;
float prev_mouse_coord[2];
float prev_spline_coord[2];
@@ -1028,6 +1028,7 @@ typedef struct SlideSplineCurvatureData {
static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
{
*slide_data->adjust_bezt = slide_data->bezt_backup;
+ *slide_data->other_bezt = slide_data->other_bezt_backup;
}
@@ -1056,7 +1057,7 @@ static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
}
static SlideSplineCurvatureData *slide_spline_curvature_customdata(
- bContext *C, wmOperator *op, const wmEvent *event)
+ bContext *C, const wmEvent *event)
{
const float threshold = 19;
@@ -1068,8 +1069,6 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(
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,
@@ -1101,13 +1100,16 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(
/* 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;
+ slide_data->other_bezt = next_bezt;
}
else {
slide_data->adjust_bezt = next_bezt;
+ slide_data->other_bezt = &point->bezt;
}
/* Data needed for restoring state. */
slide_data->bezt_backup = *slide_data->adjust_bezt;
+ slide_data->other_bezt_backup = *slide_data->other_bezt;
/* Let's dont touch other side of the point for now, so set handle to FREE. */
if (u < 0.5f) {
@@ -1124,11 +1126,14 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(
/* Change selection */
ED_mask_select_toggle_all(mask, SEL_DESELECT);
slide_data->adjust_bezt->f2 |= SELECT;
+ slide_data->other_bezt->f2 |= SELECT;
if (u < 0.5f) {
slide_data->adjust_bezt->f3 |= SELECT;
+ slide_data->other_bezt->f1 |= SELECT;
}
else {
slide_data->adjust_bezt->f1 |= SELECT;
+ slide_data->other_bezt->f3 |= SELECT;
}
mask_layer->act_spline = spline;
mask_layer->act_point = point;
@@ -1151,7 +1156,7 @@ static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEv
return OPERATOR_PASS_THROUGH;
}
- slide_data = slide_spline_curvature_customdata(C, op, event);
+ slide_data = slide_spline_curvature_customdata(C, event);
if (slide_data != NULL) {
op->customdata = slide_data;
WM_event_add_modal_handler(C, op);
@@ -1162,6 +1167,38 @@ static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEv
return OPERATOR_PASS_THROUGH;
}
+static void slide_spline_solve_P1(const float u,
+ const float B[2],
+ const float P0[0],
+ const float P2[0],
+ const float P3[0],
+ float solution[2])
+{
+ const float u2 = u * u, u3 = u * u * u;
+ const float v = 1.0f - u;
+ const float v2 = v * v, v3 = v * v * v;
+ const float inv_divider = 1.0f / (3.0f * v2 * u);
+ const float t = 3.0f * v * u2;
+ solution[0] = -(v3 * P0[0] + t * P2[0] + u3 * P3[0] - B[0]) * inv_divider;
+ solution[1] = -(v3 * P0[1] + t * P2[1] + u3 * P3[1] - B[1]) * inv_divider;
+}
+
+static void slide_spline_solve_P2(const float u,
+ const float B[2],
+ const float P0[0],
+ const float P1[0],
+ const float P3[0],
+ float solution[2])
+{
+ const float u2 = u * u, u3 = u * u * u;
+ const float v = 1.0f - u;
+ const float v2 = v * v, v3 = v * v * v;
+ const float inv_divider = 1.0f / (3.0f * v * u2);
+ const float t = 3.0f * v2 * u;
+ solution[0] = -(v3 * P0[0] + t * P1[0] + u3 * P3[0] - B[0]) * inv_divider;
+ solution[1] = -(v3 * P0[1] + t * P1[1] + u3 * P3[1] - B[1]) * inv_divider;
+}
+
static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *) op->customdata;
@@ -1175,12 +1212,9 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
/* fall-through */ /* update CV position */
case MOUSEMOVE:
{
+ const float margin = 0.2f;
float B[2], mouse_coord[2], delta[2];
float u = slide_data->u;
- float u2 = slide_data->u * slide_data->u;
- float u3 = slide_data->u * slide_data->u * slide_data->u;
- float v = 1.0f - slide_data->u;
- float v2 = v * v, v3 = v * v * v;;
/* Get coordinate spline is expected to go through. */
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, mouse_coord);
@@ -1193,22 +1227,66 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve
copy_v2_v2(slide_data->prev_mouse_coord, mouse_coord);
if (u < 0.5f) {
- slide_data->adjust_bezt->vec[2][0] =
- -(v3 * slide_data->P0[0] + 3.0f * v * u2 * slide_data->P2[0] + u3 * slide_data->P3[0] - B[0]) /
- (3.0f * v2 * u);
+ float oldP2[2];
+ bool need_restore_P2 = false;
+
+ if (u > margin) {
+ float solution[2];
+ float x = (u - margin) * 0.5f / (0.5f - margin);
+ float weight = (3 * x * x - 2 * x * x * x);
+
+ slide_spline_solve_P2(u, B,
+ slide_data->P0,
+ slide_data->P1,
+ slide_data->P3,
+ solution);
+
+ copy_v2_v2(oldP2, slide_data->P2);
+ interp_v2_v2v2(slide_data->P2, slide_data->P2, solution, weight);
+ copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->P2);
+ need_restore_P2 = true;
+ }
+
+ slide_spline_solve_P1(u, B,
+ slide_data->P0,
+ slide_data->P2,
+ slide_data->P3,
+ slide_data->adjust_bezt->vec[2]);
- slide_data->adjust_bezt->vec[2][1] =
- -(v3 * slide_data->P0[1] + 3.0f * v * u2 * slide_data->P2[1] + u3 * slide_data->P3[1] - B[1]) /
- (3.0f * v2 * u);
+ if (need_restore_P2) {
+ copy_v2_v2(slide_data->P2, oldP2);
+ }
}
else {
- slide_data->adjust_bezt->vec[0][0] =
- -(v3 * slide_data->P0[0] + 3.0f * v2 * u * slide_data->P1[0] + u3 * slide_data->P3[0] - B[0]) /
- (3.0f * v * u2);
+ float oldP1[2];
+ bool need_restore_P1 = false;
+
+ if (u < 1.0f - margin) {
+ float solution[2];
+ float x = ((1.0f - u) - margin) * 0.5f / (0.5f - margin);
+ float weight = 3 * x * x - 2 * x * x * x;
+
+ slide_spline_solve_P1(u, B,
+ slide_data->P0,
+ slide_data->P2,
+ slide_data->P3,
+ solution);
+
+ copy_v2_v2(oldP1, slide_data->P1);
+ interp_v2_v2v2(slide_data->P1, slide_data->P1, solution, weight);
+ copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->P1);
+ need_restore_P1 = true;
+ }
+
+ slide_spline_solve_P2(u, B,
+ slide_data->P0,
+ slide_data->P1,
+ slide_data->P3,
+ slide_data->adjust_bezt->vec[0]);
- slide_data->adjust_bezt->vec[0][1] =
- -(v3 * slide_data->P0[1] + 3.0f * v2 * u * slide_data->P1[1] + u3 * slide_data->P3[1] - B[1]) /
- (3.0f * v * u2);
+ if (need_restore_P1) {
+ copy_v2_v2(slide_data->P1, oldP1);
+ }
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);