diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_mask.h | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mask.c | 185 |
3 files changed, 165 insertions, 64 deletions
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 691afaf8f16..5dd0b14be63 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 44c9bc9ebbe..0ce2953a2e3 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 d08b7316e61..8ea035e3249 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_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float interp_v2_v2v2(co, r0, r1, u); } +BLI_INLINE void orthogonal_direction_get(float vec[2], float result[2]) +{ + result[0] = -vec[1]; + result[1] = vec[0]; + normalize_v2(result); +} + +/* TODO(sergey): This function will re-calculate loads of stuff again and again + * when differentiating feather points. This might be easily cached + * in the callee function for this case. + */ void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2]) { - MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); - BezTriple *bezt = &point->bezt, *bezt_next; - float q0[2], q1[2], q2[2], r0[2], r1[2], vec[2]; + MaskSplinePoint *point_prev, *point_next; - bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point); + /* TODO(sergey): This actually depends on a resolution. */ + const float du = 0.05f; - if (!bezt_next) { - BKE_mask_point_handle(point, vec); + BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next); - sub_v2_v2v2(n, vec, bezt->vec[1]); - normalize_v2(n); - return; + if (u - du < 0.0f && point_prev == NULL) { + float co[2], dir[2]; + BKE_mask_point_segment_co(spline, point, u + du, co); + sub_v2_v2v2(dir, co, point->bezt.vec[1]); + orthogonal_direction_get(dir, n); + } + else if (u + du > 1.0f && point_next == NULL) { + float co[2], dir[2]; + BKE_mask_point_segment_co(spline, point, u - du, co); + sub_v2_v2v2(dir, point->bezt.vec[1], co); + orthogonal_direction_get(dir, n); } + else { + float prev_co[2], next_co[2], co[2]; + float dir1[2], dir2[2], dir[2]; - interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u); - interp_v2_v2v2(q1, bezt->vec[2], bezt_next->vec[0], u); - interp_v2_v2v2(q2, bezt_next->vec[0], bezt_next->vec[1], u); + if (u - du < 0.0f) { + BKE_mask_point_segment_co(spline, point_prev, 1.0f + (u - du), prev_co); + } + else { + BKE_mask_point_segment_co(spline, point, u - du, prev_co); + } - interp_v2_v2v2(r0, q0, q1, u); - interp_v2_v2v2(r1, q1, q2, u); + BKE_mask_point_segment_co(spline, point, u, co); + + if (u + du > 1.0f) { + BKE_mask_point_segment_co(spline, point_next, u + du - 1.0f, next_co); + } + else { + BKE_mask_point_segment_co(spline, point, u + du, next_co); + } - sub_v2_v2v2(vec, r1, r0); + sub_v2_v2v2(dir1, co, prev_co); + sub_v2_v2v2(dir2, next_co, co); - n[0] = -vec[1]; - n[1] = vec[0]; + normalize_v2(dir1); + normalize_v2(dir2); + add_v2_v2v2(dir, dir1, dir2); - normalize_v2(n); + orthogonal_direction_get(dir, n); + } } static float mask_point_interp_weight(BezTriple *bezt, BezTriple *bezt_next, const float u) @@ -693,13 +754,37 @@ void BKE_mask_point_select_set(MaskSplinePoint *point, const bool do_select) } } -void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const bool do_select) +void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const eMaskWhichHandle which_handle, const bool do_select) { if (do_select) { - MASKPOINT_SEL_HANDLE(point); + if (ELEM(which_handle, MASK_WHICH_HANDLE_STICK, MASK_WHICH_HANDLE_BOTH)) { + point->bezt.f1 |= SELECT; + point->bezt.f3 |= SELECT; + } + else if (which_handle == MASK_WHICH_HANDLE_LEFT) { + point->bezt.f1 |= SELECT; + } + else if (which_handle == MASK_WHICH_HANDLE_RIGHT) { + point->bezt.f3 |= SELECT; + } + else { + BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle"); + } } else { - MASKPOINT_DESEL_HANDLE(point); + if (ELEM(which_handle, MASK_WHICH_HANDLE_STICK, MASK_WHICH_HANDLE_BOTH)) { + point->bezt.f1 &= ~SELECT; + point->bezt.f3 &= ~SELECT; + } + else if (which_handle == MASK_WHICH_HANDLE_LEFT) { + point->bezt.f1 &= ~SELECT; + } + else if (which_handle == MASK_WHICH_HANDLE_RIGHT) { + point->bezt.f3 &= ~SELECT; + } + else { + BLI_assert(!"Wrong which_handle passed to BKE_mask_point_select_set_handle"); + } } } @@ -1170,7 +1255,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *poin else if (handle_type == HD_AUTO) { BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0); } - else if (handle_type == HD_ALIGN) { + else if (handle_type == HD_ALIGN || handle_type == HD_ALIGN_DOUBLESIDE) { float v1[3], v2[3]; float vec[3], h[3]; |