[Bf-blender-cvs] [b9dc338f0e5] greasepencil-object: GPencil: Basic Merge Material Stroke operator

Antonio Vazquez noreply at git.blender.org
Wed Oct 30 22:57:29 CET 2019


Commit: b9dc338f0e57b479b4fbe0d8d803dd26c895f2a9
Author: Antonio Vazquez
Date:   Wed Sep 4 17:32:32 2019 +0200
Branches: greasepencil-object
https://developer.blender.org/rBb9dc338f0e57b479b4fbe0d8d803dd26c895f2a9

GPencil: Basic Merge Material Stroke operator

Still needs more work on merge algorithm, but at least this is the basic structure.

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

M	source/blender/blenkernel/BKE_gpencil.h
M	source/blender/blenkernel/intern/gpencil.c
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_merge.c
M	source/blender/editors/gpencil/gpencil_ops.c

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

diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 8c02ff37311..4178bf9c923 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -28,6 +28,7 @@ struct BoundBox;
 struct Brush;
 struct CurveMapping;
 struct Depsgraph;
+struct GHash;
 struct ListBase;
 struct Main;
 struct Material;
@@ -105,6 +106,9 @@ bool BKE_gpencil_material_index_used(struct bGPdata *gpd, int index);
 void BKE_gpencil_material_remap(struct bGPdata *gpd,
                                 const unsigned int *remap,
                                 unsigned int remap_len);
+bool BKE_gpencil_merge_materials_table_get(struct Object *ob,
+                                           float threshold,
+                                           struct GHash *r_mat_table);
 
 /* statistics functions */
 void BKE_gpencil_stats_update(struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 07bc7716593..3a87c2858db 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -2108,6 +2108,87 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd,
 #undef MAT_NR_REMAP
 }
 
+/* Load a table with material conversion index for merged materials. */
+bool BKE_gpencil_merge_materials_table_get(Object *ob, float threshold, GHash *r_mat_table)
+{
+  bool changed = false;
+
+  Material *ma_primary = NULL;
+  Material *ma_secondary = NULL;
+  MaterialGPencilStyle *gp_style_primary = NULL;
+  MaterialGPencilStyle *gp_style_secondary = NULL;
+
+  short *totcol = give_totcolp(ob);
+  if (totcol == 0) {
+    return changed;
+  }
+
+  for (int idx_primary = 0; idx_primary < *totcol; idx_primary++) {
+    /* Read primary material to compare. */
+    ma_primary = BKE_material_gpencil_get(ob, idx_primary + 1);
+    if (ma_primary == NULL) {
+      continue;
+    }
+
+    for (int idx_secondary = idx_primary + 1; idx_secondary < *totcol; idx_secondary++) {
+      /* Read secondary material to compare with primary material. */
+      ma_secondary = BKE_material_gpencil_get(ob, idx_secondary + 1);
+      if ((ma_secondary == NULL) ||
+          (BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary)))) {
+        continue;
+      }
+      gp_style_primary = ma_primary->gp_style;
+      gp_style_secondary = ma_secondary->gp_style;
+
+      if ((gp_style_primary == NULL) || (gp_style_secondary == NULL) ||
+          (gp_style_secondary->flag & GP_STYLE_COLOR_LOCKED)) {
+        continue;
+      }
+
+      /* Check materials have the same mode. */
+      if (gp_style_primary->mode != gp_style_secondary->mode) {
+        continue;
+      }
+
+      /* Check materials have same stroke and fill attributes. */
+      if ((gp_style_primary->flag & GP_STYLE_STROKE_SHOW) !=
+          (gp_style_secondary->flag & GP_STYLE_STROKE_SHOW)) {
+        continue;
+      }
+
+      if ((gp_style_primary->flag & GP_STYLE_FILL_SHOW) !=
+          (gp_style_secondary->flag & GP_STYLE_FILL_SHOW)) {
+        continue;
+      }
+
+      /* Check materials have the same type. */
+      if ((gp_style_primary->stroke_style != gp_style_secondary->stroke_style) ||
+          (gp_style_primary->fill_style != gp_style_secondary->fill_style)) {
+        continue;
+      }
+
+      float stroke_a[4], stroke_b[4], fill_a[4], fill_b[4];
+      copy_v4_v4(stroke_a, gp_style_primary->stroke_rgba);
+      copy_v4_v4(stroke_b, gp_style_secondary->stroke_rgba);
+      copy_v4_v4(fill_a, gp_style_primary->fill_rgba);
+      copy_v4_v4(fill_b, gp_style_secondary->fill_rgba);
+
+      /* Check stroke and fill color. */
+      if ((!compare_v4v4(stroke_a, stroke_b, threshold)) ||
+          (!compare_v4v4(fill_a, fill_b, threshold))) {
+        continue;
+      }
+
+      /* Save conversion indexes. */
+      BLI_ghash_insert(
+          r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
+      changed = true;
+    }
+  }
+
+  return changed;
+}
+
 /* statistics functions */
 void BKE_gpencil_stats_update(bGPdata *gpd)
 {
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index f9517d7b441..d487a8e543b 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -494,6 +494,7 @@ void GPENCIL_OT_stroke_merge(struct wmOperatorType *ot);
 void GPENCIL_OT_stroke_cutter(struct wmOperatorType *ot);
 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_transform_uv(struct wmOperatorType *ot);
 void GPENCIL_OT_reset_uv_transform(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 36cef3ccdc0..3ce3c60a7c3 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -37,6 +37,7 @@
 #include "BKE_gpencil.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_report.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -569,3 +570,92 @@ void GPENCIL_OT_stroke_merge(wmOperatorType *ot)
   RNA_def_boolean(ot->srna, "clear_point", 0, "Dissolve Points", "Dissolve old selected points");
   RNA_def_boolean(ot->srna, "clear_stroke", 0, "Delete Strokes", "Delete old selected strokes");
 }
+
+/* Merge similar materials. */
+static bool gp_stroke_merge_material_poll(bContext *C)
+{
+  /* only supported with grease pencil objects */
+  Object *ob = CTX_data_active_object(C);
+  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+    return false;
+  }
+
+  return true;
+}
+
+static int gp_stroke_merge_material_exec(bContext *C, wmOperator *op)
+{
+  Object *ob = CTX_data_active_object(C);
+  bGPdata *gpd = (bGPdata *)ob->data;
+  const float threshold = RNA_float_get(op->ptr, "threshold");
+
+  /* Review materials. */
+  GHash *mat_table = BLI_ghash_int_new(__func__);
+
+  short *totcol = give_totcolp(ob);
+  if (totcol == 0) {
+    return OPERATOR_CANCELLED;
+  }
+
+  bool changed = BKE_gpencil_merge_materials_table_get(ob, threshold, mat_table);
+
+  int removed = BLI_ghash_len(mat_table);
+
+  /* Update stroke material index. */
+  if (changed) {
+    CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+      for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+        for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+          if (ED_gpencil_stroke_can_use(C, gps) == false) {
+            continue;
+          }
+          if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
+            continue;
+          }
+
+          if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
+            int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
+            gps->mat_nr = POINTER_AS_INT(idx);
+          }
+        }
+      }
+    }
+    CTX_DATA_END;
+  }
+
+  /* Free hash memory. */
+  BLI_ghash_free(mat_table, NULL, NULL);
+
+  /* notifiers */
+  if (changed) {
+    BKE_reportf(op->reports, RPT_INFO, "Merged %d materiales of %d", removed, *totcol);
+    DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+    WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+  }
+  else {
+    BKE_report(op->reports, RPT_INFO, "Nothing to merge");
+  }
+  return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_stroke_merge_material(wmOperatorType *ot)
+{
+  PropertyRNA *prop;
+
+  /* identifiers */
+  ot->name = "Merge Stroke Materials";
+  ot->idname = "GPENCIL_OT_stroke_merge_material";
+  ot->description = "Replace materials in strokes merging similar";
+
+  /* api callbacks */
+  ot->exec = gp_stroke_merge_material_exec;
+  ot->poll = gp_stroke_merge_material_poll;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  /* properties */
+  prop = RNA_def_float(ot->srna, "threshold", 0.01f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
+  /* avoid re-using last var */
+  RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index ff68907427d..69b2d00aa68 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -321,6 +321,7 @@ void ED_operatortypes_gpencil(void)
   WM_operatortype_append(GPENCIL_OT_stroke_cutter);
   WM_operatortype_append(GPENCIL_OT_stroke_trim);
   WM_operatortype_append(GPENCIL_OT_stroke_merge_by_distance);
+  WM_operatortype_append(GPENCIL_OT_stroke_merge_material);
 
   WM_operatortype_append(GPENCIL_OT_transform_uv);
   WM_operatortype_append(GPENCIL_OT_reset_uv_transform);



More information about the Bf-blender-cvs mailing list