[Bf-blender-cvs] [f944121700d] master: GPencil: New operator to Normalize strokes

Antonio Vazquez noreply at git.blender.org
Wed Jun 2 16:43:43 CEST 2021


Commit: f944121700daf267766399ef368834be3cdec518
Author: Antonio Vazquez
Date:   Wed Jun 2 16:41:13 2021 +0200
Branches: master
https://developer.blender.org/rBf944121700daf267766399ef368834be3cdec518

GPencil: New operator to Normalize strokes

Sometimes is required to reset the thickness or the opacity of the strokes. Actually this was done using a modifier, but this operators solves this.

Reviewed By: mendio, filedescriptor

Maniphest Tasks: T87427

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

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

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

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index ae18fc4fb76..229b520e449 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -5035,6 +5035,10 @@ class VIEW3D_MT_edit_gpencil_stroke(Menu):
         layout.operator("gpencil.stroke_flip", text="Switch Direction")
         layout.prop(settings, "use_scale_thickness", text="Scale Thickness")
 
+        layout.separator()
+        layout.operator("gpencil.stroke_normalize", text="Normalize Thickness").mode = 'THICKNESS'
+        layout.operator("gpencil.stroke_normalize", text="Normalize Opacity").mode = 'OPACITY'
+
         layout.separator()
         layout.operator("gpencil.reset_transform_fill", text="Reset Fill Transform")
 
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e65afa1abff..dc0508bd608 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -5347,3 +5347,181 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot)
   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stroke Normalize Operator
+ * \{ */
+
+typedef enum eGP_NormalizeMode {
+  GP_NORMALIZE_THICKNESS = 0,
+  GP_NORMALIZE_OPACITY,
+} eGP_NormalizeMode;
+
+static bool gpencil_stroke_normalize_poll(bContext *C)
+{
+  Object *ob = CTX_data_active_object(C);
+  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+    return false;
+  }
+  bGPdata *gpd = (bGPdata *)ob->data;
+  if (gpd == NULL) {
+    return false;
+  }
+
+  bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+
+  return ((gpl != NULL) && (ob->mode == OB_MODE_EDIT_GPENCIL));
+}
+
+static void gpencil_stroke_normalize_ui(bContext *C, wmOperator *op)
+{
+  uiLayout *layout = op->layout;
+  uiLayout *row;
+
+  const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode");
+
+  uiLayoutSetPropSep(layout, true);
+  uiLayoutSetPropDecorate(layout, false);
+  row = uiLayoutRow(layout, true);
+  uiItemR(row, op->ptr, "mode", 0, NULL, ICON_NONE);
+
+  if (mode == GP_NORMALIZE_THICKNESS) {
+    row = uiLayoutRow(layout, true);
+    uiItemR(row, op->ptr, "value", 0, NULL, ICON_NONE);
+  }
+  else if (mode == GP_NORMALIZE_OPACITY) {
+    row = uiLayoutRow(layout, true);
+    uiItemR(row, op->ptr, "factor", 0, NULL, ICON_NONE);
+  }
+}
+
+static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op)
+{
+  bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+  /* Sanity checks. */
+  if (ELEM(NULL, gpd)) {
+    return OPERATOR_CANCELLED;
+  }
+
+  const eGP_NormalizeMode mode = RNA_enum_get(op->ptr, "mode");
+  const int value = RNA_int_get(op->ptr, "value");
+  const float factor = RNA_float_get(op->ptr, "factor");
+
+  /* Go through each editable + selected stroke. */
+  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+  const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+
+  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+    bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+
+    for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+      if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+
+        if (gpf == NULL) {
+          continue;
+        }
+
+        LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+
+          /* Skip strokes that are invalid for current view. */
+          if (ED_gpencil_stroke_can_use(C, gps) == false) {
+            continue;
+          }
+
+          bool selected = (is_curve_edit) ? gps->editcurve->flag |= GP_CURVE_SELECT :
+                                            (gps->flag & GP_STROKE_SELECT);
+          if (!selected) {
+            continue;
+          }
+
+          float stroke_thickness_inv = 1.0f / max_ii(gps->thickness, 1);
+          /* Fill opacity need to be managed before. */
+          if (mode == GP_NORMALIZE_OPACITY) {
+            gps->fill_opacity_fac = factor;
+            CLAMP(gps->fill_opacity_fac, 0.0f, 1.0f);
+          }
+
+          /* Loop all Polyline points. */
+          if (!is_curve_edit) {
+            for (int i = 0; i < gps->totpoints; i++) {
+              bGPDspoint *pt = &gps->points[i];
+              if (mode == GP_NORMALIZE_THICKNESS) {
+                pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f);
+              }
+              else if (mode == GP_NORMALIZE_OPACITY) {
+                pt->strength = factor;
+                CLAMP(pt->strength, 0.0f, 1.0f);
+              }
+            }
+          }
+          else {
+            /* Loop all Bezier points. */
+            for (int i = 0; i < gps->editcurve->tot_curve_points; i++) {
+              bGPDcurve_point *gpc_pt = &gps->editcurve->curve_points[i];
+              if (mode == GP_NORMALIZE_THICKNESS) {
+                gpc_pt->pressure = max_ff((float)value * stroke_thickness_inv, 0.0f);
+              }
+              else if (mode == GP_NORMALIZE_OPACITY) {
+                gpc_pt->strength = factor;
+                CLAMP(gpc_pt->strength, 0.0f, 1.0f);
+              }
+            }
+
+            gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+            BKE_gpencil_stroke_geometry_update(gpd, gps);
+          }
+        }
+        /* If not multiedit, exit loop. */
+        if (!is_multiedit) {
+          break;
+        }
+      }
+    }
+  }
+  CTX_DATA_END;
+
+  /* notifiers */
+  DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+  WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+  return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_normalize(wmOperatorType *ot)
+{
+  static const EnumPropertyItem prop_gpencil_normalize_modes[] = {
+      {GP_NORMALIZE_THICKNESS,
+       "THICKNESS",
+       0,
+       "Thickness",
+       "Normalizes the stroke thickness by making all points use the same thickness value"},
+      {GP_NORMALIZE_OPACITY,
+       "OPACITY",
+       0,
+       "Opacity",
+       "Normalizes the stroke opacity by making all points use the same opacity value"},
+      {0, NULL, 0, NULL, NULL},
+  };
+
+  /* identifiers */
+  ot->name = "Normalize Stroke";
+  ot->idname = "GPENCIL_OT_stroke_normalize";
+  ot->description = "Normalize stroke attributes";
+
+  /* api callbacks */
+  ot->exec = gpencil_stroke_normalize_exec;
+  ot->poll = gpencil_stroke_normalize_poll;
+  ot->ui = gpencil_stroke_normalize_ui;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  /* props */
+  ot->prop = RNA_def_enum(
+      ot->srna, "mode", prop_gpencil_normalize_modes, 0, "Mode", "Attribute to be normalized");
+  RNA_def_float(ot->srna, "factor", 1.0f, 0.0f, 1.0f, "Factor", "", 0.0f, 1.0f);
+  RNA_def_int(ot->srna, "value", 10, 0, 1000, "Value", "Value", 0, 1000);
+}
+
+/** \} */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 0e8fdc3c375..276e8c81e0f 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -488,6 +488,7 @@ void GPENCIL_OT_stroke_trim(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_merge_by_distance(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_merge_material(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_reset_vertex_color(struct wmOperatorType *ot);
+void GPENCIL_OT_stroke_normalize(struct wmOperatorType *ot);
 
 void GPENCIL_OT_material_to_vertex_color(struct wmOperatorType *ot);
 void GPENCIL_OT_extract_palette_vertex(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 0e9ce1d603f..35640cf3b66 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -649,6 +649,7 @@ void ED_operatortypes_gpencil(void)
   WM_operatortype_append(GPENCIL_OT_stroke_merge_by_distance);
   WM_operatortype_append(GPENCIL_OT_stroke_merge_material);
   WM_operatortype_append(GPENCIL_OT_stroke_reset_vertex_color);
+  WM_operatortype_append(GPENCIL_OT_stroke_normalize);
 
   WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
   WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);



More information about the Bf-blender-cvs mailing list