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:
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_merge.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c126
1 files changed, 111 insertions, 15 deletions
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 91339709162..9a7ad8d7220 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"
@@ -60,6 +61,7 @@ typedef struct tGPencilPointCache {
float x, y, z;
float pressure;
float strength;
+ float vert_color[4];
} tGPencilPointCache;
/* helper function to sort points */
@@ -93,6 +95,7 @@ static void gpencil_insert_points_to_stroke(bGPDstroke *gps,
pt_dst->uv_fac = 1.0f;
pt_dst->uv_rot = 0;
pt_dst->flag |= GP_SPOINT_SELECT;
+ copy_v4_v4(pt_dst->vert_color, point_elem->vert_color);
}
}
@@ -113,7 +116,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
/* if not exist, create a new one */
if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
- BKE_brush_gpencil_presets(bmain, ts);
+ BKE_brush_gpencil_paint_presets(bmain, ts);
}
Brush *brush = paint->brush;
@@ -125,25 +128,21 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
else {
add_frame_mode = GP_GETFRAME_ADD_NEW;
}
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, add_frame_mode);
/* stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
gps->totpoints = totpoints;
gps->inittime = 0.0f;
gps->thickness = brush->size;
- gps->gradient_f = brush->gpencil_settings->gradient_f;
- copy_v2_v2(gps->gradient_s, brush->gpencil_settings->gradient_s);
+ gps->hardeness = brush->gpencil_settings->hardeness;
+ copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio);
gps->flag |= GP_STROKE_SELECT;
gps->flag |= GP_STROKE_3DSPACE;
gps->mat_nr = ob->actcol - 1;
/* allocate memory for points */
gps->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, "gp_stroke_points");
- /* initialize triangle memory to dummy data */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
if (cyclic) {
gps->flag |= GP_STROKE_CYCLIC;
@@ -181,17 +180,14 @@ static void gpencil_get_elements_len(bContext *C, int *totstrokes, int *totpoint
static void gpencil_dissolve_points(bContext *C)
{
- bGPDstroke *gps, *gpsn;
-
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL) {
continue;
}
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
- gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_TAG, false, 0);
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
}
}
CTX_DATA_END;
@@ -224,7 +220,7 @@ static void gpencil_calc_points_factor(bContext *C,
if (gpf == NULL) {
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if (clear_stroke) {
@@ -239,6 +235,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&pt2->x, &pt->x);
pt2->pressure = pt->pressure;
pt2->strength = pt->strength;
+ copy_v4_v4(pt2->vert_color, pt->vert_color);
pt->flag &= ~GP_SPOINT_SELECT;
if (clear_point) {
pt->flag |= GP_SPOINT_TAG;
@@ -288,6 +285,7 @@ static void gpencil_calc_points_factor(bContext *C,
copy_v3_v3(&sort_pt->x, &pt2->x);
sort_pt->pressure = pt2->pressure;
sort_pt->strength = pt2->strength;
+ copy_v4_v4(sort_pt->vert_color, pt2->vert_color);
sort_pt->gps = gps_array[i];
@@ -336,6 +334,7 @@ static int gpencil_insert_to_array(tGPencilPointCache *src_array,
dst_elem->pressure = src_elem->pressure;
dst_elem->strength = src_elem->strength;
dst_elem->factor = src_elem->factor;
+ copy_v4_v4(dst_elem->vert_color, src_elem->vert_color);
}
return last;
@@ -458,7 +457,7 @@ static bool gp_strokes_merge_poll(bContext *C)
/* check hidden or locked materials */
MaterialGPencilStyle *gp_style = ma->gp_style;
- if ((gp_style->flag & GP_STYLE_COLOR_HIDE) || (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ if ((gp_style->flag & GP_MATERIAL_HIDE) || (gp_style->flag & GP_MATERIAL_LOCKED)) {
return false;
}
@@ -569,3 +568,100 @@ 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 hue_threshold = RNA_float_get(op->ptr, "hue_threshold");
+ const float sat_threshold = RNA_float_get(op->ptr, "sat_threshold");
+ const float val_threshold = RNA_float_get(op->ptr, "val_threshold");
+
+ /* Review materials. */
+ GHash *mat_table = BLI_ghash_int_new(__func__);
+
+ short *totcol = BKE_object_material_len_p(ob);
+ if (totcol == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bool changed = BKE_gpencil_merge_materials_table_get(
+ ob, hue_threshold, sat_threshold, val_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) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ 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 Grease Pencil 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, "hue_threshold", 0.001f, 0.0f, 1.0f, "Hue Threshold", "", 0.0f, 1.0f);
+ prop = RNA_def_float(
+ ot->srna, "sat_threshold", 0.001f, 0.0f, 1.0f, "Saturation Threshold", "", 0.0f, 1.0f);
+ prop = RNA_def_float(
+ ot->srna, "val_threshold", 0.001f, 0.0f, 1.0f, "Value Threshold", "", 0.0f, 1.0f);
+ /* avoid re-using last var */
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}