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>2019-10-31 18:44:47 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-11-04 12:54:59 +0300
commit9fac6765c8a5c5250a3262e68bbb6c0e8845ee32 (patch)
tree253272ec2902a53caf5c10948007f805a7ffc325 /source/blender/editors/mask
parente236f5b5749f256034e7605a66f611f1fad74c41 (diff)
Nasking: Toggle cyclic on Ctrl-Click on initial vertex
This change replaces old behavior when spline was toggled as cyclic on double-click. Doing so was tricky on a tablet and is rather non-intuitive in general. Differential Revision: https://developer.blender.org/D6162
Diffstat (limited to 'source/blender/editors/mask')
-rw-r--r--source/blender/editors/mask/mask_add.c106
1 files changed, 75 insertions, 31 deletions
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index dade81a5daf..5c730c74df7 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -591,12 +591,79 @@ static bool add_vertex_new(const bContext *C, Mask *mask, MaskLayer *mask_layer,
return true;
}
-static int add_vertex_exec(bContext *C, wmOperator *op)
+/* Convert coordinate from normalized space to pixel one.
+ * TODO(sergey): Make the function more generally available. */
+static void mask_point_make_pixel_space(bContext *C,
+ float point_normalized[2],
+ float point_pixel[2])
{
- Mask *mask = CTX_data_edit_mask(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
- float co[2];
+ float scalex, scaley;
+ ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
+
+ point_pixel[0] = point_normalized[0] * scalex;
+ point_pixel[1] = point_normalized[1] * scaley;
+}
+
+static int add_vertex_handle_cyclic_at_point(bContext *C,
+ Mask *mask,
+ MaskSpline *spline,
+ MaskSplinePoint *active_point,
+ MaskSplinePoint *other_point,
+ float co[2])
+{
+ const float tolerance_in_pixels_squared = 4 * 4;
+
+ if (spline->flag & MASK_SPLINE_CYCLIC) {
+ /* No cycling toggle needed, we've got nothing meaningful to do in this operator. */
+ return OPERATOR_CANCELLED;
+ }
+
+ float co_pixel[2];
+ mask_point_make_pixel_space(C, co, co_pixel);
+
+ float point_pixel[2];
+ mask_point_make_pixel_space(C, other_point->bezt.vec[1], point_pixel);
+
+ const float dist_squared = len_squared_v2v2(co_pixel, point_pixel);
+ if (dist_squared > tolerance_in_pixels_squared) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ spline->flag |= MASK_SPLINE_CYCLIC;
+
+ /* TODO, update keyframes in time. */
+ BKE_mask_calc_handle_point_auto(spline, active_point, false);
+ BKE_mask_calc_handle_point_auto(spline, other_point, false);
+
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ return OPERATOR_FINISHED;
+}
+
+static int add_vertex_handle_cyclic(
+ bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *active_point, float co[2])
+{
+ MaskSplinePoint *first_point = &spline->points[0];
+ MaskSplinePoint *last_point = &spline->points[spline->tot_point - 1];
+ const bool is_first_point_active = (active_point == first_point);
+ const bool is_last_point_active = (active_point == last_point);
+ if (is_last_point_active) {
+ return add_vertex_handle_cyclic_at_point(C, mask, spline, active_point, first_point, co);
+ }
+ else if (is_first_point_active) {
+ return add_vertex_handle_cyclic_at_point(C, mask, spline, active_point, last_point, co);
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int add_vertex_exec(bContext *C, wmOperator *op)
+{
+ Mask *mask = CTX_data_edit_mask(C);
if (mask == NULL) {
/* if there's no active mask, create one */
mask = ED_mask_new(C, NULL);
@@ -608,40 +675,17 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
mask_layer = NULL;
}
+ float co[2];
RNA_float_get_array(op->ptr, "location", co);
/* TODO, having an active point but no active spline is possible, why? */
if (mask_layer && mask_layer->act_spline && mask_layer->act_point &&
MASKPOINT_ISSEL_ANY(mask_layer->act_point)) {
-
- /* cheap trick - double click for cyclic */
MaskSpline *spline = mask_layer->act_spline;
- MaskSplinePoint *point = mask_layer->act_point;
-
- const bool is_sta = (point == spline->points);
- const bool is_end = (point == &spline->points[spline->tot_point - 1]);
-
- /* then check are we overlapping the mouse */
- if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) {
- if (spline->flag & MASK_SPLINE_CYCLIC) {
- /* nothing to do */
- return OPERATOR_CANCELLED;
- }
- else {
- /* recalc the connecting point as well to make a nice even curve */
- MaskSplinePoint *point_other = is_end ? spline->points :
- &spline->points[spline->tot_point - 1];
- spline->flag |= MASK_SPLINE_CYCLIC;
-
- /* TODO, update keyframes in time */
- BKE_mask_calc_handle_point_auto(spline, point, false);
- BKE_mask_calc_handle_point_auto(spline, point_other, false);
-
- DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
-
- WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- return OPERATOR_FINISHED;
- }
+ MaskSplinePoint *active_point = mask_layer->act_point;
+ const int cyclic_result = add_vertex_handle_cyclic(C, mask, spline, active_point, co);
+ if (cyclic_result != OPERATOR_PASS_THROUGH) {
+ return cyclic_result;
}
if (!add_vertex_subdivide(C, mask, co)) {