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:
authorAntonio Vazquez <blendergit@gmail.com>2021-08-08 15:53:05 +0300
committerAntonio Vazquez <blendergit@gmail.com>2021-08-08 15:56:33 +0300
commita7aeec26550e24fa8b9d8f678afa65c48a5524d5 (patch)
treee5822af061c3a37a3c26ceb11192be393ab6c1b1
parenta7bb537a61c7c680bc01896ccf27a02c9e7a688a (diff)
GPencil: New Select Random operator
Select strokes or points randomly (similar to meshes). Reviewed By: pepeland Differential Revision: https://developer.blender.org/D12157
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c233
4 files changed, 236 insertions, 0 deletions
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++) {
@@ -513,6 +536,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
* \{ */