[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