[Bf-blender-cvs] [a7aeec26550] master: GPencil: New Select Random operator

Antonio Vazquez noreply at git.blender.org
Sun Aug 8 14:56:39 CEST 2021


Commit: a7aeec26550e24fa8b9d8f678afa65c48a5524d5
Author: Antonio Vazquez
Date:   Sun Aug 8 14:53:05 2021 +0200
Branches: master
https://developer.blender.org/rBa7aeec26550e24fa8b9d8f678afa65c48a5524d5

GPencil: New Select Random operator

Select strokes or points randomly (similar to meshes).

Reviewed By: pepeland

Differential Revision: https://developer.blender.org/D12157

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

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_ops.c
M	source/blender/editors/gpencil/gpencil_select.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 20b706f5004..c6bc6d9b5d3 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1854,6 +1854,7 @@ class VIEW3D_MT_select_gpencil(Menu):
 
         layout.operator("gpencil.select_linked", text="Linked")
         layout.operator("gpencil.select_alternate")
+        layout.operator("gpencil.select_random")
         layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
 
         if context.mode == 'VERTEX_GPENCIL':
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index d1a1e417d9e..b6730cb123b 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -375,6 +375,7 @@ void GPENCIL_OT_select_less(struct wmOperatorType *ot);
 void GPENCIL_OT_select_first(struct wmOperatorType *ot);
 void GPENCIL_OT_select_last(struct wmOperatorType *ot);
 void GPENCIL_OT_select_alternate(struct wmOperatorType *ot);
+void GPENCIL_OT_select_random(struct wmOperatorType *ot);
 void GPENCIL_OT_select_vertex_color(struct wmOperatorType *ot);
 
 void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 35640cf3b66..8c78a402e81 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -555,6 +555,7 @@ void ED_operatortypes_gpencil(void)
   WM_operatortype_append(GPENCIL_OT_select_first);
   WM_operatortype_append(GPENCIL_OT_select_last);
   WM_operatortype_append(GPENCIL_OT_select_alternate);
+  WM_operatortype_append(GPENCIL_OT_select_random);
   WM_operatortype_append(GPENCIL_OT_select_vertex_color);
 
   WM_operatortype_append(GPENCIL_OT_duplicate);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 69734fa1ba8..4865cd3ecc4 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -33,6 +33,7 @@
 #include "BLI_ghash.h"
 #include "BLI_lasso_2d.h"
 #include "BLI_math_vector.h"
+#include "BLI_rand.h"
 #include "BLI_utildefines.h"
 
 #include "DNA_gpencil_types.h"
@@ -193,6 +194,28 @@ static void deselect_all_selected(bContext *C)
   CTX_DATA_END;
 }
 
+static void select_all_stroke_points(bGPdata *gpd, bGPDstroke *gps, bool select)
+{
+  for (int i = 0; i < gps->totpoints; i++) {
+    bGPDspoint *pt = &gps->points[i];
+    if (select) {
+      pt->flag |= GP_SPOINT_SELECT;
+    }
+    else {
+      pt->flag &= ~GP_SPOINT_SELECT;
+    }
+  }
+
+  if (select) {
+    gps->flag |= GP_STROKE_SELECT;
+    BKE_gpencil_stroke_select_index_set(gpd, gps);
+  }
+  else {
+    gps->flag &= ~GP_STROKE_SELECT;
+    BKE_gpencil_stroke_select_index_reset(gps);
+  }
+}
+
 static void select_all_curve_points(bGPdata *gpd, bGPDstroke *gps, bGPDcurve *gpc, bool deselect)
 {
   for (int i = 0; i < gpc->tot_curve_points; i++) {
@@ -512,6 +535,216 @@ void GPENCIL_OT_select_alternate(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Select Random Operator
+ * \{ */
+
+static int gpencil_select_random_exec(bContext *C, wmOperator *op)
+{
+  Object *ob = CTX_data_active_object(C);
+  ToolSettings *ts = CTX_data_tool_settings(C);
+  bGPdata *gpd = ED_gpencil_data_get_active(C);
+  if ((gpd == NULL) || (GPENCIL_NONE_EDIT_MODE(gpd))) {
+    return OPERATOR_CANCELLED;
+  }
+
+  const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends");
+  const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+  const float randfac = RNA_float_get(op->ptr, "ratio");
+  const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+  const int start = (unselect_ends) ? 1 : 0;
+  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+
+  int selectmode;
+  if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) {
+    selectmode = gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt);
+  }
+  else if (ob && ob->mode == OB_MODE_VERTEX_GPENCIL) {
+    selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+  }
+  else {
+    selectmode = ts->gpencil_selectmode_edit;
+  }
+
+  bool changed = false;
+  int seed_iter = seed;
+  int stroke_idx = 0;
+
+  if (is_curve_edit) {
+    GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+    {
+      /* Only apply to unselected strokes (if select). */
+      if (select) {
+        if ((gps->flag & GP_STROKE_SELECT) || (gps->totpoints == 0)) {
+          continue;
+        }
+      }
+      else {
+        if (((gps->flag & GP_STROKE_SELECT) == 0) || (gps->totpoints == 0)) {
+          continue;
+        }
+      }
+
+      /* Different seed by stroke. */
+      seed_iter += gps->totpoints + stroke_idx;
+      stroke_idx++;
+
+      if (selectmode == GP_SELECTMODE_STROKE) {
+        RNG *rng = BLI_rng_new(seed_iter);
+        const unsigned int j = BLI_rng_get_uint(rng) % gps->totpoints;
+        bool select_stroke = ((gps->totpoints * randfac) <= j) ? true : false;
+        select_stroke ^= select;
+        /* Curve function has select paremter inverted. */
+        select_all_curve_points(gpd, gps, gps->editcurve, !select_stroke);
+        changed = true;
+      }
+      else {
+        int elem_map_len = 0;
+        bGPDcurve_point **elem_map = MEM_mallocN(sizeof(*elem_map) * gpc->tot_curve_points,
+                                                 __func__);
+        bGPDcurve_point *ptc;
+        for (int i = start; i < gpc->tot_curve_points; i++) {
+          bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+          elem_map[elem_map_len++] = gpc_pt;
+        }
+
+        BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter);
+        const int count_select = elem_map_len * randfac;
+        for (int i = 0; i < count_select; i++) {
+          ptc = elem_map[i];
+          if (select) {
+            ptc->flag |= GP_SPOINT_SELECT;
+            BEZT_SEL_ALL(&ptc->bezt);
+          }
+          else {
+            ptc->flag &= ~GP_SPOINT_SELECT;
+            BEZT_DESEL_ALL(&ptc->bezt);
+          }
+        }
+        MEM_freeN(elem_map);
+
+        /* unselect start and end points */
+        if (unselect_ends) {
+          bGPDcurve_point *gpc_pt = &gpc->curve_points[0];
+          gpc_pt->flag &= ~GP_SPOINT_SELECT;
+          BEZT_DESEL_ALL(&gpc_pt->bezt);
+
+          gpc_pt = &gpc->curve_points[gpc->tot_curve_points - 1];
+          gpc_pt->flag &= ~GP_SPOINT_SELECT;
+          BEZT_DESEL_ALL(&gpc_pt->bezt);
+        }
+
+        BKE_gpencil_curve_sync_selection(gpd, gps);
+      }
+
+      changed = true;
+    }
+    GP_EDITABLE_CURVES_END(gps_iter);
+  }
+  else {
+    CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+      /* Only apply to unselected strokes (if select). */
+      if (select) {
+        if ((gps->flag & GP_STROKE_SELECT) || (gps->totpoints == 0)) {
+          continue;
+        }
+      }
+      else {
+        if (((gps->flag & GP_STROKE_SELECT) == 0) || (gps->totpoints == 0)) {
+          continue;
+        }
+      }
+
+      /* Different seed by stroke. */
+      seed_iter += gps->totpoints + stroke_idx;
+      stroke_idx++;
+
+      if (selectmode == GP_SELECTMODE_STROKE) {
+        RNG *rng = BLI_rng_new(seed_iter);
+        const unsigned int j = BLI_rng_get_uint(rng) % gps->totpoints;
+        bool select_stroke = ((gps->totpoints * randfac) <= j) ? true : false;
+        select_stroke ^= select;
+        select_all_stroke_points(gpd, gps, select_stroke);
+        changed = true;
+      }
+      else {
+        int elem_map_len = 0;
+        bGPDspoint **elem_map = MEM_mallocN(sizeof(*elem_map) * gps->totpoints, __func__);
+        bGPDspoint *pt;
+        for (int i = start; i < gps->totpoints; i++) {
+          pt = &gps->points[i];
+          elem_map[elem_map_len++] = pt;
+        }
+
+        BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter);
+        const int count_select = elem_map_len * randfac;
+        for (int i = 0; i < count_select; i++) {
+          pt = elem_map[i];
+          if (select) {
+            pt->flag |= GP_SPOINT_SELECT;
+          }
+          else {
+            pt->flag &= ~GP_SPOINT_SELECT;
+          }
+        }
+        MEM_freeN(elem_map);
+
+        /* unselect start and end points */
+        if (unselect_ends) {
+          pt = &gps->points[0];
+          pt->flag &= ~GP_SPOINT_SELECT;
+
+          pt = &gps->points[gps->totpoints - 1];
+          pt->flag &= ~GP_SPOINT_SELECT;
+        }
+
+        BKE_gpencil_stroke_sync_selection(gpd, gps);
+      }
+
+      changed = true;
+    }
+    CTX_DATA_END;
+  }
+
+  if (changed) {
+    /* updates */
+    DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+
+    /* copy on write tag is needed, or else no refresh happens */
+    DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+
+    WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+    WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+  }
+
+  return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_random(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "Random";
+  ot->idname = "GPENCIL_OT_select_random";
+  ot->description = "Select random points for non selected strokes";
+
+  /* callbacks */
+  ot->exec = gpencil_select_random_exec;
+  ot->poll = gpencil_select_poll;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  /* properties */
+  WM_operator_properties_select_random(ot);
+  RNA_def_boolean(ot->srna,
+                  "unselect_ends",
+                  false,
+                  "Unselect Ends",
+                  "Do not select the first and last point of the stroke");
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Select Grouped Operator
  * \{ */



More information about the Bf-blender-cvs mailing list