[Bf-blender-cvs] [9fac6765c8a] master: Nasking: Toggle cyclic on Ctrl-Click on initial vertex

Sergey Sharybin noreply at git.blender.org
Mon Nov 4 14:06:31 CET 2019


Commit: 9fac6765c8a5c5250a3262e68bbb6c0e8845ee32
Author: Sergey Sharybin
Date:   Thu Oct 31 16:44:47 2019 +0100
Branches: master
https://developer.blender.org/rB9fac6765c8a5c5250a3262e68bbb6c0e8845ee32

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

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

M	source/blender/editors/mask/mask_add.c

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

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)) {



More information about the Bf-blender-cvs mailing list