From f8c21937d2ba1140533c5e6f70426099f9680609 Mon Sep 17 00:00:00 2001 From: Henrik Dick Date: Thu, 7 Apr 2022 17:41:49 +0200 Subject: GPencil: Add skip option to envelope modifier This patch adds an option to only use every n-th segment of the envelope result. This can be used to reduce the complexity of the result. Differential Revision: http://developer.blender.org/D14503 --- .../gpencil_modifiers/intern/MOD_gpencilenvelope.c | 81 +++++++++++++--------- .../makesdna/DNA_gpencil_modifier_defaults.h | 1 + .../blender/makesdna/DNA_gpencil_modifier_types.h | 4 ++ .../blender/makesrna/intern/rna_gpencil_modifier.c | 7 ++ 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c index f8ac8d95493..d9881f5b7ae 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c @@ -332,18 +332,17 @@ static void add_stroke(Object *ob, bGPDstroke *gps, const int point_index, const int connection_index, - const int size, + const int size2, + const int size1, const int mat_nr, const float thickness, const float strength, ListBase *results) { + const int size = size1 + size2; bGPdata *gpd = ob->data; bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size, gps->thickness); - const int size1 = size == 4 ? 2 : 1; - const int size2 = size - size1; - memcpy(&gps_dst->points[0], &gps->points[connection_index], size1 * sizeof(bGPDspoint)); memcpy(&gps_dst->points[size1], &gps->points[point_index], size2 * sizeof(bGPDspoint)); @@ -369,35 +368,36 @@ static void add_stroke_cyclic(Object *ob, bGPDstroke *gps, const int point_index, const int connection_index, + const int size, const int mat_nr, const float thickness, const float strength, ListBase *results) { bGPdata *gpd = ob->data; - bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, 4, gps->thickness); + bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size * 2, gps->thickness); + if (gps->dvert != NULL) { + gps_dst->dvert = MEM_malloc_arrayN(size * 2, sizeof(MDeformVert), __func__); + } - int connection_index2 = (connection_index + 1) % gps->totpoints; - int point_index2 = (point_index + 1) % gps->totpoints; + for (int i = 0; i < size; i++) { + int a = (connection_index + i) % gps->totpoints; + int b = (point_index + i) % gps->totpoints; - gps_dst->points[0] = gps->points[connection_index]; - gps_dst->points[1] = gps->points[connection_index2]; - gps_dst->points[2] = gps->points[point_index]; - gps_dst->points[3] = gps->points[point_index2]; - for (int i = 0; i < 4; i++) { + gps_dst->points[i] = gps->points[a]; + gps_dst->points[size + i] = gps->points[b]; + + if (gps->dvert != NULL) { + BKE_defvert_array_copy(&gps_dst->dvert[i], &gps->dvert[a], 1); + BKE_defvert_array_copy(&gps_dst->dvert[size + i], &gps->dvert[b], 1); + } + } + for (int i = 0; i < size * 2; i++) { gps_dst->points[i].pressure *= thickness; gps_dst->points[i].strength *= strength; memset(&gps_dst->points[i].runtime, 0, sizeof(bGPDspoint_Runtime)); } - if (gps->dvert != NULL) { - gps_dst->dvert = MEM_malloc_arrayN(4, sizeof(MDeformVert), __func__); - BKE_defvert_array_copy(&gps_dst->dvert[0], &gps->dvert[connection_index], 1); - BKE_defvert_array_copy(&gps_dst->dvert[1], &gps->dvert[connection_index2], 1); - BKE_defvert_array_copy(&gps_dst->dvert[2], &gps->dvert[point_index], 1); - BKE_defvert_array_copy(&gps_dst->dvert[3], &gps->dvert[point_index2], 1); - } - BLI_addtail(results, gps_dst); /* Calc geometry data. */ @@ -459,31 +459,41 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp const int mat_nr = mmd->mat_nr < 0 ? gps->mat_nr : min_ii(mmd->mat_nr, ob->totcol - 1); if (mmd->mode == GP_ENVELOPE_FILLS) { + const int skip = min_ii(mmd->skip, min_ii(mmd->spread / 2, gps->totpoints - 2)); if (gps->flag & GP_STROKE_CYCLIC) { for (int i = 0; i < gps->totpoints; i++) { - const int connection_index = (i + mmd->spread) % gps->totpoints; - add_stroke_cyclic( - ob, gps, i, connection_index, mat_nr, mmd->thickness, mmd->strength, &duplicates); + const int connection_index = (i + mmd->spread - skip) % gps->totpoints; + add_stroke_cyclic(ob, + gps, + i, + connection_index, + 2 + skip, + mat_nr, + mmd->thickness, + mmd->strength, + &duplicates); + i += mmd->skip; } } else { - for (int i = 1; i < gps->totpoints - 1 && i < mmd->spread + 1; i++) { - add_stroke(ob, gps, i, 0, 3, mat_nr, mmd->thickness, mmd->strength, &duplicates); - } - for (int i = 0; i < gps->totpoints - 1; i++) { - const int connection_index = min_ii(i + mmd->spread, gps->totpoints - 1); - const int size = i == gps->totpoints - 2 ? 2 : - connection_index < gps->totpoints - 1 ? 4 : - 3; + for (int i = -mmd->spread + skip; i < gps->totpoints - 1; i++) { + const int point_index = max_ii(0, i); + const int connection_index = min_ii(i + mmd->spread + 1, gps->totpoints - 1); + const int size1 = min_ii(2 + skip, + min_ii(point_index + 1, gps->totpoints - point_index)); + const int size2 = min_ii( + 2 + skip, min_ii(connection_index + 1, gps->totpoints - connection_index)); add_stroke(ob, gps, - i, - connection_index, - size, + point_index, + connection_index + 1 - size2, + size1, + size2, mat_nr, mmd->thickness, mmd->strength, &duplicates); + i += mmd->skip; } } BLI_remlink(&gpf->strokes, gps); @@ -496,6 +506,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp const int connection_index = (i + 1 + mmd->spread) % gps->totpoints; add_stroke_simple( ob, gps, i, connection_index, mat_nr, mmd->thickness, mmd->strength, &duplicates); + i += mmd->skip; } } else { @@ -509,6 +520,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp mmd->thickness, mmd->strength, &duplicates); + i += mmd->skip; } } } @@ -585,6 +597,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) if (mode != GP_ENVELOPE_DEFORM) { uiItemR(layout, ptr, "strength", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "mat_nr", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "skip", 0, NULL, ICON_NONE); } gpencil_modifier_panel_end(layout, ptr); diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index 9d14ca039ac..750f97bb3c6 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -373,6 +373,7 @@ .mat_nr = -1, \ .thickness = 1.0f, \ .strength = 1.0f, \ + .skip = 0, \ } diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 6603ed1a078..b0e7342c9cb 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -1168,10 +1168,14 @@ typedef struct EnvelopeGpencilModifierData { float thickness; /** Strength multiplier for the new strokes. */ float strength; + /** Number of points to skip over. */ + int skip; /** Custom index for passes. */ int layer_pass; /* Length of the envelope effect. */ int spread; + + char _pad[4]; } EnvelopeGpencilModifierData; typedef enum eEnvelopeGpencil_Flag { diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index b09d8a4738d..04a9a6b169e 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -4126,6 +4126,13 @@ static void rna_def_modifier_gpencilenvelope(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Strength", "Multiplier for the strength of the new strokes"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "skip", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "skip"); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text( + prop, "Skip Segments", "The number of generated segments to skip to reduce complexity"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ENVELOPE_INVERT_LAYER); RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); -- cgit v1.2.3