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:
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py3
-rw-r--r--source/blender/blenkernel/BKE_mask.h34
-rw-r--r--source/blender/blenkernel/intern/curve.c10
-rw-r--r--source/blender/blenkernel/intern/mask.c185
-rw-r--r--source/blender/editors/interface/resources.c65
-rw-r--r--source/blender/editors/mask/mask_add.c148
-rw-r--r--source/blender/editors/mask/mask_draw.c192
-rw-r--r--source/blender/editors/mask/mask_edit.c4
-rw-r--r--source/blender/editors/mask/mask_intern.h2
-rw-r--r--source/blender/editors/mask/mask_ops.c229
-rw-r--r--source/blender/editors/mask/mask_select.c30
-rw-r--r--source/blender/editors/transform/transform_conversions.c195
-rw-r--r--source/blender/makesdna/DNA_curve_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_mask.c96
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c48
15 files changed, 868 insertions, 376 deletions
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index cd659e1e5fe..eef7b00f0be 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 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];
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index a112106620f..8e53f9d2332 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -763,6 +763,18 @@ static void ui_theme_init_new(bTheme *btheme)
}
}
+static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
+{
+ rgba_char_args_set(theme_space->handle_free, 0, 0, 0, 255);
+ rgba_char_args_set(theme_space->handle_auto, 0x90, 0x90, 0x00, 255);
+ rgba_char_args_set(theme_space->handle_vect, 0x40, 0x90, 0x30, 255);
+ rgba_char_args_set(theme_space->handle_align, 0x80, 0x30, 0x60, 255);
+ rgba_char_args_set(theme_space->handle_sel_free, 0, 0, 0, 255);
+ rgba_char_args_set(theme_space->handle_sel_auto, 0xf0, 0xff, 0x40, 255);
+ rgba_char_args_set(theme_space->handle_sel_vect, 0x40, 0xc0, 0x30, 255);
+ rgba_char_args_set(theme_space->handle_sel_align, 0xf0, 0x90, 0xa0, 255);
+ rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
+}
/* initialize default theme
* Note: when you add new colors, created & saved themes need initialized
@@ -873,14 +885,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.nurb_sel_uline, 0xf0, 0xff, 0x40, 255);
rgba_char_args_set(btheme->tv3d.nurb_sel_vline, 0xf0, 0x90, 0xa0, 255);
- rgba_char_args_set(btheme->tv3d.handle_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.handle_auto, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(btheme->tv3d.handle_vect, 0x40, 0x90, 0x30, 255);
- rgba_char_args_set(btheme->tv3d.handle_align, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_auto, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_vect, 0x40, 0xc0, 0x30, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_align, 0xf0, 0x90, 0xa0, 255);
+ ui_theme_space_init_handles_color(&btheme->tv3d);
rgba_char_args_set(btheme->tv3d.act_spline, 0xdb, 0x25, 0x12, 255);
rgba_char_args_set(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
@@ -1023,6 +1028,9 @@ void ui_theme_init_default(void)
rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255);
rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255);
+ ui_theme_space_init_handles_color(&btheme->tima);
+ btheme->tima.handle_vertex_size = 5;
+
/* space text */
btheme->text = btheme->tv3d;
rgba_char_args_set(btheme->text.back, 153, 153, 153, 255);
@@ -1125,7 +1133,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
- btheme->tclip.handle_vertex_size = 4;
+ btheme->tclip.handle_vertex_size = 5;
+ ui_theme_space_init_handles_color(&btheme->tclip);
}
void ui_style_init_default(void)
@@ -1885,27 +1894,9 @@ void init_userdef_do_versions(void)
/* init new curve colors */
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
- /* init colors used for handles in 3D-View */
- rgba_char_args_set(btheme->tv3d.handle_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.handle_auto, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(btheme->tv3d.handle_vect, 0x40, 0x90, 0x30, 255);
- rgba_char_args_set(btheme->tv3d.handle_align, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_auto, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_vect, 0x40, 0xc0, 0x30, 255);
- rgba_char_args_set(btheme->tv3d.handle_sel_align, 0xf0, 0x90, 0xa0, 255);
- rgba_char_args_set(btheme->tv3d.act_spline, 0xdb, 0x25, 0x12, 255);
-
- /* same colors again for Graph Editor... */
- rgba_char_args_set(btheme->tipo.handle_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_auto, 0x90, 0x90, 0x00, 255);
- rgba_char_args_set(btheme->tipo.handle_vect, 0x40, 0x90, 0x30, 255);
- rgba_char_args_set(btheme->tipo.handle_align, 0x80, 0x30, 0x60, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_free, 0, 0, 0, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_auto, 0xf0, 0xff, 0x40, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_vect, 0x40, 0xc0, 0x30, 255);
- rgba_char_args_set(btheme->tipo.handle_sel_align, 0xf0, 0x90, 0xa0, 255);
-
+ ui_theme_space_init_handles_color(&btheme->tv3d);
+ ui_theme_space_init_handles_color(&btheme->tipo);
+
/* edge crease */
rgba_char_args_set_fl(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0);
}
@@ -2010,7 +2001,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff);
rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff);
- btheme->tclip.handle_vertex_size = 4;
+ btheme->tclip.handle_vertex_size = 5;
}
/* auto-clamped handles -> based on auto */
@@ -2423,7 +2414,17 @@ void init_userdef_do_versions(void)
}
}
}
-
+
+ {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ ui_theme_space_init_handles_color(&btheme->tclip);
+ ui_theme_space_init_handles_color(&btheme->tima);
+ btheme->tima.handle_vertex_size = 5;
+ btheme->tclip.handle_vertex_size = 5;
+ }
+ }
+
if (U.pixelsize == 0.0f)
U.pixelsize = 1.0f;
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 7fa41c361bb..2e1d5221b56 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -182,15 +182,13 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no
/******************** add vertex *********************/
static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
- const float point_co[2], const float tangent[2], const float u,
- MaskSplinePoint *reference_point, const short reference_adjacent,
- const float view_zoom)
+ const float point_co[2], const float u,
+ MaskSplinePoint *reference_point, const short reference_adjacent)
{
MaskSplinePoint *prev_point = NULL;
MaskSplinePoint *next_point = NULL;
BezTriple *bezt;
float co[3];
- const float len = 10.0; /* default length of handle in pixel space */
copy_v2_v2(co, point_co);
co[2] = 0.0f;
@@ -201,7 +199,41 @@ static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *
bezt->h1 = bezt->h2 = HD_ALIGN;
if (reference_point) {
- bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
+ if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) {
+ /* If the reference point is sharp try using some smooth point as reference
+ * for handles.
+ */
+ int point_index = reference_point - spline->points;
+ int delta = new_point == spline->points ? 1 : -1;
+ int i = 0;
+ for (i = 0; i < spline->tot_point - 1; ++i) {
+ MaskSplinePoint *current_point;
+
+ point_index += delta;
+ if (point_index == -1 || point_index >= spline->tot_point) {
+ if (spline->flag & MASK_SPLINE_CYCLIC) {
+ if (point_index == -1) {
+ point_index = spline->tot_point - 1;
+ }
+ else if (point_index >= spline->tot_point) {
+ point_index = 0;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ current_point = &spline->points[point_index];
+ if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) {
+ bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1);
+ break;
+ }
+ }
+ }
+ else {
+ bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
+ }
}
else if (reference_adjacent) {
if (spline->tot_point != 1) {
@@ -219,83 +251,11 @@ static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *
copy_v3_v3(bezt->vec[1], co);
copy_v3_v3(bezt->vec[2], co);
- /* initial offset for handles */
- if (spline->tot_point == 1) {
- /* first point of splien is aligned horizontally */
- bezt->vec[0][0] -= len * view_zoom;
- bezt->vec[2][0] += len * view_zoom;
- }
- else if (tangent) {
- float vec[2];
-
- copy_v2_v2(vec, tangent);
-
- mul_v2_fl(vec, len);
-
- sub_v2_v2(bezt->vec[0], vec);
- add_v2_v2(bezt->vec[2], vec);
-
- if (reference_adjacent) {
- BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
- }
- }
- else {
-
- /* calculating auto handles works much nicer */
-#if 0
- /* next points are aligning in the direction of previous/next point */
- MaskSplinePoint *point;
- float v1[2], v2[2], vec[2];
- float dir = 1.0f;
-
- if (new_point == spline->points) {
- point = new_point + 1;
- dir = -1.0f;
- }
- else
- point = new_point - 1;
-
- if (spline->tot_point < 3) {
- v1[0] = point->bezt.vec[1][0] * width;
- v1[1] = point->bezt.vec[1][1] * height;
-
- v2[0] = new_point->bezt.vec[1][0] * width;
- v2[1] = new_point->bezt.vec[1][1] * height;
- }
- else {
- if (new_point == spline->points) {
- v1[0] = spline->points[1].bezt.vec[1][0] * width;
- v1[1] = spline->points[1].bezt.vec[1][1] * height;
-
- v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width;
- v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height;
- }
- else {
- v1[0] = spline->points[0].bezt.vec[1][0] * width;
- v1[1] = spline->points[0].bezt.vec[1][1] * height;
-
- v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width;
- v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height;
- }
- }
-
- sub_v2_v2v2(vec, v1, v2);
- mul_v2_fl(vec, len * dir / len_v2(vec));
-
- vec[0] /= width;
- vec[1] /= height;
-
- add_v2_v2(bezt->vec[0], vec);
- sub_v2_v2(bezt->vec[2], vec);
-#else
- BKE_mask_calc_handle_point_auto(spline, new_point, TRUE);
+ BKE_mask_parent_init(&new_point->parent);
+ if (spline->tot_point != 1) {
BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
-
-#endif
}
- BKE_mask_parent_init(&new_point->parent);
-
/* select new point */
MASKPOINT_SEL_ALL(new_point);
ED_mask_select_flush_all(mask);
@@ -382,7 +342,7 @@ static int add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2]
new_point = &spline->points[point_index + 1];
- setup_vertex_point(mask, spline, new_point, co, tangent, u, NULL, TRUE, 1.0f);
+ setup_vertex_point(mask, spline, new_point, co, u, NULL, TRUE);
/* TODO - we could pass the spline! */
BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, true, true);
@@ -409,7 +369,6 @@ static int add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay,
float tangent_point[2];
float tangent_co[2];
bool do_cyclic_correct = false;
- bool do_recalc_src = false; /* when extruding from endpoints only */
bool do_prev; /* use prev point rather then next?? */
if (!masklay) {
@@ -440,11 +399,9 @@ static int add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay,
}
else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) {
do_prev = TRUE;
- do_recalc_src = TRUE;
}
else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) {
do_prev = FALSE;
- do_recalc_src = TRUE;
}
else {
do_prev = FALSE; /* quiet warning */
@@ -482,18 +439,13 @@ static int add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay,
masklay->act_point = new_point;
- setup_vertex_point(mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE, 1.0f);
+ setup_vertex_point(mask, spline, new_point, co, 0.5f, ref_point, FALSE);
if (masklay->splines_shapes.first) {
point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, true, true);
}
- if (do_recalc_src) {
- /* TODO, update keyframes in time */
- BKE_mask_calc_handle_point_auto(spline, ref_point, FALSE);
- }
-
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return TRUE;
@@ -504,7 +456,6 @@ static int add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, con
MaskSpline *spline;
MaskSplinePoint *point;
MaskSplinePoint *new_point = NULL, *ref_point = NULL;
- float view_zoom;
if (!masklay) {
/* if there's no masklay currently operationg on, create new one */
@@ -529,22 +480,7 @@ static int add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, con
masklay->act_point = new_point;
- {
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- float zoom_x, zoom_y;
- /* calc view zoom in a simplistic way */
- ED_mask_zoom(sa, ar, &zoom_x, &zoom_y);
-
- view_zoom = zoom_x + zoom_y / 2.0f;
- view_zoom = 1.0f / view_zoom;
-
- /* arbitrary but gives good results */
- view_zoom /= 500.0f;
- }
-
- setup_vertex_point(mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE, view_zoom);
+ setup_vertex_point(mask, spline, new_point, co, 0.5f, ref_point, FALSE);
{
int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 24fcbd19fc1..12fcd3c1459 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -132,29 +132,122 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
+static void draw_circle(const float x, const float y,
+ const float size, const float xscale, const float yscale)
+{
+ static GLuint displist = 0;
+
+ /* Initialize round circle shape. */
+ if (displist == 0) {
+ GLUquadricObj *qobj;
+
+ displist = glGenLists(1);
+ glNewList(displist, GL_COMPILE);
+
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ gluDisk(qobj, 0, 0.7, 8, 1);
+ gluDeleteQuadric(qobj);
+
+ glEndList();
+ }
+
+ glPushMatrix();
+ glTranslatef(x, y, 0.0f);
+ glScalef(1.0f / xscale * size, 1.0f / yscale * size, 1.0f);
+ glCallList(displist);
+ glPopMatrix();
+}
+
+static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point,
+ const eMaskWhichHandle which_handle, const int draw_type,
+ const float handle_size, const float xscale, const float yscale,
+ const float point_pos[2], const float handle_pos[2])
+{
+ const BezTriple *bezt = &point->bezt;
+ char handle_type;
+
+ if (which_handle == MASK_WHICH_HANDLE_STICK || which_handle == MASK_WHICH_HANDLE_LEFT) {
+ handle_type = bezt->h1;
+ }
+ else {
+ handle_type = bezt->h2;
+ }
+
+ if (handle_type == HD_VECT) {
+ return;
+ }
+
+ /* this could be split into its own loop */
+ if (draw_type == MASK_DT_OUTLINE) {
+ const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
+ glLineWidth(3);
+ glColor4ubv(rgb_gray);
+ glBegin(GL_LINES);
+ glVertex2fv(point_pos);
+ glVertex2fv(handle_pos);
+ glEnd();
+ glLineWidth(1);
+ }
+
+ switch (handle_type) {
+ case HD_FREE:
+ UI_ThemeColor(TH_HANDLE_FREE);
+ break;
+ case HD_AUTO:
+ UI_ThemeColor(TH_HANDLE_AUTO);
+ break;
+ case HD_ALIGN:
+ case HD_ALIGN_DOUBLESIDE:
+ UI_ThemeColor(TH_HANDLE_ALIGN);
+ break;
+ }
+
+ glBegin(GL_LINES);
+ glVertex2fv(point_pos);
+ glVertex2fv(handle_pos);
+ glEnd();
+
+ /* draw handle points */
+ if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
+ if (point == mask_layer->act_point)
+ glColor3f(1.0f, 1.0f, 1.0f);
+ else
+ glColor3f(1.0f, 1.0f, 0.0f);
+ }
+ else {
+ glColor3f(0.5f, 0.5f, 0.0f);
+ }
+
+ draw_circle(handle_pos[0], handle_pos[1], handle_size, xscale, yscale);
+}
+
/* return non-zero if spline is selected */
static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
- const char UNUSED(draw_flag), const char draw_type)
+ const char draw_flag, const char draw_type,
+ const float xscale, const float yscale)
{
const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
+ const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
+
unsigned char rgb_spline[4];
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
SpaceClip *sc = CTX_wm_space_clip(C);
- int undistort = FALSE;
+ bool undistort = false;
- int i, hsize, tot_feather_point;
+ int i, handle_size, tot_feather_point;
float (*feather_points)[2], (*fp)[2];
if (!spline->tot_point)
return;
if (sc)
- undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
+ undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
/* TODO, add this to sequence editor */
- hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */
+ handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
- glPointSize(hsize);
+ glPointSize(handle_size);
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
@@ -202,6 +295,12 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
}
MEM_freeN(feather_points);
+ if (is_smooth) {
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
/* control points */
for (i = 0; i < spline->tot_point; i++) {
@@ -210,38 +309,36 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
MaskSplinePoint *point_deform = &points_array[i];
BezTriple *bezt = &point_deform->bezt;
- float handle[2];
float vert[2];
- const bool has_handle = BKE_mask_point_has_handle(point);
copy_v2_v2(vert, bezt->vec[1]);
- BKE_mask_point_handle(point_deform, handle);
if (undistort) {
mask_point_undistort_pos(sc, vert, vert);
- mask_point_undistort_pos(sc, handle, handle);
}
/* draw handle segment */
- if (has_handle) {
-
- /* this could be split into its own loop */
- if (draw_type == MASK_DT_OUTLINE) {
- const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
- glLineWidth(3);
- glColor4ubv(rgb_gray);
- glBegin(GL_LINES);
- glVertex2fv(vert);
- glVertex2fv(handle);
- glEnd();
- glLineWidth(1);
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ float handle[2];
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle);
+ if (undistort) {
+ mask_point_undistort_pos(sc, handle, handle);
}
-
- glColor3ubv(rgb_spline);
- glBegin(GL_LINES);
- glVertex2fv(vert);
- glVertex2fv(handle);
- glEnd();
+ draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK,
+ draw_type, handle_size, xscale, yscale, vert, handle);
+ }
+ else {
+ float handle_left[2], handle_right[2];
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left);
+ BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right);
+ if (undistort) {
+ mask_point_undistort_pos(sc, handle_left, handle_left);
+ mask_point_undistort_pos(sc, handle_left, handle_left);
+ }
+ draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT,
+ draw_type, handle_size, xscale, yscale, vert, handle_left);
+ draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT,
+ draw_type, handle_size, xscale, yscale, vert, handle_right);
}
/* draw CV point */
@@ -257,26 +354,14 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
glBegin(GL_POINTS);
glVertex2fv(vert);
glEnd();
-
- /* draw handle points */
- if (has_handle) {
- if (MASKPOINT_ISSEL_HANDLE(point)) {
- if (point == masklay->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
- else
- glColor3f(1.0f, 1.0f, 0.0f);
- }
- else {
- glColor3f(0.5f, 0.5f, 0.0f);
- }
-
- glBegin(GL_POINTS);
- glVertex2fv(handle);
- glEnd();
- }
}
glPointSize(1.0f);
+
+ if (is_smooth) {
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
}
/* #define USE_XOR */
@@ -408,7 +493,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
const char draw_flag, const char draw_type,
const bool is_active,
- int width, int height)
+ const int width, const int height)
{
const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
BKE_mask_spline_resolution(spline, width, height));
@@ -482,7 +567,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
}
static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
- int width, int height)
+ const int width, const int height, const float xscale, const float yscale)
{
MaskLayer *masklay;
int i;
@@ -504,7 +589,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
/* ...and then handles over the curve so they're nicely visible */
- draw_spline_points(C, masklay, spline, draw_flag, draw_type);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
}
/* show undeform for testing */
@@ -514,7 +599,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
spline->points_deform = NULL;
draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
// draw_spline_parents(masklay, spline);
- draw_spline_points(C, masklay, spline, draw_flag, draw_type);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
spline->points_deform = back;
}
}
@@ -525,16 +610,21 @@ void ED_mask_draw(const bContext *C,
const char draw_flag, const char draw_type)
{
ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
int width, height;
+ float aspx, aspy;
+ float xscale, yscale;
if (!mask)
return;
ED_mask_get_size(sa, &width, &height);
+ ED_mask_get_aspect(sa, ar, &aspx, &aspy);
+ UI_view2d_getscale(&ar->v2d, &xscale, &yscale);
- draw_masklays(C, mask, draw_flag, draw_type, width, height);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy);
}
typedef struct ThreadedMaskRasterizeState {
@@ -719,7 +809,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
/* draw! */
- draw_masklays(C, mask, draw_flag, draw_type, width, height);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height, maxdim * zoomx, maxdim * zoomy);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index ad287a3af9f..af4645e31ec 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -570,8 +570,8 @@ void ED_operatormacros_mask(void)
"Add new vertex and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
ot->description = "Add new vertex and slide it";
WM_operatortype_macro_define(ot, "MASK_OT_add_vertex");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_boolean_set(otmacro->ptr, "release_confirm", TRUE);
+ otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point");
+ RNA_boolean_set(otmacro->ptr, "is_new_point", TRUE);
ot = WM_operatortype_append_macro("MASK_OT_add_feather_vertex_slide", "Add Feather Vertex and Slide",
"Add new vertex to feather and slide it", OPTYPE_UNDO | OPTYPE_REGISTER);
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 62872e72cb4..d95e07f043a 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -73,7 +73,7 @@ bool ED_mask_feather_find_nearest(
struct MaskSplinePoint *ED_mask_point_find_nearest(
const struct bContext *C, struct Mask *mask, const float normal_co[2], const float threshold,
- struct MaskLayer **masklay_r, struct MaskSpline **spline_r, bool *is_handle_r,
+ struct MaskLayer **masklay_r, struct MaskSpline **spline_r, eMaskWhichHandle *which_handle_r,
float *score);
void MASK_OT_layer_move(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index b9b456177ea..da91c59a094 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -59,9 +59,17 @@
/******************** utility functions *********************/
+static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point, /*const*/ eMaskWhichHandle which_handle,
+ const float scalex, const float scaley, float handle[2])
+{
+ BKE_mask_point_handle(point, which_handle, handle);
+ handle[0] *= scalex;
+ handle[1] *= scaley;
+}
+
MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const float normal_co[2], const float threshold,
- MaskLayer **masklay_r, MaskSpline **spline_r, bool *is_handle_r,
- float *score)
+ MaskLayer **masklay_r, MaskSpline **spline_r,
+ eMaskWhichHandle *which_handle_r, float *score)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -72,8 +80,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const
MaskSplinePoint *point = NULL;
float co[2];
const float threshold_sq = threshold * threshold;
- float len_sq = FLT_MAX, scalex, scaley;
- int is_handle = FALSE, width, height;
+ float len_sq= FLT_MAX, scalex, scaley;
+ eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE;
+ int width, height;
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
@@ -96,35 +105,64 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *cur_point = &spline->points[i];
MaskSplinePoint *cur_point_deform = &points_array[i];
- float cur_len_sq, vec[2], handle[2];
+ eMaskWhichHandle cur_which_handle;
+ float cur_len_sq, vec[2];
vec[0] = cur_point_deform->bezt.vec[1][0] * scalex;
vec[1] = cur_point_deform->bezt.vec[1][1] * scaley;
- if (BKE_mask_point_has_handle(cur_point)) {
- BKE_mask_point_handle(cur_point_deform, handle);
- handle[0] *= scalex;
- handle[1] *= scaley;
+ cur_len_sq = len_squared_v2v2(co, vec);
- cur_len_sq = len_squared_v2v2(co, handle);
+ if (cur_len_sq < len_sq) {
+ point_spline = spline;
+ point_masklay = masklay;
+ point = cur_point;
+ len_sq = cur_len_sq;
+ which_handle = MASK_WHICH_HANDLE_NONE;
+ }
- if (cur_len_sq < len_sq) {
- point_masklay = masklay;
- point_spline = spline;
- point = cur_point;
- len_sq = cur_len_sq;
- is_handle = TRUE;
+ if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) {
+ float handle[2];
+ mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
+ cur_len_sq = len_squared_v2v2(co, handle);
+ cur_which_handle = MASK_WHICH_HANDLE_STICK;
+ }
+ else {
+ float handle_left[2], handle_right[2];
+ float len_left_sq, len_right_sq;
+ mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
+ mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
+
+ len_left_sq = len_squared_v2v2(co, handle_left);
+ len_right_sq = len_squared_v2v2(co, handle_right);
+ if (i == 0) {
+ if (len_left_sq <= len_right_sq) {
+ cur_which_handle = MASK_WHICH_HANDLE_LEFT;
+ cur_len_sq = len_left_sq;
+ }
+ else {
+ cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
+ cur_len_sq = len_right_sq;
+ }
+ }
+ else {
+ if (len_right_sq <= len_left_sq) {
+ cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
+ cur_len_sq = len_right_sq;
+ }
+ else {
+ cur_which_handle = MASK_WHICH_HANDLE_LEFT;
+ cur_len_sq = len_left_sq;
+ }
}
}
- cur_len_sq = len_squared_v2v2(co, vec);
-
- if (cur_len_sq < len_sq) {
- point_spline = spline;
+ if (cur_len_sq <= len_sq) {
point_masklay = masklay;
+ point_spline = spline;
point = cur_point;
len_sq = cur_len_sq;
- is_handle = FALSE;
+ which_handle = cur_which_handle;
}
}
}
@@ -137,8 +175,8 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const
if (spline_r)
*spline_r = point_spline;
- if (is_handle_r)
- *is_handle_r = is_handle;
+ if (which_handle_r)
+ *which_handle_r = which_handle;
if (score)
*score = sqrtf(len_sq);
@@ -152,8 +190,8 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const
if (spline_r)
*spline_r = NULL;
- if (is_handle_r)
- *is_handle_r = FALSE;
+ if (which_handle_r)
+ *which_handle_r = MASK_WHICH_HANDLE_NONE;
return NULL;
}
@@ -423,18 +461,22 @@ typedef struct SlidePointData {
float co[2];
float vec[3][3];
+ char old_h1, old_h2;
Mask *mask;
MaskLayer *masklay;
MaskSpline *spline, *orig_spline;
MaskSplinePoint *point;
MaskSplinePointUW *uw;
+ eMaskWhichHandle which_handle;
float handle[2], no[2], feather[2];
int width, height;
float weight, weight_scalar;
short curvature_only, accurate;
short initial_feather, overall_feather;
+
+ bool is_sliding_new_point;
} SlidePointData;
static bool slide_point_check_initial_feather(MaskSpline *spline)
@@ -460,6 +502,41 @@ static bool slide_point_check_initial_feather(MaskSpline *spline)
return TRUE;
}
+static void select_sliding_point(Mask *mask, MaskLayer *mask_layer, MaskSpline *spline,
+ MaskSplinePoint *point)
+{
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ BKE_mask_point_select_set(point, TRUE);
+
+ mask_layer->act_spline = spline;
+ mask_layer->act_point = point;
+ ED_mask_select_flush_all(mask);
+}
+
+static void check_sliding_handle_type(MaskSplinePoint *point, eMaskWhichHandle which_handle)
+{
+ BezTriple *bezt = &point->bezt;
+
+ if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+ if (bezt->h1 == HD_VECT) {
+ bezt->h1 = HD_FREE;
+ }
+ else if (bezt->h1 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+ }
+ else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ if (bezt->h2 == HD_VECT) {
+ bezt->h2 = HD_FREE;
+ }
+ else if (bezt->h2 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
+ }
+}
+
static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
@@ -472,15 +549,15 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
MaskSplinePoint *point, *cv_point, *feather_point;
MaskSplinePointUW *uw = NULL;
int width, height, action = SLIDE_ACTION_NONE;
- bool is_handle = false;
const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
float co[2], cv_score, feather_score;
const float threshold = 19;
+ eMaskWhichHandle which_handle;
ED_mask_mouse_pos(sa, ar, event->mval, co);
ED_mask_get_size(sa, &width, &height);
- cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score);
+ cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &which_handle, &cv_score);
if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
if (slide_feather || !cv_point || feather_score < cv_score) {
@@ -493,7 +570,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
}
if (cv_point && action == SLIDE_ACTION_NONE) {
- if (is_handle)
+ if (which_handle != MASK_WHICH_HANDLE_NONE)
action = SLIDE_ACTION_HANDLE;
else
action = SLIDE_ACTION_POINT;
@@ -504,6 +581,8 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
}
if (action != SLIDE_ACTION_NONE) {
+ select_sliding_point(mask, masklay, spline, point);
+
customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
customdata->mask = mask;
@@ -515,6 +594,13 @@ 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 (uw) {
float co_uw[2];
float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
@@ -540,8 +626,10 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
customdata->initial_feather = slide_point_check_initial_feather(spline);
copy_m3_m3(customdata->vec, point->bezt.vec);
- if (BKE_mask_point_has_handle(point))
- BKE_mask_point_handle(point, customdata->handle);
+ if (which_handle != MASK_WHICH_HANDLE_NONE) {
+ BKE_mask_point_handle(point, which_handle, customdata->handle);
+ }
+ customdata->which_handle = which_handle;
ED_mask_mouse_pos(sa, ar, event->mval, customdata->co);
}
@@ -550,11 +638,16 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *
static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- SlidePointData *slidedata = slide_point_customdata(C, op, event);
+ Mask *mask = CTX_data_edit_mask(C);
+ SlidePointData *slidedata;
- if (slidedata) {
- Mask *mask = CTX_data_edit_mask(C);
+ if (mask == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ slidedata = slide_point_customdata(C, op, event);
+
+ if (slidedata) {
op->customdata = slidedata;
WM_event_add_modal_handler(C, op);
@@ -645,6 +738,8 @@ static void cancel_slide_point(SlidePointData *data)
}
else {
copy_m3_m3(data->point->bezt.vec, data->vec);
+ data->point->bezt.h1 = data->old_h1;
+ data->point->bezt.h2 = data->old_h2;
}
}
}
@@ -695,10 +790,34 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
sub_v2_v2v2(offco, co, data->co);
if (data->accurate)
mul_v2_fl(offco, 0.2f);
+
+ if (data->is_sliding_new_point && data->which_handle == MASK_WHICH_HANDLE_STICK) {
+ if (ELEM(data->point, &data->spline->points[0],
+ &data->spline->points[data->spline->tot_point - 1]))
+ {
+ SWAP(float, offco[0], offco[1]);
+ offco[1] *= -1;
+ }
+ }
+
add_v2_v2(offco, data->co);
add_v2_v2(offco, delta);
- BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec);
+ BKE_mask_point_set_handle(data->point, data->which_handle,
+ offco, data->curvature_only,
+ data->handle, data->vec);
+
+ if (data->is_sliding_new_point) {
+ if (ELEM(data->which_handle, MASK_WHICH_HANDLE_LEFT, MASK_WHICH_HANDLE_RIGHT)) {
+ BezTriple *bezt = &data->point->bezt;
+ float vec[2];
+ short self_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 0 : 2;
+ short other_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 2 : 0;
+
+ sub_v2_v2v2(vec, bezt->vec[1], bezt->vec[self_handle]);
+ add_v2_v2v2(bezt->vec[other_handle], bezt->vec[1], vec);
+ }
+ }
}
else if (data->action == SLIDE_ACTION_POINT) {
float delta[2];
@@ -826,6 +945,16 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
+ if (data->is_sliding_new_point) {
+ BezTriple *bezt = &data->point->bezt;
+ if (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) < FLT_EPSILON) {
+ bezt->h1 = HD_VECT;
+ }
+ if (len_squared_v2v2(bezt->vec[2], bezt->vec[1]) < FLT_EPSILON) {
+ bezt->h2 = HD_VECT;
+ }
+ }
+
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
DAG_id_tag_update(&data->mask->id, 0);
@@ -850,6 +979,8 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
void MASK_OT_slide_point(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Slide Point";
ot->description = "Slide control points";
@@ -858,12 +989,15 @@ void MASK_OT_slide_point(wmOperatorType *ot)
/* api callbacks */
ot->invoke = slide_point_invoke;
ot->modal = slide_point_modal;
- ot->poll = ED_maskedit_mask_poll;
+ ot->poll = ED_operator_mask;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide feather instead of vertex");
+
+ prop = RNA_def_boolean(ot->srna, "is_new_point", 0, "Slide New Point", "Newly created vertex is being slided");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/******************** toggle cyclic *********************/
@@ -887,6 +1021,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DAG_id_tag_update(&mask->id, 0);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
@@ -1218,7 +1353,25 @@ static int set_handle_type_exec(bContext *C, wmOperator *op)
if (MASKPOINT_ISSEL_ANY(point)) {
BezTriple *bezt = &point->bezt;
- bezt->h1 = bezt->h2 = handle_type;
+ if (bezt->f2 & SELECT) {
+ bezt->h1 = handle_type;
+ bezt->h2 = handle_type;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ bezt->h1 = handle_type;
+ }
+ if (bezt->f3 & SELECT) {
+ bezt->h2 = handle_type;
+ }
+ }
+
+ if (handle_type == HD_ALIGN) {
+ float vec[3];
+ sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
+ add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
+ }
+
changed = true;
}
}
@@ -1239,7 +1392,9 @@ void MASK_OT_handle_type_set(wmOperatorType *ot)
static EnumPropertyItem editcurve_handle_type_items[] = {
{HD_AUTO, "AUTO", 0, "Auto", ""},
{HD_VECT, "VECTOR", 0, "Vector", ""},
- {HD_ALIGN, "ALIGNED", 0, "Aligned", ""},
+ {HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
+ {HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
+ {HD_FREE, "FREE", 0, "Free", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index 16fd8414f22..29b5714be59 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -255,38 +255,36 @@ static int select_exec(bContext *C, wmOperator *op)
bool extend = RNA_boolean_get(op->ptr, "extend");
bool deselect = RNA_boolean_get(op->ptr, "deselect");
bool toggle = RNA_boolean_get(op->ptr, "toggle");
-
- bool is_handle = 0;
+ eMaskWhichHandle which_handle;
const float threshold = 19;
RNA_float_get_array(op->ptr, "location", co);
- point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL);
+ point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &which_handle, NULL);
if (extend == false && deselect == false && toggle == false)
ED_mask_select_toggle_all(mask, SEL_DESELECT);
if (point) {
-
- if (is_handle) {
+ if (which_handle != MASK_WHICH_HANDLE_NONE) {
if (extend) {
masklay->act_spline = spline;
masklay->act_point = point;
- BKE_mask_point_select_set_handle(point, TRUE);
+ BKE_mask_point_select_set_handle(point, which_handle, TRUE);
}
else if (deselect) {
- BKE_mask_point_select_set_handle(point, FALSE);
+ BKE_mask_point_select_set_handle(point, which_handle, FALSE);
}
else {
masklay->act_spline = spline;
masklay->act_point = point;
- if (!MASKPOINT_ISSEL_HANDLE(point)) {
- BKE_mask_point_select_set_handle(point, TRUE);
+ if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
+ BKE_mask_point_select_set_handle(point, which_handle, TRUE);
}
else if (toggle) {
- BKE_mask_point_select_set_handle(point, FALSE);
+ BKE_mask_point_select_set_handle(point, which_handle, FALSE);
}
}
}
@@ -444,11 +442,11 @@ static int border_select_exec(bContext *C, wmOperator *op)
if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) {
BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT);
- BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, mode == GESTURE_MODAL_SELECT);
}
else if (!extend) {
BKE_mask_point_select_set(point, FALSE);
- BKE_mask_point_select_set_handle(point, FALSE);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, FALSE);
}
changed = true;
@@ -531,7 +529,7 @@ static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
BKE_mask_point_select_set(point, select);
- BKE_mask_point_select_set_handle(point, select);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
}
changed = true;
@@ -649,7 +647,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
BKE_mask_point_select_set(point, mode == GESTURE_MODAL_SELECT);
- BKE_mask_point_select_set_handle(point, mode == GESTURE_MODAL_SELECT);
+ BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, mode == GESTURE_MODAL_SELECT);
changed = true;
}
@@ -702,14 +700,12 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
MaskSplinePoint *point = NULL;
float co[2];
int do_select = !RNA_boolean_get(op->ptr, "deselect");
-
- bool is_handle = false;
const float threshold = 19;
bool changed = false;
ED_mask_mouse_pos(sa, ar, event->mval, co);
- point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL);
+ point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, NULL, NULL);
if (point) {
ED_mask_spline_select_set(spline, do_select);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 886dea2e34b..0b3238c7d1e 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -6584,8 +6584,67 @@ typedef struct TransDataMasking {
MaskSplinePoint *point;
float parent_matrix[3][3];
float parent_inverse_matrix[3][3];
+ char orig_handle_type;
+
+ eMaskWhichHandle which_handle;
} TransDataMasking;
+static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which_handle,
+ TransData *td, TransData2D *td2d, TransDataMasking *tdm,
+ const float asp[2],
+ /*const*/ float parent_matrix[3][3],
+ /*const*/ float parent_inverse_matrix[3][3])
+{
+ BezTriple *bezt = &point->bezt;
+ short is_sel_any = MASKPOINT_ISSEL_ANY(point);
+
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
+
+ tdm->is_handle = TRUE;
+ copy_m3_m3(tdm->parent_matrix, parent_matrix);
+ copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
+
+ BKE_mask_point_handle(point, which_handle, tdm->handle);
+ tdm->which_handle = which_handle;
+
+ copy_v2_v2(tdm->orig_handle, tdm->handle);
+
+ mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
+ td2d->loc[0] *= asp[0];
+ td2d->loc[1] *= asp[1];
+ td2d->loc[2] = 0.0f;
+
+ td2d->loc2d = tdm->handle;
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (is_sel_any) {
+ td->flag |= TD_SELECTED;
+ }
+
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ if (which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+}
+
static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
TransData *td, TransData2D *td2d, TransDataMasking *tdm,
const int propmode, const float asp[2])
@@ -6595,14 +6654,15 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
const bool is_sel_any = MASKPOINT_ISSEL_ANY(point);
float parent_matrix[3][3], parent_inverse_matrix[3][3];
- tdm->point = point;
- copy_m3_m3(tdm->vec, bezt->vec);
-
BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix);
invert_m3_m3(parent_inverse_matrix, parent_matrix);
if (propmode || is_sel_point) {
int i;
+
+ tdm->point = point;
+ copy_m3_m3(tdm->vec, bezt->vec);
+
for (i = 0; i < 3; i++) {
copy_m3_m3(tdm->parent_matrix, parent_matrix);
copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
@@ -6645,49 +6705,64 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point,
unit_m3(td->mtx);
unit_m3(td->smtx);
+ if (i == 0) {
+ tdm->orig_handle_type = bezt->h1;
+ }
+ else if (i == 3) {
+ tdm->orig_handle_type = bezt->h2;
+ }
+
td++;
td2d++;
tdm++;
}
}
else {
- tdm->is_handle = TRUE;
- copy_m3_m3(tdm->parent_matrix, parent_matrix);
- copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix);
-
- BKE_mask_point_handle(point, tdm->handle);
-
- copy_v2_v2(tdm->orig_handle, tdm->handle);
-
- mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle);
- td2d->loc[0] *= asp[0];
- td2d->loc[1] *= asp[1];
- td2d->loc[2] = 0.0f;
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ MaskHandleToTransData(point, MASK_WHICH_HANDLE_STICK,
+ td, td2d, tdm, asp, parent_matrix,
+ parent_inverse_matrix);
- td2d->loc2d = tdm->handle;
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ MaskHandleToTransData(point, MASK_WHICH_HANDLE_LEFT,
+ td, td2d, tdm, asp, parent_matrix,
+ parent_inverse_matrix);
- td->flag = 0;
- td->loc = td2d->loc;
- mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]);
- copy_v3_v3(td->iloc, td->loc);
+ if (bezt->h1 == HD_VECT) {
+ bezt->h1 = HD_FREE;
+ }
+ else if (bezt->h1 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
- memset(td->axismtx, 0, sizeof(td->axismtx));
- td->axismtx[2][2] = 1.0f;
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ MaskHandleToTransData(point, MASK_WHICH_HANDLE_RIGHT,
+ td, td2d, tdm, asp, parent_matrix,
+ parent_inverse_matrix);
- td->ext = NULL;
- td->val = NULL;
+ if (bezt->h2 == HD_VECT) {
+ bezt->h2 = HD_FREE;
+ }
+ else if (bezt->h2 == HD_AUTO) {
+ bezt->h1 = HD_ALIGN_DOUBLESIDE;
+ bezt->h2 = HD_ALIGN_DOUBLESIDE;
+ }
- if (is_sel_any) {
- td->flag |= TD_SELECTED;
+ td++;
+ td2d++;
+ tdm++;
+ }
}
-
- td->dist = 0.0;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- td++;
- td2d++;
}
}
@@ -6731,10 +6806,23 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
MaskSplinePoint *point = &spline->points[i];
if (MASKPOINT_ISSEL_ANY(point)) {
- if (MASKPOINT_ISSEL_KNOT(point))
+ if (MASKPOINT_ISSEL_KNOT(point)) {
countsel += 3;
- else
- countsel += 1;
+ }
+ else {
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ countsel += 1;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ countsel++;
+ }
+ if (bezt->f3 & SELECT) {
+ countsel++;
+ }
+ }
+ }
}
if (propmode)
@@ -6782,9 +6870,24 @@ static void createTransMaskingData(bContext *C, TransInfo *t)
tdm += 3;
}
else {
- td++;
- td2d++;
- tdm++;
+ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ else {
+ BezTriple *bezt = &point->bezt;
+ if (bezt->f1 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ if (bezt->f3 & SELECT) {
+ td++;
+ td2d++;
+ tdm++;
+ }
+ }
}
}
}
@@ -6810,10 +6913,20 @@ void flushTransMasking(TransInfo *t)
mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d);
if (tdm->is_handle) {
- BKE_mask_point_set_handle(tdm->point, td->loc2d,
+ BKE_mask_point_set_handle(tdm->point, tdm->which_handle,
+ td->loc2d,
(t->flag & T_ALT_TRANSFORM) != 0,
tdm->orig_handle, tdm->vec);
}
+
+ if (t->state == TRANS_CANCEL) {
+ if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) {
+ tdm->point->bezt.h1 = tdm->orig_handle_type;
+ }
+ else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) {
+ tdm->point->bezt.h2 = tdm->orig_handle_type;
+ }
+ }
}
}
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 0c9e9b01a76..2d3a28fbd41 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -354,7 +354,8 @@ typedef enum eBezTriple_Handle {
HD_AUTO = 1,
HD_VECT = 2,
HD_ALIGN = 3,
- HD_AUTO_ANIM = 4 /* auto-clamped handles for animation */
+ HD_AUTO_ANIM = 4, /* auto-clamped handles for animation */
+ HD_ALIGN_DOUBLESIDE = 5, /* align handles, displayed both of them. used for masks */
} eBezTriple_Handle;
/* interpolation modes (used only for BezTriple->ipo) */
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 31e6b0e48e2..29bc15f1dbe 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -312,12 +312,83 @@ static int rna_MaskSplinePoint_handle_type_get(PointerRNA *ptr)
return bezt->h1;
}
+static MaskSpline *mask_spline_from_point(Mask *mask, MaskSplinePoint *point)
+{
+ MaskLayer *mask_layer;
+ for (mask_layer = mask->masklayers.first;
+ mask_layer;
+ mask_layer = mask_layer->next)
+ {
+ MaskSpline *spline;
+ for (spline = mask_layer->splines.first;
+ spline;
+ spline = spline->next)
+ {
+ if (point >= spline->points && point < spline->points + spline->tot_point) {
+ return spline;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void mask_point_check_stick(MaskSplinePoint *point)
+{
+ BezTriple *bezt = &point->bezt;
+ if (bezt->h1 == HD_ALIGN && bezt->h2 == HD_ALIGN) {
+ float vec[3];
+ sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
+ add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
+ }
+}
+
static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value)
{
MaskSplinePoint *point = (MaskSplinePoint *) ptr->data;
BezTriple *bezt = &point->bezt;
+ MaskSpline *spline = mask_spline_from_point((Mask *) ptr->id.data, point);
bezt->h1 = bezt->h2 = value;
+ mask_point_check_stick(point);
+ BKE_mask_calc_handle_point(spline, point);
+}
+
+static int rna_MaskSplinePoint_handle_left_type_get(PointerRNA *ptr)
+{
+ MaskSplinePoint *point = (MaskSplinePoint *) ptr->data;
+ BezTriple *bezt = &point->bezt;
+
+ return bezt->h1;
+}
+
+static void rna_MaskSplinePoint_handle_left_type_set(PointerRNA *ptr, int value)
+{
+ MaskSplinePoint *point = (MaskSplinePoint *) ptr->data;
+ BezTriple *bezt = &point->bezt;
+ MaskSpline *spline = mask_spline_from_point((Mask *) ptr->id.data, point);
+
+ bezt->h1 = value;
+ mask_point_check_stick(point);
+ BKE_mask_calc_handle_point(spline, point);
+}
+
+static int rna_MaskSplinePoint_handle_right_type_get(PointerRNA *ptr)
+{
+ MaskSplinePoint *point = (MaskSplinePoint *) ptr->data;
+ BezTriple *bezt = &point->bezt;
+
+ return bezt->h2;
+}
+
+static void rna_MaskSplinePoint_handle_right_type_set(PointerRNA *ptr, int value)
+{
+ MaskSplinePoint *point = (MaskSplinePoint *) ptr->data;
+ BezTriple *bezt = &point->bezt;
+ MaskSpline *spline = mask_spline_from_point((Mask *) ptr->id.data, point);
+
+ bezt->h2 = value;
+ mask_point_check_stick(point);
+ BKE_mask_calc_handle_point(spline, point);
}
/* ** API ** */
@@ -608,7 +679,9 @@ static void rna_def_maskSplinePoint(BlenderRNA *brna)
static EnumPropertyItem handle_type_items[] = {
{HD_AUTO, "AUTO", 0, "Auto", ""},
{HD_VECT, "VECTOR", 0, "Vector", ""},
- {HD_ALIGN, "ALIGNED", 0, "Aligned", ""},
+ {HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
+ {HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
+ {HD_FREE, "FREE", 0, "Free", ""},
{0, NULL, 0, NULL, NULL}};
rna_def_maskSplinePointUW(brna);
@@ -642,6 +715,27 @@ static void rna_def_maskSplinePoint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Handle Type", "Handle type");
RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+ /* handle_type */
+ prop = RNA_def_property(srna, "handle_left_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_MaskSplinePoint_handle_left_type_get", "rna_MaskSplinePoint_handle_left_type_set", NULL);
+ RNA_def_property_enum_items(prop, handle_type_items);
+ RNA_def_property_ui_text(prop, "Handle 1 Type", "Handle type");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+
+ /* handle_right */
+ prop = RNA_def_property(srna, "handle_right_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, "rna_MaskSplinePoint_handle_right_type_get", "rna_MaskSplinePoint_handle_right_type_set", NULL);
+ RNA_def_property_enum_items(prop, handle_type_items);
+ RNA_def_property_ui_text(prop, "Handle 2 Type", "Handle type");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+
+ /* weight */
+ prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "bezt.weight");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Weight", "Weight of the point");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_data");
+
/* select */
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bezt.f1", SELECT);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 41953fb0239..fd8d8aede87 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1292,7 +1292,7 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
-static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurbs)
+static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs, bool incl_lastsel, bool incl_vector)
{
PropertyRNA *prop;
@@ -1340,11 +1340,19 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurb
RNA_def_property_ui_text(prop, "Auto handle color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "handle_vect", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "handle_vect");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Vector handle color", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ if (incl_vector) {
+ prop = RNA_def_property(srna, "handle_vect", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "handle_vect");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Vector handle color", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "handle_sel_vect", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "handle_sel_vect");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Vector handle selected color", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+ }
prop = RNA_def_property(srna, "handle_align", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "handle_align");
@@ -1364,19 +1372,13 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurb
RNA_def_property_ui_text(prop, "Auto handle selected color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "handle_sel_vect", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "handle_sel_vect");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Vector handle selected color", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "handle_sel_align", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "handle_sel_align");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Align handle selected color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- if (incl_nurbs == 0) {
+ if (incl_nurbs == false) {
/* assume that when nurbs are off, this is for 2D (i.e. anim) editors */
prop = RNA_def_property(srna, "handle_auto_clamped", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "handle_auto_clamped");
@@ -1391,11 +1393,13 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurb
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
- prop = RNA_def_property(srna, "lastsel_point", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "lastsel_point");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Last selected point", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ if (incl_lastsel) {
+ prop = RNA_def_property(srna, "lastsel_point", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "lastsel_point");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Last selected point", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+ }
}
static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
@@ -1484,7 +1488,7 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_edge(srna);
rna_def_userdef_theme_spaces_face(srna);
- rna_def_userdef_theme_spaces_curves(srna, 1);
+ rna_def_userdef_theme_spaces_curves(srna, true, true, true);
prop = RNA_def_property(srna, "extra_edge_len", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -1628,7 +1632,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
rna_def_userdef_theme_spaces_vertex(srna);
- rna_def_userdef_theme_spaces_curves(srna, 0);
+ rna_def_userdef_theme_spaces_curves(srna, false, true, true);
prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -2247,6 +2251,8 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Other Object UVs", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false);
}
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
@@ -2759,6 +2765,8 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Strips Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false);
}
static void rna_def_userdef_themes(BlenderRNA *brna)