[Bf-blender-cvs] [5122c75fd62] soc-2020-greasepencil-curve: GPencil: Implement box and lasso curve select

Falk David noreply at git.blender.org
Tue Jul 14 16:53:19 CEST 2020


Commit: 5122c75fd62c244473e10e3242f3312378bebca9
Author: Falk David
Date:   Tue Jul 14 16:52:35 2020 +0200
Branches: soc-2020-greasepencil-curve
https://developer.blender.org/rB5122c75fd62c244473e10e3242f3312378bebca9

GPencil: Implement box and lasso curve select

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

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 d348b849f5b..d2f15f667b4 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -128,6 +128,61 @@ static bool gpencil_select_poll(bContext *C)
   return false;
 }
 
+static bool gpencil_3d_point_to_screen_space(ARegion *region,
+                                             const float diff_mat[4][4],
+                                             const float co[3],
+                                             int r_co[2])
+{
+  float parent_co[3];
+  mul_v3_m4v3(parent_co, diff_mat, co);
+  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])) {
+      copy_v2_v2_int(r_co, screen_co);
+      return true;
+    }
+  }
+  r_co[0] = V2D_IS_CLIPPED;
+  r_co[1] = V2D_IS_CLIPPED;
+  return false;
+}
+
+/* helper to deselect all selected strokes/points */
+static void deselect_all_selected(bContext *C)
+{
+  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+    /* deselect stroke and its points if selected */
+    if (gps->flag & GP_STROKE_SELECT) {
+      bGPDspoint *pt;
+      int i;
+
+      /* deselect points */
+      for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+        pt->flag &= ~GP_SPOINT_SELECT;
+      }
+
+      /* deselect curve and curve points */
+      if (gps->editcurve != NULL) {
+        bGPDcurve *gpc = gps->editcurve;
+        for (int j = 0; j < gpc->tot_curve_points; j++) {
+          bGPDcurve_point *gpc_pt = &gpc->curve_points[j];
+          BezTriple *bezt = &gpc_pt->bezt;
+          gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+          BEZT_DESEL_ALL(bezt);
+        }
+
+        gpc->flag &= ~GP_CURVE_SELECT;
+      }
+
+      /* deselect stroke itself too */
+      gps->flag &= ~GP_STROKE_SELECT;
+    }
+  }
+  CTX_DATA_END;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -1137,8 +1192,6 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd,
 }
 
 static bool gpencil_do_curve_circle_sel(bContext *C,
-                                        bGPdata *gpd,
-                                        bGPDlayer *gpl,
                                         bGPDstroke *gps,
                                         bGPDcurve *gpc,
                                         const int mx,
@@ -1278,25 +1331,24 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
   rect.xmax = mx + radius;
   rect.ymax = my + radius;
 
-  GP_SpaceConversion gsc = {NULL};
-  /* init space conversion stuff */
-  gpencil_point_conversion_init(C, &gsc);
-
   if (is_curve_edit) {
     if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
       ED_gpencil_select_curve_toggle_all(C, SEL_DESELECT);
       changed = true;
     }
 
-    /* TODO: do curve circle select */
     GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
     {
       changed |= gpencil_do_curve_circle_sel(
-          C, gpd, gpl, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode);
+          C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode);
     }
     GP_EDITABLE_CURVES_END(gps_iter);
   }
   else {
+    GP_SpaceConversion gsc = {NULL};
+    /* init space conversion stuff */
+    gpencil_point_conversion_init(C, &gsc);
+
     if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
       ED_gpencil_select_toggle_all(C, SEL_DESELECT);
       changed = true;
@@ -1365,18 +1417,203 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot)
  *
  * \{ */
 
-typedef bool (*GPencilTestFn)(bGPDstroke *gps,
-                              bGPDspoint *pt,
-                              const GP_SpaceConversion *gsc,
+typedef struct GP_SelectUserData {
+  int mx, my, radius;
+  /* Bounding box rect */
+  rcti rect;
+  const int (*lasso_coords)[2];
+  int lasso_coords_len;
+} GP_SelectUserData;
+
+typedef bool (*GPencilTestFn)(ARegion *region,
                               const float diff_mat[4][4],
-                              void *user_data);
+                              const float pt[3],
+                              GP_SelectUserData *user_data);
+
+static bool gpencil_generic_curve_select(bContext *C,
+                                         Object *ob,
+                                         bGPdata *gpd,
+                                         GPencilTestFn is_inside_fn,
+                                         rcti box,
+                                         GP_SelectUserData *user_data,
+                                         const bool strokemode,
+                                         const eSelectOp sel_op)
+{
+  ARegion *region = CTX_wm_region(C);
+  View3D *v3d = CTX_wm_view3d(C);
+  const bool handle_only_selected = (v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
+  const bool handle_all = (v3d->overlay.handle_display == CURVE_HANDLE_ALL);
+
+  // /* deselect handles first */
+  // if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+  //   GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+  //   {
+  //     /* deselect stroke and its points if selected */
+  //     if (gps->flag & GP_STROKE_SELECT) {
+  //       if (gps->editcurve != NULL) {
+  //         bGPDcurve *gpc = gps->editcurve;
+  //         for (int j = 0; j < gpc->tot_curve_points; j++) {
+  //           bGPDcurve_point *gpc_pt = &gpc->curve_points[j];
+  //           BezTriple *bezt = &gpc_pt->bezt;
+  //           if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
+  //             bezt->f1 &= ~SELECT;
+  //             bezt->f3 &= ~SELECT;
+  //           }
+
+  //           SET_FLAG_FROM_TEST(gpc_pt->flag, bezt->f1 || bezt->f3, GP_CURVE_POINT_SELECT);
+  //         }
+
+  //         gpc->flag &= ~GP_CURVE_SELECT;
+  //       }
+
+  //       /* deselect stroke itself too */
+  //       gps->flag &= ~GP_STROKE_SELECT;
+  //     }
+  //   }
+  //   GP_EDITABLE_CURVES_END(gps_iter);
+  // }
+
+  bool hit = false;
+  bool changed = false;
+
+  GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+  {
+    bool any_select = false;
+    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 = (handle_all || (handle_only_selected &&
+                                                   (gpc_pt->flag & GP_CURVE_POINT_SELECT)));
+
+      if (handles_visible) {
+        for (int j = 0; j < 3; j++) {
+          const bool is_select = BEZT_ISSEL_IDX(bezt, j);
+          bool is_inside = is_inside_fn(region, gps_iter.diff_mat, bezt->vec[j], user_data);
+          if (strokemode) {
+            if (is_inside) {
+              hit = true;
+              any_select = true;
+              break;
+            }
+          }
+          else {
+            const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+            if (sel_op_result != -1) {
+              if (sel_op_result) {
+                gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+                BEZT_SEL_IDX(bezt, j);
+                any_select = true;
+              }
+              else {
+                gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+                BEZT_DESEL_IDX(bezt, j);
+              }
+              changed = true;
+              hit = true;
+            }
+            else {
+              if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+                gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+                BEZT_DESEL_IDX(bezt, j);
+              }
+            }
+          }
+        }
+      }
+      /* if the handles are not visible only check ctrl point (vec[1])*/
+      else {
+        const bool is_select = bezt->f2;
+        bool is_inside = is_inside_fn(region, gps_iter.diff_mat, bezt->vec[1], user_data);
+        if (strokemode) {
+          if (is_inside) {
+            hit = true;
+            any_select = true;
+          }
+        }
+        else {
+          const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+          if (sel_op_result != -1) {
+            if (sel_op_result) {
+              gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+              bezt->f2 |= SELECT;
+              any_select = true;
+            }
+            else {
+              gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+              bezt->f2 &= ~SELECT;
+            }
+            changed = true;
+            hit = true;
+          }
+          else {
+            if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+              gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+              bezt->f2 &= ~SELECT;
+            }
+          }
+        }
+      }
+    }
+
+    if (!hit) {
+      /* check if we selected the inside of a filled curve */
+      MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+      if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+        continue;
+      }
+      int mval[2];
+      mval[0] = (box.xmax + box.xmin) / 2;
+      mval[1] = (box.ymax + box.ymin) / 2;
+
+      hit = false;
+    }
+
+    /* select the entire curve */
+    if (strokemode) {
+      const int sel_op_result = ED_select_op_action_deselected(sel_op, any_select, hit);
+      if (sel_op_result != -1) {
+        for (int i = 0; i < gpc->tot_curve_points; i++) {
+          bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+          BezTriple *bezt = &gpc_pt->bezt;
+
+          if (sel_op_result) {
+            gpc_pt->flag |= GP_CURVE_POINT_SELECT;
+            BEZT_SEL_ALL(bezt);
+          }
+          else {
+            gpc_pt->flag &= ~GP_CURVE_POINT_SELECT;
+            BEZT_DESEL_ALL(bezt);
+          }
+        }
+
+        if(sel_op_result) {
+          gpc->flag |= GP_CURVE_SELECT;
+        }
+        else {
+          gpc->flag &= ~GP_CURVE_SELECT;
+        }
+        changed = true;
+      }
+    }
+
+    BKE_gpencil_curve_sync_selection(gps);
+  }
+  GP_EDITABLE_CURVES_END(gps_iter);
+
+  return changed;
+}
 
 static bool gpencil_ge

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list