[Bf-blender-cvs] [70421bbe34f] soc-2020-greasepencil-curve: GPencil: Add point selection for curve handles

Falk David noreply at git.blender.org
Wed Jun 17 23:02:19 CEST 2020


Commit: 70421bbe34f286bdac4b0dd383dbcdcddaaa20f6
Author: Falk David
Date:   Wed Jun 17 23:01:37 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rB70421bbe34f286bdac4b0dd383dbcdcddaaa20f6

GPencil: Add point selection for curve handles

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

M	source/blender/editors/gpencil/gpencil_select.c

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

diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index b104cf5f0e4..765c2969ac4 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -59,6 +59,7 @@
 
 #include "ED_gpencil.h"
 #include "ED_select_utils.h"
+#include "ED_view3d.h"
 
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
@@ -131,6 +132,31 @@ static bool gpencil_select_poll(bContext *C)
   return false;
 }
 
+static bool error_threshold_display_poll(bContext *C)
+{
+  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+    if (gps->editcurve == NULL) {
+      return true;
+    }
+  }
+  CTX_DATA_END;
+  return false;
+}
+
+static void gpencil_select_ui(bContext *C, wmOperator *op)
+{
+  uiLayout *layout = op->layout;
+  PointerRNA ptr;
+
+  Object *ob = CTX_data_active_object(C);
+  bGPdata *gpd = ob->data;
+
+  if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) && error_threshold_display_poll(C)) {
+    RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+    uiItemR(layout, &ptr, "error_threshold", 0, NULL, ICON_NONE);
+  }
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -192,7 +218,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
   return OPERATOR_FINISHED;
 }
 
-static void property_error_threshold_define(wmOperatorType *ot)
+static void WM_operator_property_error_threshold(wmOperatorType *ot)
 {
   PropertyRNA *prop = RNA_def_float(ot->srna,
                                     "error_threshold",
@@ -206,31 +232,6 @@ static void property_error_threshold_define(wmOperatorType *ot)
   RNA_def_property_ui_range(prop, FLT_MIN, 10.0f, 0.1f, 5);
 }
 
-static bool error_threshold_display_poll(bContext *C)
-{
-  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
-    if (gps->editcurve == NULL) {
-      return true;
-    }
-  }
-  CTX_DATA_END;
-  return false;
-}
-
-static void select_all_ui(bContext *C, wmOperator *op)
-{
-  uiLayout *layout = op->layout;
-  PointerRNA ptr;
-
-  Object *ob = CTX_data_active_object(C);
-  bGPdata *gpd = ob->data;
-
-  if (GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) && error_threshold_display_poll(C)) {
-    RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
-    uiItemR(layout, &ptr, "error_threshold", 0, NULL, ICON_NONE);
-  }
-}
-
 void GPENCIL_OT_select_all(wmOperatorType *ot)
 {
   /* identifiers */
@@ -245,10 +246,10 @@ void GPENCIL_OT_select_all(wmOperatorType *ot)
   /* flags */
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
-  ot->ui = select_all_ui;
+  ot->ui = gpencil_select_ui;
 
   WM_operator_properties_select_all(ot);
-  property_error_threshold_define(ot);
+  WM_operator_property_error_threshold(ot);
 }
 
 /** \} */
@@ -1580,10 +1581,75 @@ static void deselect_all_selected(bContext *C)
       /* deselect stroke itself too */
       gps->flag &= ~GP_STROKE_SELECT;
     }
+    if (gps->editcurve != NULL) {
+      bGPDcurve *gpc = gps->editcurve;
+      for (int i = 0; i < gpc->tot_curve_points; i++) {
+        bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+        BezTriple *bezt = &gpc_pt->bezt;
+        gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+        BEZT_DESEL_ALL(bezt);
+      }
+
+      gpc->flag &= ~GP_CURVE_SELECT;
+    }
   }
   CTX_DATA_END;
 }
 
+static void gpencil_select_curve_point(bContext *C,
+                                       const int mval[2],
+                                       const int radius_squared,
+                                       bGPDcurve **r_gpc,
+                                       bGPDcurve_point **r_pt,
+                                       char *handle)
+{
+  ARegion *region = CTX_wm_region(C);
+  View3D *v3d = CTX_wm_view3d(C);
+  const bool only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
+
+  int hit_distance = radius_squared;
+
+  GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+  {
+    for (int i = 0; i < gpc->tot_curve_points; i++) {
+      bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+      BezTriple *bezt = &gpc_pt->bezt;
+
+      if (bezt->hide == 1) {
+        continue;
+      }
+
+      const bool handles_visible = (v3d->overlay.handle_display != CURVE_HANDLE_NONE) &&
+                                   (!only_selected || BEZT_ISSEL_ANY(bezt));
+
+      /* if the handles are not visible only check ctrl point (vec[1])*/
+      int from = (!handles_visible) ? 1 : 0;
+      int to = (!handles_visible) ? 2 : 3;
+
+      for (int j = from; j < to; j++) {
+        float parent_co[3];
+        mul_v3_m4v3(parent_co, gps_iter.diff_mat, bezt->vec[j]);
+        int screen_co[2];
+        if (ED_view3d_project_int_global(
+                region, parent_co, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
+            V3D_PROJ_RET_OK) {
+          if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
+            const int pt_distance = len_manhattan_v2v2_int(mval, screen_co);
+
+            if (pt_distance <= radius_squared && pt_distance < hit_distance) {
+              *r_gpc = gpc;
+              *r_pt = gpc_pt;
+              *handle = j;
+              hit_distance = pt_distance;
+            }
+          }
+        }
+      }
+    }
+  }
+  GP_EDITABLE_CURVES_END(gps_iter);
+}
+
 static int gpencil_select_exec(bContext *C, wmOperator *op)
 {
   ScrArea *area = CTX_wm_area(C);
@@ -1592,6 +1658,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
   ToolSettings *ts = CTX_data_tool_settings(C);
   const float scale = ts->gp_sculpt.isect_threshold;
   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
 
   /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
   const float radius = 0.4f * U.widget_unit;
@@ -1603,14 +1670,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
   bool toggle = RNA_boolean_get(op->ptr, "toggle");
   bool whole = RNA_boolean_get(op->ptr, "entire_strokes");
   const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all") && !use_shift_extend;
+  float error_threshold = RNA_float_get(op->ptr, "error_threshold");
 
   int mval[2] = {0};
+  /* get mouse location */
+  RNA_int_get_array(op->ptr, "location", mval);
 
   GP_SpaceConversion gsc = {NULL};
 
   bGPDlayer *hit_layer = NULL;
   bGPDstroke *hit_stroke = NULL;
   bGPDspoint *hit_point = NULL;
+  bGPDcurve *hit_curve = NULL;
+  bGPDcurve_point *hit_curve_point = NULL;
   int hit_distance = radius_squared;
 
   /* sanity checks */
@@ -1632,73 +1704,77 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
     whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE);
   }
 
-  /* init space conversion stuff */
-  gp_point_conversion_init(C, &gsc);
-
-  /* get mouse location */
-  RNA_int_get_array(op->ptr, "location", mval);
+  if (is_curve_edit) {
+    char handle = 0;
+    gpencil_select_curve_point(C, mval, radius_squared, &hit_curve, &hit_curve_point, &handle);
+  }
 
-  /* First Pass: Find stroke point which gets hit */
-  GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
-    bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
-    bGPDspoint *pt;
-    int i;
+  if (hit_curve_point == NULL) {
+    /* init space conversion stuff */
+    gp_point_conversion_init(C, &gsc);
 
-    /* Check boundbox to speedup. */
-    float fmval[2];
-    copy_v2fl_v2i(fmval, mval);
-    if (!ED_gpencil_stroke_check_collision(
-            &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
-      continue;
-    }
+    /* First Pass: Find stroke point which gets hit */
+    GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+      bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+      bGPDspoint *pt;
+      int i;
 
-    /* firstly, check for hit-point */
-    for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
-      int xy[2];
-      if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+      /* Check boundbox to speedup. */
+      float fmval[2];
+      copy_v2fl_v2i(fmval, mval);
+      if (!ED_gpencil_stroke_check_collision(
+              &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
         continue;
       }
 
-      bGPDspoint pt2;
-      gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
-      gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
-
-      /* do boundbox check first */
-      if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
-        const int pt_distance = len_manhattan_v2v2_int(mval, xy);
-
-        /* check if point is inside */
-        if (pt_distance <= radius_squared) {
-          /* only use this point if it is a better match than the current hit - T44685 */
-          if (pt_distance < hit_distance) {
-            hit_layer = gpl;
-            hit_stroke = gps_active;
-            hit_point = (!is_multiedit) ? pt->runtime.pt_orig : pt;
-            hit_distance = pt_distance;
+      /* firstly, check for hit-point */
+      for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+        int xy[2];
+        if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
+          continue;
+        }
+
+        bGPDspoint pt2;
+        gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
+        gp_point_to_xy(&gsc, gps, &pt2, &xy[0], &xy[1]);
+
+        /* do boundbox check first */
+        if (!ELEM(V2D_IS_CLIPPED, xy[0], xy[1])) {
+          const int pt_distance = len_manhattan_v2v2_int(mval, xy);
+
+          /* check if point is inside */
+          if (pt_distance <= radius_squared) {
+            /* only use this point if it is a better match than the current hit - T44685 */
+            if (pt_distance < hit_distance) {
+              hit_layer = gpl;
+              hit_stroke = gps_active;
+              hit_point = (!is_multiedit) ? pt->runtime.pt_orig : pt;
+              hit_distance = pt_distance;
+            }
           }
         }
       }
-    }
-    if (ELEM(NULL, hit_stroke, hit_point)) {
-      /* If nothing hit, check if the mouse is inside any filled stroke.
-       * Only check fi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list