From 39bc44ffc59ef1ad96893ce838c3a3484d072f44 Mon Sep 17 00:00:00 2001 From: Antonioya Date: Sun, 28 Oct 2018 18:08:24 +0100 Subject: GP: Refactor Instance modifier and rename to Array The old name Instance was logic when the modifier created new object instances, but now works equal to mesh Array modifier, so the old name was not logic and must be Array. Also added a Object to use as offset similar to mesh Array modifier. --- source/blender/blenkernel/BKE_gpencil.h | 2 +- source/blender/blenkernel/BKE_gpencil_modifier.h | 2 - .../blender/blenkernel/intern/gpencil_modifier.c | 41 --- .../blender/editors/space_outliner/outliner_draw.c | 2 +- source/blender/gpencil_modifiers/CMakeLists.txt | 2 +- .../gpencil_modifiers/MOD_gpencil_modifiertypes.h | 2 +- .../gpencil_modifiers/intern/MOD_gpencil_util.c | 2 +- .../gpencil_modifiers/intern/MOD_gpencilarray.c | 344 +++++++++++++++++++++ .../gpencil_modifiers/intern/MOD_gpencilinstance.c | 257 --------------- .../blender/makesdna/DNA_gpencil_modifier_types.h | 29 +- source/blender/makesrna/RNA_access.h | 2 +- .../blender/makesrna/intern/rna_gpencil_modifier.c | 48 ++- 12 files changed, 386 insertions(+), 347 deletions(-) create mode 100644 source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c delete mode 100644 source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c (limited to 'source') diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 8ab088eff02..1debfecc895 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -50,7 +50,7 @@ struct Brush; struct Object; struct bDeformGroup; struct SimplifyGpencilModifierData; -struct InstanceGpencilModifierData; +struct ArrayGpencilModifierData; struct LatticeGpencilModifierData; struct MDeformVert; diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index 5efc390015c..91f368613cb 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -234,8 +234,6 @@ typedef struct GpencilModifierTypeInfo { GreasePencilTexWalkFunc walk, void *userData); } GpencilModifierTypeInfo; -void BKE_gpencil_instance_modifier_instance_tfm(struct InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4]); - /* Initialize modifier's global data (type info and some common global storages). */ void BKE_gpencil_modifier_init(void); diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index abf6268a9a3..68691cd3d05 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -720,47 +720,6 @@ GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *na return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name)); } -/* helper function for per-instance positioning */ -void BKE_gpencil_instance_modifier_instance_tfm(InstanceGpencilModifierData *mmd, const int elem_idx[3], float r_mat[4][4]) -{ - float offset[3], rot[3], scale[3]; - int ri = mmd->rnd[0]; - float factor; - - offset[0] = mmd->offset[0] * elem_idx[0]; - offset[1] = mmd->offset[1] * elem_idx[1]; - offset[2] = mmd->offset[2] * elem_idx[2]; - - /* rotation */ - if (mmd->flag & GP_INSTANCE_RANDOM_ROT) { - factor = mmd->rnd_rot * mmd->rnd[ri]; - mul_v3_v3fl(rot, mmd->rot, factor); - add_v3_v3(rot, mmd->rot); - } - else { - copy_v3_v3(rot, mmd->rot); - } - - /* scale */ - if (mmd->flag & GP_INSTANCE_RANDOM_SIZE) { - factor = mmd->rnd_size * mmd->rnd[ri]; - mul_v3_v3fl(scale, mmd->scale, factor); - add_v3_v3(scale, mmd->scale); - } - else { - copy_v3_v3(scale, mmd->scale); - } - - /* advance random index */ - mmd->rnd[0]++; - if (mmd->rnd[0] > 19) { - mmd->rnd[0] = 1; - } - - /* calculate matrix */ - loc_eul_size_to_mat4(r_mat, offset, rot, scale); -} - void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag) { bGPDspoint *temp_points; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 1c45dc24108..41ec458c023 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1064,7 +1064,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case eGpencilModifierType_Tint: data.icon = ICON_COLOR; break; - case eGpencilModifierType_Instance: + case eGpencilModifierType_Array: data.icon = ICON_MOD_ARRAY; break; case eGpencilModifierType_Build: diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 00a387c58e8..b28a83372b8 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -50,7 +50,7 @@ set(SRC intern/MOD_gpencilthick.c intern/MOD_gpenciltint.c intern/MOD_gpencilcolor.c - intern/MOD_gpencilinstance.c + intern/MOD_gpencilarray.c intern/MOD_gpencilbuild.c intern/MOD_gpencilopacity.c intern/MOD_gpencillattice.c diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index d820bbcc7c8..07db9f15288 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -36,7 +36,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Simplify; extern GpencilModifierTypeInfo modifierType_Gpencil_Thick; extern GpencilModifierTypeInfo modifierType_Gpencil_Tint; extern GpencilModifierTypeInfo modifierType_Gpencil_Color; -extern GpencilModifierTypeInfo modifierType_Gpencil_Instance; +extern GpencilModifierTypeInfo modifierType_Gpencil_Array; extern GpencilModifierTypeInfo modifierType_Gpencil_Build; extern GpencilModifierTypeInfo modifierType_Gpencil_Opacity; extern GpencilModifierTypeInfo modifierType_Gpencil_Lattice; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index 1a61133f3f7..2551d9a216d 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -69,7 +69,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(Thick); INIT_GP_TYPE(Tint); INIT_GP_TYPE(Color); - INIT_GP_TYPE(Instance); + INIT_GP_TYPE(Array); INIT_GP_TYPE(Build); INIT_GP_TYPE(Opacity); INIT_GP_TYPE(Lattice); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c new file mode 100644 index 00000000000..b188dd0de0b --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -0,0 +1,344 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017, Blender Foundation + * This is a new part of Blender + * + * Contributor(s): Antonio Vazquez, Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/gpencil_modifiers/intern/MOD_gpencilinstance.c + * \ingroup modifiers + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_gpencil_modifier_types.h" + +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_gpencil.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_modifier.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_main.h" +#include "BKE_scene.h" +#include "BKE_layer.h" +#include "BKE_library_query.h" +#include "BKE_collection.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "MOD_gpencil_util.h" +#include "MOD_gpencil_modifiertypes.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +static void initData(GpencilModifierData *md) +{ + ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md; + gpmd->count = 2; + gpmd->offset[0] = 1.0f; + gpmd->offset[1] = 0.0f; + gpmd->offset[2] = 0.0f; + gpmd->shift[0] = 0.0f; + gpmd->shift[1] = 0.0f; + gpmd->shift[2] = 0.0f; + gpmd->scale[0] = 1.0f; + gpmd->scale[1] = 1.0f; + gpmd->scale[2] = 1.0f; + gpmd->rnd_rot = 0.5f; + gpmd->rnd_size = 0.5f; + gpmd->object = NULL; + + /* fill random values */ + BLI_array_frand(gpmd->rnd, 20, 1); + gpmd->rnd[0] = 1; +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copyData_generic(md, target); +} + +/* -------------------------------- */ +/* helper function for per-instance positioning */ +static void BKE_gpencil_instance_modifier_instance_tfm( + Object *ob, ArrayGpencilModifierData *mmd, const int elem_idx, + float r_mat[4][4], float r_offset[4][4]) +{ + float offset[3], rot[3], scale[3]; + int ri = mmd->rnd[0]; + float factor; + + offset[0] = mmd->offset[0] * elem_idx; + offset[1] = mmd->offset[1] * elem_idx; + offset[2] = mmd->offset[2] * elem_idx; + + /* rotation */ + if (mmd->flag & GP_ARRAY_RANDOM_ROT) { + factor = mmd->rnd_rot * mmd->rnd[ri]; + mul_v3_v3fl(rot, mmd->rot, factor); + add_v3_v3(rot, mmd->rot); + } + else { + copy_v3_v3(rot, mmd->rot); + } + + /* scale */ + if (mmd->flag & GP_ARRAY_RANDOM_SIZE) { + factor = mmd->rnd_size * mmd->rnd[ri]; + mul_v3_v3fl(scale, mmd->scale, factor); + add_v3_v3(scale, mmd->scale); + } + else { + copy_v3_v3(scale, mmd->scale); + } + + /* advance random index */ + mmd->rnd[0]++; + if (mmd->rnd[0] > 19) { + mmd->rnd[0] = 1; + } + + /* calculate matrix */ + loc_eul_size_to_mat4(r_mat, offset, rot, scale); + + copy_m4_m4(r_offset, r_mat); + + /* offset object */ + if (mmd->object) { + float mat_offset[4][4]; + float obinv[4][4]; + + unit_m4(mat_offset); + add_v3_v3(mat_offset[3], mmd->offset); + invert_m4_m4(obinv, ob->obmat); + + mul_m4_series(r_offset, mat_offset, + obinv, mmd->object->obmat); + copy_m4_m4(mat_offset, r_offset); + + /* clear r_mat locations to avoid double transform */ + zero_v3(r_mat[3]); + } +} + +/* array modifier - generate geometry callback (for viewport/rendering) */ +static void generate_geometry( + GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), + Object *ob, bGPDlayer *gpl, bGPDframe *gpf) +{ + ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md; + ListBase stroke_cache = {NULL, NULL}; + bGPDstroke *gps; + int idx; + + /* Check which strokes we can use once, and store those results in an array + * for quicker checking of what's valid (since string comparisons are expensive) + */ + const int num_strokes = BLI_listbase_count(&gpf->strokes); + int num_valid = 0; + + bool *valid_strokes = MEM_callocN(sizeof(bool) * num_strokes, __func__); + + for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) { + /* Record whether this stroke can be used + * ATTENTION: The logic here is the inverse of what's used everywhere else! + */ + if (is_stroke_affected_by_modifier(ob, + mmd->layername, mmd->pass_index, mmd->layer_pass, 1, gpl, gps, + mmd->flag & GP_ARRAY_INVERT_LAYER, mmd->flag & GP_ARRAY_INVERT_PASS, + mmd->flag & GP_ARRAY_INVERT_LAYERPASS)) + { + valid_strokes[idx] = true; + num_valid++; + } + } + + /* Early exit if no strokes can be copied */ + if (num_valid == 0) { + if (G.debug & G_DEBUG) { + printf("GP Array Mod - No strokes to be included\n"); + } + + MEM_SAFE_FREE(valid_strokes); + return; + } + + + /* Generate new instances of all existing strokes, + * keeping each instance together so they maintain + * the correct ordering relative to each other + */ + float current_offset[4][4]; + unit_m4(current_offset); + + for (int x = 0; x < mmd->count; x++) { + /* original strokes are at index = 0 */ + if (x == 0) { + continue; + } + + /* Compute transforms for this instance */ + float mat[4][4]; + float mat_offset[4][4]; + BKE_gpencil_instance_modifier_instance_tfm(ob, mmd, x, mat, mat_offset); + + if (mmd->object) { + /* recalculate cumulative offset here */ + mul_m4_m4m4(current_offset, current_offset, mat_offset); + } + else { + copy_m4_m4(current_offset, mat); + } + /* apply shift */ + madd_v3_v3fl(current_offset[3], mmd->shift, x); + + /* Duplicate original strokes to create this instance */ + for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) { + /* check if stroke can be duplicated */ + if (valid_strokes[idx]) { + /* Duplicate stroke */ + bGPDstroke *gps_dst = MEM_dupallocN(gps); + gps_dst->points = MEM_dupallocN(gps->points); + if (gps->dvert) { + gps_dst->dvert = MEM_dupallocN(gps->dvert); + BKE_gpencil_stroke_weights_duplicate(gps, gps_dst); + } + gps_dst->triangles = MEM_dupallocN(gps->triangles); + + /* Move points */ + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps_dst->points[i]; + if (mmd->object) { + /* apply local changes (rot/scale) */ + mul_m4_v3(mat, &pt->x); + } + /* global changes */ + mul_m4_v3(current_offset, &pt->x); + } + + /* if replace material, use new one */ + if ((mmd->mat_rpl > 0) && (mmd->mat_rpl <= ob->totcol)) { + gps_dst->mat_nr = mmd->mat_rpl - 1; + } + + /* Add new stroke to cache, to be added to the frame once + * all duplicates have been made + */ + BLI_addtail(&stroke_cache, gps_dst); + } + } + } + + /* merge newly created stroke instances back into the main stroke list */ + if (mmd->flag & GP_ARRAY_KEEP_ONTOP) { + BLI_movelisttolist_reverse(&gpf->strokes, &stroke_cache); + } + else { + BLI_movelisttolist(&gpf->strokes, &stroke_cache); + } + + /* free temp data */ + MEM_SAFE_FREE(valid_strokes); +} + +static void bakeModifier( + Main *UNUSED(bmain), Depsgraph *depsgraph, + GpencilModifierData *md, Object *ob) +{ + + bGPdata *gpd = ob->data; + + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + generate_geometry(md, depsgraph, ob, gpl, gpf); + } + } +} + +/* -------------------------------- */ + +/* Generic "generateStrokes" callback */ +static void generateStrokes( + GpencilModifierData *md, Depsgraph *depsgraph, + Object *ob, bGPDlayer *gpl, bGPDframe *gpf) +{ + generate_geometry(md, depsgraph, ob, gpl, gpf); +} + +static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + ArrayGpencilModifierData *lmd = (ArrayGpencilModifierData *)md; + if (lmd->object != NULL) { + DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Array Modifier"); + DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Array Modifier"); + } + DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Array Modifier"); +} + +static void foreachObjectLink( + GpencilModifierData *md, Object *ob, + ObjectWalkFunc walk, void *userData) +{ + ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md; + + walk(userData, ob, &mmd->object, IDWALK_CB_NOP); +} + + +GpencilModifierTypeInfo modifierType_Gpencil_Array = { + /* name */ "Array", + /* structName */ "ArrayGpencilModifierData", + /* structSize */ sizeof(ArrayGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ 0, + + /* copyData */ copyData, + + /* deformStroke */ NULL, + /* generateStrokes */ generateStrokes, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ NULL, + /* foreachObjectLink */ foreachObjectLink, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c deleted file mode 100644 index 9c56a06af99..00000000000 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2017, Blender Foundation - * This is a new part of Blender - * - * Contributor(s): Antonio Vazquez, Joshua Leung - * - * ***** END GPL LICENSE BLOCK ***** - * - */ - -/** \file blender/gpencil_modifiers/intern/MOD_gpencilinstance.c - * \ingroup modifiers - */ - -#include - -#include "MEM_guardedalloc.h" - -#include "DNA_scene_types.h" -#include "DNA_object_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_gpencil_modifier_types.h" - -#include "BLI_blenlib.h" -#include "BLI_rand.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "BKE_gpencil.h" -#include "BKE_gpencil_modifier.h" -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_object.h" -#include "BKE_main.h" -#include "BKE_scene.h" -#include "BKE_layer.h" -#include "BKE_collection.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_query.h" - -#include "MOD_gpencil_util.h" -#include "MOD_gpencil_modifiertypes.h" - -static void initData(GpencilModifierData *md) -{ - InstanceGpencilModifierData *gpmd = (InstanceGpencilModifierData *)md; - gpmd->count[0] = 1; - gpmd->count[1] = 1; - gpmd->count[2] = 1; - gpmd->offset[0] = 1.0f; - gpmd->offset[1] = 1.0f; - gpmd->offset[2] = 1.0f; - gpmd->shift[0] = 0.0f; - gpmd->shift[1] = 0.0f; - gpmd->shift[2] = 0.0f; - gpmd->scale[0] = 1.0f; - gpmd->scale[1] = 1.0f; - gpmd->scale[2] = 1.0f; - gpmd->rnd_rot = 0.5f; - gpmd->rnd_size = 0.5f; - gpmd->lock_axis |= GP_LOCKAXIS_X; - - /* fill random values */ - BLI_array_frand(gpmd->rnd, 20, 1); - gpmd->rnd[0] = 1; -} - -static void copyData(const GpencilModifierData *md, GpencilModifierData *target) -{ - BKE_gpencil_modifier_copyData_generic(md, target); -} - -/* -------------------------------- */ - -/* array modifier - generate geometry callback (for viewport/rendering) */ -/* TODO: How to skip this for the simplify options? --> !GP_SIMPLIFY_MODIF(ts, playing) */ -static void generate_geometry( - GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), - Object *ob, bGPDlayer *gpl, bGPDframe *gpf) -{ - InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; - ListBase stroke_cache = {NULL, NULL}; - bGPDstroke *gps; - int idx; - - /* Check which strokes we can use once, and store those results in an array - * for quicker checking of what's valid (since string comparisons are expensive) - */ - const int num_strokes = BLI_listbase_count(&gpf->strokes); - int num_valid = 0; - - bool *valid_strokes = MEM_callocN(sizeof(bool) * num_strokes, __func__); - - for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) { - /* Record whether this stroke can be used - * ATTENTION: The logic here is the inverse of what's used everywhere else! - */ - if (is_stroke_affected_by_modifier(ob, - mmd->layername, mmd->pass_index, mmd->layer_pass, 1, gpl, gps, - mmd->flag & GP_INSTANCE_INVERT_LAYER, mmd->flag & GP_INSTANCE_INVERT_PASS, - mmd->flag & GP_INSTANCE_INVERT_LAYERPASS)) - { - valid_strokes[idx] = true; - num_valid++; - } - } - - /* Early exit if no strokes can be copied */ - if (num_valid == 0) { - if (G.debug & G_DEBUG) { - printf("GP Array Mod - No strokes to be included\n"); - } - - MEM_SAFE_FREE(valid_strokes); - return; - } - - - /* Generate new instances of all existing strokes, - * keeping each instance together so they maintain - * the correct ordering relative to each other - */ - for (int x = 0; x < mmd->count[0]; x++) { - for (int y = 0; y < mmd->count[1]; y++) { - for (int z = 0; z < mmd->count[2]; z++) { - /* original strokes are at index = 0,0,0 */ - if ((x == 0) && (y == 0) && (z == 0)) { - continue; - } - - /* Compute transforms for this instance */ - const int elem_idx[3] = {x, y, z}; - float mat[4][4]; - - BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat); - - /* apply shift */ - int sh = x; - if (mmd->lock_axis == GP_LOCKAXIS_Y) { - sh = y; - } - if (mmd->lock_axis == GP_LOCKAXIS_Z) { - sh = z; - } - madd_v3_v3fl(mat[3], mmd->shift, sh); - - /* Duplicate original strokes to create this instance */ - for (gps = gpf->strokes.first, idx = 0; gps; gps = gps->next, idx++) { - /* check if stroke can be duplicated */ - if (valid_strokes[idx]) { - /* Duplicate stroke */ - bGPDstroke *gps_dst = MEM_dupallocN(gps); - gps_dst->points = MEM_dupallocN(gps->points); - if (gps->dvert) { - gps_dst->dvert = MEM_dupallocN(gps->dvert); - BKE_gpencil_stroke_weights_duplicate(gps, gps_dst); - } - gps_dst->triangles = MEM_dupallocN(gps->triangles); - - /* Move points */ - for (int i = 0; i < gps->totpoints; i++) { - bGPDspoint *pt = &gps_dst->points[i]; - mul_m4_v3(mat, &pt->x); - } - - /* if replace material, use new one */ - if ((mmd->mat_rpl > 0) && (mmd->mat_rpl <= ob->totcol)) { - gps_dst->mat_nr = mmd->mat_rpl - 1; - } - - /* Add new stroke to cache, to be added to the frame once - * all duplicates have been made - */ - BLI_addtail(&stroke_cache, gps_dst); - } - } - } - } - } - - /* merge newly created stroke instances back into the main stroke list */ - if (mmd->flag & GP_INSTANCE_KEEP_ONTOP) { - BLI_movelisttolist_reverse(&gpf->strokes, &stroke_cache); - } - else { - BLI_movelisttolist(&gpf->strokes, &stroke_cache); - } - - /* free temp data */ - MEM_SAFE_FREE(valid_strokes); -} - -static void bakeModifier( - Main *UNUSED(bmain), Depsgraph *depsgraph, - GpencilModifierData *md, Object *ob) -{ - - bGPdata *gpd = ob->data; - - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { - generate_geometry(md, depsgraph, ob, gpl, gpf); - } - } -} - -/* -------------------------------- */ - -/* Generic "generateStrokes" callback */ -static void generateStrokes( - GpencilModifierData *md, Depsgraph *depsgraph, - Object *ob, bGPDlayer *gpl, bGPDframe *gpf) -{ - generate_geometry(md, depsgraph, ob, gpl, gpf); -} - -GpencilModifierTypeInfo modifierType_Gpencil_Instance = { - /* name */ "Instance", - /* structName */ "InstanceGpencilModifierData", - /* structSize */ sizeof(InstanceGpencilModifierData), - /* type */ eGpencilModifierTypeType_Gpencil, - /* flags */ 0, - - /* copyData */ copyData, - - /* deformStroke */ NULL, - /* generateStrokes */ generateStrokes, - /* bakeModifier */ bakeModifier, - /* remapTime */ NULL, - - /* initData */ initData, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepsgraph */ NULL, - /* dependsOnTime */ NULL, - /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, -}; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 65c75c151cd..191588a9d36 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -40,7 +40,7 @@ typedef enum GpencilModifierType { eGpencilModifierType_Subdiv = 2, eGpencilModifierType_Thick = 3, eGpencilModifierType_Tint = 4, - eGpencilModifierType_Instance = 5, + eGpencilModifierType_Array = 5, eGpencilModifierType_Build = 6, eGpencilModifierType_Opacity = 7, eGpencilModifierType_Color = 8, @@ -235,9 +235,10 @@ typedef enum eOpacityGpencil_Flag { GP_OPACITY_INVERT_LAYERPASS = (1 << 4), } eOpacityGpencil_Flag; -typedef struct InstanceGpencilModifierData { +typedef struct ArrayGpencilModifierData { GpencilModifierData modifier; - int count[3]; /* number of elements in array */ + struct Object *object; + int count; /* number of elements in array */ int flag; /* several flags */ float offset[3]; /* Location increments */ float shift[3]; /* shift increment */ @@ -246,22 +247,22 @@ typedef struct InstanceGpencilModifierData { float rot[3]; /* Rotation changes */ float scale[3]; /* Scale changes */ float rnd[20]; /* (first element is the index) random values */ - int lock_axis; /* lock shift to one axis */ + char pad_[4]; int pass_index; /* custom index for passes */ char layername[64]; /* layer name */ int mat_rpl; /* material replace (0 keep default) */ int layer_pass; /* custom index for passes */ -} InstanceGpencilModifierData; - -typedef enum eInstanceGpencil_Flag { - GP_INSTANCE_RANDOM_SIZE = (1 << 0), - GP_INSTANCE_RANDOM_ROT = (1 << 1), - GP_INSTANCE_INVERT_LAYER = (1 << 2), - GP_INSTANCE_INVERT_PASS = (1 << 3), - GP_INSTANCE_KEEP_ONTOP = (1 << 4), - GP_INSTANCE_INVERT_LAYERPASS = (1 << 5), -} eInstanceGpencil_Flag; +} ArrayGpencilModifierData; + +typedef enum eArrayGpencil_Flag { + GP_ARRAY_RANDOM_SIZE = (1 << 0), + GP_ARRAY_RANDOM_ROT = (1 << 1), + GP_ARRAY_INVERT_LAYER = (1 << 2), + GP_ARRAY_INVERT_PASS = (1 << 3), + GP_ARRAY_KEEP_ONTOP = (1 << 4), + GP_ARRAY_INVERT_LAYERPASS = (1 << 5), +} eArrayGpencil_Flag; typedef struct BuildGpencilModifierData { GpencilModifierData modifier; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 0125b7c7b37..c1152058739 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -607,7 +607,7 @@ extern StructRNA RNA_ThickGpencilModifier; extern StructRNA RNA_TintGpencilModifier; extern StructRNA RNA_TimeGpencilModifier; extern StructRNA RNA_ColorGpencilModifier; -extern StructRNA RNA_InstanceGpencilModifier; +extern StructRNA RNA_ArrayGpencilModifier; extern StructRNA RNA_DupliGpencilModifier; extern StructRNA RNA_OpacityGpencilModifier; extern StructRNA RNA_LatticeGpencilModifier; diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 37bcd83e8b7..0be38cbc558 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -61,7 +61,7 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { {0, "", 0, N_("Generate"), "" }, - {eGpencilModifierType_Instance, "GP_INSTANCE", ICON_MOD_ARRAY, "Instance", "Create grid of duplicate instances"}, + {eGpencilModifierType_Array, "GP_ARRAY", ICON_MOD_ARRAY, "Array", "Create array of duplicate instances"}, {eGpencilModifierType_Build, "GP_BUILD", ICON_MOD_BUILD, "Build", "Create duplication of strokes"}, {eGpencilModifierType_Mirror, "GP_MIRROR", ICON_MOD_MIRROR, "Mirror", "Duplicate strokes like a mirror"}, {eGpencilModifierType_Simplify, "GP_SIMPLIFY", ICON_MOD_DECIM, "Simplify", "Simplify stroke reducing number of points"}, @@ -103,13 +103,6 @@ static const EnumPropertyItem modifier_gphook_falloff_items[] = { { 0, NULL, 0, NULL, NULL } }; -static const EnumPropertyItem rna_enum_gpencil_lockshift_items[] = { - { GP_LOCKAXIS_X, "GP_LOCKAXIS_X", 0, "X", "Use X axis" }, - { GP_LOCKAXIS_Y, "GP_LOCKAXIS_Y", 0, "Y", "Use Y axis" }, - { GP_LOCKAXIS_Z, "GP_LOCKAXIS_Z", 0, "Z", "Use Z axis" }, - { 0, NULL, 0, NULL, NULL } -}; - static const EnumPropertyItem rna_enum_time_mode_items[] = { { GP_TIME_MODE_NORMAL, "NORMAL", 0, "Normal", "Apply offset in normal animation direction" }, { GP_TIME_MODE_REVERSE, "REVERSE", 0, "Reverse", "Apply offset in reverse animation direction" }, @@ -154,8 +147,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_TimeGpencilModifier; case eGpencilModifierType_Color: return &RNA_ColorGpencilModifier; - case eGpencilModifierType_Instance: - return &RNA_InstanceGpencilModifier; + case eGpencilModifierType_Array: + return &RNA_ArrayGpencilModifier; case eGpencilModifierType_Build: return &RNA_BuildGpencilModifier; case eGpencilModifierType_Opacity: @@ -1012,9 +1005,9 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "InstanceGpencilModifier", "GpencilModifier"); + srna = RNA_def_struct(brna, "ArrayGpencilModifier", "GpencilModifier"); RNA_def_struct_ui_text(srna, "Instance Modifier", "Create grid of duplicate instances"); - RNA_def_struct_sdna(srna, "InstanceGpencilModifierData"); + RNA_def_struct_sdna(srna, "ArrayGpencilModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY); prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE); @@ -1028,13 +1021,21 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pass", "Pass index"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "count", PROP_INT, PROP_XYZ); + prop = RNA_def_property(srna, "count", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 1, INT_MAX); - RNA_def_property_ui_range(prop, 1, 20, 1, -1); + RNA_def_property_ui_range(prop, 1, 50, 1, -1); RNA_def_property_ui_text(prop, "Count", "Number of items"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); /* Offset parameters */ + prop = RNA_def_property(srna, "offset_object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "object"); + RNA_def_property_ui_text(prop, "Object Offset", + "Use the location and rotation of another object to determine the distance and " + "rotational change between arrayed items"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Offset", "Value for the distance between items"); @@ -1047,13 +1048,6 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "lock_axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "lock_axis"); - RNA_def_property_enum_items(prop, rna_enum_gpencil_lockshift_items); - //RNA_def_property_flag(prop, PROP_ENUM_FLAG); - RNA_def_property_ui_text(prop, "Axis", ""); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rot"); RNA_def_property_ui_text(prop, "Rotation", "Value for changes in rotation"); @@ -1067,7 +1061,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "random_rot", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_RANDOM_ROT); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_RANDOM_ROT); RNA_def_property_ui_text(prop, "Random Rotation", "Use random factors for rotation"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -1078,7 +1072,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "random_scale", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_RANDOM_SIZE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_RANDOM_SIZE); RNA_def_property_ui_text(prop, "Random Scale", "Use random factors for scale"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -1095,12 +1089,12 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) 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_INSTANCE_INVERT_LAYER); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_LAYER); RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_INVERT_PASS); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_PASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); @@ -1111,12 +1105,12 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_INVERT_LAYERPASS); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_LAYERPASS); RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "keep_on_top", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_KEEP_ONTOP); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_KEEP_ONTOP); RNA_def_property_ui_text(prop, "Keep On Top", "Keep the original stroke in front of new instances (only affect by layer)"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); -- cgit v1.2.3