diff options
23 files changed, 851 insertions, 84 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index df6dd6eab92..4b9671c7881 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -234,8 +234,12 @@ bool BKE_gpencil_stroke_sample(struct bGPdata *gpd, * \param gps: Stroke to smooth * \param i: Point index * \param inf: Amount of smoothing to apply + * \param smooth_caps: Apply smooth to stroke extremes */ -bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, int i, float inf); +bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, + int i, + float inf, + const bool smooth_caps); /** * Apply smooth strength to stroke point. * \param gps: Stroke to smooth diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index e7917ffa578..d850dea0c30 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -407,16 +407,8 @@ void BKE_gpencil_set_lineart_modifier_limits(struct GpencilModifierData *md, bool BKE_gpencil_is_first_lineart_in_stack(const struct Object *ob, const struct GpencilModifierData *md); -/** - * Init grease pencil lattice deform data. - * \param ob: Grease pencil object. - */ -void BKE_gpencil_lattice_init(struct Object *ob); -/** - * Clear grease pencil lattice deform data. - * \param ob: Grease pencil object. - */ -void BKE_gpencil_lattice_clear(struct Object *ob); +void BKE_gpencil_cache_data_init(struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_cache_data_clear(struct Object *ob); /** * Calculate grease-pencil modifiers. diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 6ab14628c29..088b270bfed 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -48,6 +48,7 @@ struct Mesh; struct ModifierEvalContext; struct Object; struct ShrinkwrapModifierData; +struct ShrinkwrapGpencilModifierData; struct SpaceTransform; /* Information about boundary edges in the mesh. */ @@ -123,6 +124,13 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, const int defgrp_index, float (*vertexCos)[3], int numVerts); +/* Implementation of the Shrinkwrap Grease Pencil modifier. */ +void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd, + struct Object *ob, + struct MDeformVert *dvert, + const int defgrp_index, + float (*vertexCos)[3], + int numVerts); /** * Used in `editmesh_mask_extract.c` to shrink-wrap the extracted mesh to the sculpt. diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc index aca85984989..84a9735ac5c 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.cc +++ b/source/blender/blenkernel/intern/gpencil_geom.cc @@ -912,7 +912,10 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo return true; } -bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf) +/** + * Apply smooth position to stroke point. + */ +bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf, const bool smooth_caps) { bGPDspoint *pt = &gps->points[i]; float sco[3] = {0.0f}; @@ -926,7 +929,7 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf) /* Only affect endpoints by a fraction of the normal strength, * to prevent the stroke from shrinking too much */ - if (!is_cyclic && ELEM(i, 0, gps->totpoints - 1)) { + if ((!smooth_caps) && (!is_cyclic && ELEM(i, 0, gps->totpoints - 1))) { inf *= 0.1f; } @@ -3333,7 +3336,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, for (i = start; i < end; i++) { pt = &gps_a->points[i]; pt->pressure += (avg_pressure - pt->pressure) * ratio; - BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f); + BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f, false); ratio += step; /* In the center, reverse the ratio. */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index fb6dbc5402d..f3bd17d5ef7 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -36,6 +36,7 @@ #include "DNA_armature_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -50,7 +51,9 @@ #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_shrinkwrap.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -76,36 +79,84 @@ static GpencilVirtualModifierData virtualModifierCommonData; * each loop over all the geometry being evaluated. */ -void BKE_gpencil_lattice_init(Object *ob) +/** + * Init grease pencil cache deform data. + * \param ob: Grease pencil object + */ +void BKE_gpencil_cache_data_init(Depsgraph *depsgraph, Object *ob) { LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { - if (md->type == eGpencilModifierType_Lattice) { - LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; - Object *latob = NULL; + switch (md->type) { + case eGpencilModifierType_Lattice: { + LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; + Object *latob = NULL; + + latob = mmd->object; + if ((!latob) || (latob->type != OB_LATTICE)) { + return; + } + if (mmd->cache_data) { + BKE_lattice_deform_data_destroy(mmd->cache_data); + } - latob = mmd->object; - if ((!latob) || (latob->type != OB_LATTICE)) { - return; + /* init deform data */ + mmd->cache_data = BKE_lattice_deform_data_create(latob, ob); + break; } - if (mmd->cache_data) { - BKE_lattice_deform_data_destroy(mmd->cache_data); + case eGpencilModifierType_Shrinkwrap: { + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + ob = mmd->target; + if (!ob) { + return; + } + if (mmd->cache_data) { + BKE_shrinkwrap_free_tree(mmd->cache_data); + MEM_SAFE_FREE(mmd->cache_data); + } + Object *ob_target = DEG_get_evaluated_object(depsgraph, ob); + Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); + mmd->cache_data = MEM_callocN(sizeof(ShrinkwrapTreeData), __func__); + if (BKE_shrinkwrap_init_tree( + mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false)) { + } + else { + MEM_SAFE_FREE(mmd->cache_data); + } + break; } - /* init deform data */ - mmd->cache_data = BKE_lattice_deform_data_create(latob, ob); + default: + break; } } } -void BKE_gpencil_lattice_clear(Object *ob) +/** + * Clear grease pencil cache deform data. + * \param ob: Grease pencil object + */ +void BKE_gpencil_cache_data_clear(Object *ob) { LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { - if (md->type == eGpencilModifierType_Lattice) { - LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; - if ((mmd) && (mmd->cache_data)) { - BKE_lattice_deform_data_destroy(mmd->cache_data); - mmd->cache_data = NULL; + switch (md->type) { + case eGpencilModifierType_Lattice: { + LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; + if ((mmd) && (mmd->cache_data)) { + BKE_lattice_deform_data_destroy(mmd->cache_data); + mmd->cache_data = NULL; + } + break; } + case eGpencilModifierType_Shrinkwrap: { + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + if ((mmd) && (mmd->cache_data)) { + BKE_shrinkwrap_free_tree(mmd->cache_data); + MEM_SAFE_FREE(mmd->cache_data); + } + break; + } + default: + break; } } } @@ -699,7 +750,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) } /* Init general modifiers data. */ - BKE_gpencil_lattice_init(ob); + BKE_gpencil_cache_data_init(depsgraph, ob); const bool time_remap = BKE_gpencil_has_time_modifiers(ob); bool is_first_lineart = true; @@ -742,8 +793,8 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) } } - /* Clear any lattice data. */ - BKE_gpencil_lattice_clear(ob); + /* Clear any cache data. */ + BKE_gpencil_cache_data_clear(ob); MOD_lineart_clear_cache(&gpd->runtime.lineart_cache); } @@ -901,6 +952,10 @@ void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb) gpmd->segments[i].dmd = gpmd; } } + if (md->type == eGpencilModifierType_Shrinkwrap) { + ShrinkwrapGpencilModifierData *gpmd = (ShrinkwrapGpencilModifierData *)md; + gpmd->cache_data = NULL; + } } } diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 00a80d6e74f..7618323f488 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -28,6 +28,7 @@ #include <string.h> #include <time.h> +#include "DNA_gpencil_modifier_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -1483,6 +1484,55 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, } } +void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd, + Object *ob, + MDeformVert *dvert, + const int defgrp_index, + float (*vertexCos)[3], + int numVerts) +{ + + ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; + /* Convert gpencil struct to use the same struct and function used with meshes. */ + ShrinkwrapModifierData smd; + smd.target = mmd->target; + smd.auxTarget = mmd->aux_target; + smd.keepDist = mmd->keep_dist; + smd.shrinkType = mmd->shrink_type; + smd.shrinkOpts = mmd->shrink_opts; + smd.shrinkMode = mmd->shrink_mode; + smd.projLimit = mmd->proj_limit; + smd.projAxis = mmd->proj_axis; + + /* Configure Shrinkwrap calc data. */ + calc.smd = &smd; + calc.ob = ob; + calc.numVerts = numVerts; + calc.vertexCos = vertexCos; + calc.dvert = dvert; + calc.vgroup = defgrp_index; + calc.invert_vgroup = (mmd->flag & GP_SHRINKWRAP_INVERT_VGROUP) != 0; + + BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, mmd->target); + calc.keepDist = mmd->keep_dist; + calc.tree = mmd->cache_data; + + switch (mmd->shrink_type) { + case MOD_SHRINKWRAP_NEAREST_SURFACE: + case MOD_SHRINKWRAP_TARGET_PROJECT: + TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), gpdeform_surface); + break; + + case MOD_SHRINKWRAP_PROJECT: + TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), gpdeform_project); + break; + + case MOD_SHRINKWRAP_NEAREST_VERTEX: + TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), gpdeform_vertex); + break; + } +} + void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C, Object *ob_source, Object *ob_target) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 7dad83e305f..836d6bf90fe 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3949,7 +3949,7 @@ static void gpencil_smooth_stroke(bContext *C, wmOperator *op) /* perform smoothing */ if (smooth_position) { - BKE_gpencil_stroke_smooth_point(gps, i, factor); + BKE_gpencil_stroke_smooth_point(gps, i, factor, false); } if (smooth_strength) { BKE_gpencil_stroke_smooth_strength(gps, i, factor); diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 90cf64b58d8..c3af28d4382 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1570,7 +1570,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) float smoothfac = 1.0f; for (int r = 0; r < 1; r++) { for (int i = 0; i < gps->totpoints; i++) { - BKE_gpencil_stroke_smooth_point(gps, i, smoothfac - reduce); + BKE_gpencil_stroke_smooth_point(gps, i, smoothfac - reduce, false); } reduce += 0.25f; /* reduce the factor */ } diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 22127d7ac3b..2023ae5fe27 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -336,7 +336,7 @@ static void gpencil_interpolate_smooth_stroke(bGPDstroke *gps, float reduce = 0.0f; for (int r = 0; r < smooth_steps; r++) { for (int i = 0; i < gps->totpoints - 1; i++) { - BKE_gpencil_stroke_smooth_point(gps, i, smooth_factor - reduce); + BKE_gpencil_stroke_smooth_point(gps, i, smooth_factor - reduce, false); BKE_gpencil_stroke_smooth_strength(gps, i, smooth_factor); } reduce += 0.25f; /* reduce the factor */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 018334a851e..dabe2050b28 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1205,7 +1205,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) for (int r = 0; r < brush->gpencil_settings->draw_smoothlvl; r++) { for (i = 0; i < gps->totpoints - 1; i++) { BKE_gpencil_stroke_smooth_point( - gps, i, brush->gpencil_settings->draw_smoothfac - reduce); + gps, i, brush->gpencil_settings->draw_smoothfac - reduce, false); BKE_gpencil_stroke_smooth_strength(gps, i, brush->gpencil_settings->draw_smoothfac); } reduce += 0.25f; /* reduce the factor */ @@ -1217,7 +1217,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) float ifac = (float)brush->gpencil_settings->input_samples / 10.0f; float sfac = interpf(1.0f, 0.2f, ifac); for (i = 0; i < gps->totpoints - 1; i++) { - BKE_gpencil_stroke_smooth_point(gps, i, sfac); + BKE_gpencil_stroke_smooth_point(gps, i, sfac, false); BKE_gpencil_stroke_smooth_strength(gps, i, sfac); } } diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 32ad8c98950..186c45c9f39 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -337,7 +337,7 @@ static bool gpencil_brush_smooth_apply(tGP_BrushEditData *gso, /* perform smoothing */ if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_POSITION) { - BKE_gpencil_stroke_smooth_point(gps, pt_index, inf); + BKE_gpencil_stroke_smooth_point(gps, pt_index, inf, false); } if (gso->brush->gpencil_settings->sculpt_mode_flag & GP_SCULPT_FLAGMODE_APPLY_STRENGTH) { BKE_gpencil_stroke_smooth_strength(gps, pt_index, inf); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index c339f07fd58..a586f268128 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2368,6 +2368,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case eGpencilModifierType_WeightAngle: data.icon = ICON_MOD_VERTEX_WEIGHT; break; + case eGpencilModifierType_Shrinkwrap: + data.icon = ICON_MOD_SHRINKWRAP; + break; /* Default */ default: diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index afcd551d0af..5ee75619259 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC intern/MOD_gpencilnoise.c intern/MOD_gpenciloffset.c intern/MOD_gpencilopacity.c + intern/MOD_gpencilshrinkwrap.c intern/MOD_gpencilsimplify.c intern/MOD_gpencilsmooth.c intern/MOD_gpencilsubdiv.c diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index d9285f44a37..56cee115760 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -48,6 +48,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_WeightProximity; extern GpencilModifierTypeInfo modifierType_Gpencil_WeightAngle; extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart; extern GpencilModifierTypeInfo modifierType_Gpencil_Dash; +extern GpencilModifierTypeInfo modifierType_Gpencil_Shrinkwrap; /* MOD_gpencil_util.c */ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index d3088c68af5..f6a85919de4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -67,6 +67,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(WeightProximity); INIT_GP_TYPE(Lineart); INIT_GP_TYPE(Dash); + INIT_GP_TYPE(Shrinkwrap); #undef INIT_GP_TYPE } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c new file mode 100644 index 00000000000..6990b41e6ce --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilshrinkwrap.c @@ -0,0 +1,350 @@ +/* + * 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 + */ + +/** \file + * \ingroup modifiers + */ + +#include <stdio.h> +#include <string.h> /* For #MEMCPY_STRUCT_AFTER. */ + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "DNA_defaults.h" +#include "DNA_gpencil_modifier_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BKE_context.h" +#include "BKE_deform.h" +#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_shrinkwrap.h" + +#include "MEM_guardedalloc.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "RNA_access.h" + +#include "MOD_gpencil_modifiertypes.h" +#include "MOD_gpencil_ui_common.h" +#include "MOD_gpencil_util.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +static void initData(GpencilModifierData *md) +{ + ShrinkwrapGpencilModifierData *gpmd = (ShrinkwrapGpencilModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier)); + + MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(ShrinkwrapGpencilModifierData), modifier); +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copydata_generic(md, target); +} + +static void deformStroke(GpencilModifierData *md, + Depsgraph *UNUSED(depsgraph), + Object *ob, + bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps) +{ + bGPdata *gpd = ob->data; + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); + + if (!is_stroke_affected_by_modifier(ob, + mmd->layername, + mmd->material, + mmd->pass_index, + mmd->layer_pass, + 1, + gpl, + gps, + mmd->flag & GP_SHRINKWRAP_INVERT_LAYER, + mmd->flag & GP_SHRINKWRAP_INVERT_PASS, + mmd->flag & GP_SHRINKWRAP_INVERT_LAYERPASS, + mmd->flag & GP_SHRINKWRAP_INVERT_MATERIAL)) { + return; + } + + if ((mmd->cache_data == NULL) || (mmd->target == ob) || (mmd->aux_target == ob)) { + return; + } + + bGPDspoint *pt = gps->points; + float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * gps->totpoints, __func__); + int i; + /* Prepare array of points. */ + for (i = 0; i < gps->totpoints; i++, pt++) { + copy_v3_v3(vert_coords[i], &pt->x); + } + + shrinkwrapGpencilModifier_deform(mmd, ob, gps->dvert, def_nr, vert_coords, gps->totpoints); + + /* Apply deformed coordinates. */ + pt = gps->points; + for (i = 0; i < gps->totpoints; i++, pt++) { + copy_v3_v3(&pt->x, vert_coords[i]); + /* Smooth stroke. */ + if (mmd->smooth_factor > 0.0f) { + for (int r = 0; r < mmd->smooth_step; r++) { + BKE_gpencil_stroke_smooth_point(gps, i, mmd->smooth_factor, true); + } + } + } + + MEM_freeN(vert_coords); + + /* Calc geometry data. */ + BKE_gpencil_stroke_geometry_update(gpd, gps); +} + +static void bakeModifier(Main *UNUSED(bmain), + Depsgraph *depsgraph, + GpencilModifierData *md, + Object *ob) +{ + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + Scene *scene = DEG_get_evaluated_scene(depsgraph); + bGPdata *gpd = ob->data; + int oldframe = (int)DEG_get_ctime(depsgraph); + + if ((mmd->target == ob) || (mmd->aux_target == ob)) { + return; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + /* Apply shrinkwrap effects on this frame. */ + CFRA = gpf->framenum; + BKE_scene_graph_update_for_newframe(depsgraph); + + /* Recalculate shrinkwrap data. */ + if (mmd->cache_data) { + BKE_shrinkwrap_free_tree(mmd->cache_data); + MEM_SAFE_FREE(mmd->cache_data); + } + Object *ob_target = DEG_get_evaluated_object(depsgraph, mmd->target); + Mesh *target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); + mmd->cache_data = MEM_callocN(sizeof(ShrinkwrapTreeData), __func__); + if (BKE_shrinkwrap_init_tree( + mmd->cache_data, target, mmd->shrink_type, mmd->shrink_mode, false)) { + + /* Compute shrinkwrap effects on this frame. */ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + deformStroke(md, depsgraph, ob, gpl, gpf, gps); + } + } + /* Free data. */ + if (mmd->cache_data) { + BKE_shrinkwrap_free_tree(mmd->cache_data); + MEM_SAFE_FREE(mmd->cache_data); + } + } + } + + /* Return frame state and DB to original state. */ + CFRA = oldframe; + BKE_scene_graph_update_for_newframe(depsgraph); +} + +static void freeData(GpencilModifierData *md) +{ + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + if (mmd->cache_data) { + BKE_shrinkwrap_free_tree(mmd->cache_data); + MEM_SAFE_FREE(mmd->cache_data); + } +} + +static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams)) +{ + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + + /* The object type check is only needed here in case we have a placeholder + * object assigned (because the library containing the mesh is missing). + * + * In other cases it should be impossible to have a type mismatch. + */ + if (!mmd->target || mmd->target->type != OB_MESH) { + return true; + } + if (mmd->aux_target && mmd->aux_target->type != OB_MESH) { + return true; + } + return false; +} + +static void updateDepsgraph(GpencilModifierData *md, + const ModifierUpdateDepsgraphContext *ctx, + const int UNUSED(mode)) +{ + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + CustomData_MeshMasks mask = {0}; + + if (BKE_shrinkwrap_needs_normals(mmd->shrink_type, mmd->shrink_mode)) { + mask.vmask |= CD_MASK_NORMAL; + mask.lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; + } + + if (mmd->target != NULL) { + DEG_add_object_relation(ctx->node, mmd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier"); + DEG_add_object_relation(ctx->node, mmd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier"); + DEG_add_customdata_mask(ctx->node, mmd->target, &mask); + if (mmd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) { + DEG_add_special_eval_flag(ctx->node, &mmd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY); + } + } + if (mmd->aux_target != NULL) { + DEG_add_object_relation( + ctx->node, mmd->aux_target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier"); + DEG_add_object_relation( + ctx->node, mmd->aux_target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier"); + DEG_add_customdata_mask(ctx->node, mmd->aux_target, &mask); + if (mmd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) { + DEG_add_special_eval_flag( + ctx->node, &mmd->aux_target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY); + } + } + DEG_add_modifier_to_transform_relation(ctx->node, "Shrinkwrap Modifier"); +} + +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ShrinkwrapGpencilModifierData *mmd = (ShrinkwrapGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->target, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&mmd->aux_target, IDWALK_CB_NOP); + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *row, *col; + uiLayout *layout = panel->layout; + int toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE; + + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiLayoutSetPropSep(layout, true); + + int wrap_method = RNA_enum_get(ptr, "wrap_method"); + + uiItemR(layout, ptr, "wrap_method", 0, NULL, ICON_NONE); + + if (ELEM(wrap_method, + MOD_SHRINKWRAP_PROJECT, + MOD_SHRINKWRAP_NEAREST_SURFACE, + MOD_SHRINKWRAP_TARGET_PROJECT)) { + uiItemR(layout, ptr, "wrap_mode", 0, NULL, ICON_NONE); + } + + if (wrap_method == MOD_SHRINKWRAP_PROJECT) { + uiItemR(layout, ptr, "project_limit", 0, IFACE_("Limit"), ICON_NONE); + uiItemR(layout, ptr, "subsurf_levels", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, false); + row = uiLayoutRowWithHeading(col, true, IFACE_("Axis")); + uiItemR(row, ptr, "use_project_x", toggles_flag, NULL, ICON_NONE); + uiItemR(row, ptr, "use_project_y", toggles_flag, NULL, ICON_NONE); + uiItemR(row, ptr, "use_project_z", toggles_flag, NULL, ICON_NONE); + + uiItemR(col, ptr, "use_negative_direction", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_positive_direction", 0, NULL, ICON_NONE); + + uiItemR(layout, ptr, "cull_face", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + col = uiLayoutColumn(layout, false); + uiLayoutSetActive(col, + RNA_boolean_get(ptr, "use_negative_direction") && + RNA_enum_get(ptr, "cull_face") != 0); + uiItemR(col, ptr, "use_invert_cull", 0, NULL, ICON_NONE); + } + + uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE); + if (wrap_method == MOD_SHRINKWRAP_PROJECT) { + uiItemR(layout, ptr, "auxiliary_target", 0, NULL, ICON_NONE); + } + uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); + + uiLayoutSetPropSep(layout, true); + + uiItemR(layout, ptr, "smooth_factor", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "smooth_step", 0, IFACE_("Repeat"), ICON_NONE); + + gpencil_modifier_panel_end(layout, ptr); +} + +static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + gpencil_modifier_masking_panel_draw(panel, true, true); +} + +static void panelRegister(ARegionType *region_type) +{ + PanelType *panel_type = gpencil_modifier_panel_register( + region_type, eGpencilModifierType_Shrinkwrap, panel_draw); + gpencil_modifier_subpanel_register( + region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); +} + +GpencilModifierTypeInfo modifierType_Gpencil_Shrinkwrap = { + /* name */ "Shrinkwrap", + /* structName */ "ShrinkwrapGpencilModifierData", + /* structSize */ sizeof(ShrinkwrapGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ eGpencilModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + + /* deformStroke */ deformStroke, + /* generateStrokes */ NULL, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, + /* panelRegister */ panelRegister, +}; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index b00db1ba2d2..a63cbb53645 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -132,7 +132,7 @@ static void deformStroke(GpencilModifierData *md, const float val = mmd->factor * weight; /* perform smoothing */ if (mmd->flag & GP_SMOOTH_MOD_LOCATION) { - BKE_gpencil_stroke_smooth_point(gps, i, val); + BKE_gpencil_stroke_smooth_point(gps, i, val, false); } if (mmd->flag & GP_SMOOTH_MOD_STRENGTH) { BKE_gpencil_stroke_smooth_strength(gps, i, val); diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index 1ad884bee8f..e0947085694 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -353,5 +353,26 @@ .mat_nr = -1, \ } +#define _DNA_DEFAULT_ShrinkwrapGpencilModifierData \ + { \ + .target = NULL, \ + .aux_target = NULL, \ + .keep_dist = 0.05f, \ + .shrink_type = MOD_SHRINKWRAP_NEAREST_SURFACE, \ + .shrink_opts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR, \ + .shrink_mode = 0, \ + .proj_limit = 0.0f, \ + .proj_axis = 0, \ + .subsurf_levels = 0, \ + .material = NULL, \ + .layername = "", \ + .vgname = "", \ + .pass_index = 0, \ + .flag = 0, \ + .layer_pass = 0, \ + .smooth_factor = 0.05f, \ + .smooth_step = 1, \ + } + /* clang-format off */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 339714da255..f7964e1f2fa 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -28,6 +28,7 @@ extern "C" { #endif struct LatticeDeformData; +struct ShrinkwrapTreeData; /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! * (ONLY ADD NEW ITEMS AT THE END) @@ -58,6 +59,7 @@ typedef enum GpencilModifierType { eGpencilModifierType_WeightProximity = 21, eGpencilModifierType_Dash = 22, eGpencilModifierType_WeightAngle = 23, + eGpencilModifierType_Shrinkwrap = 24, /* Keep last. */ NUM_GREASEPENCIL_MODIFIER_TYPES, } GpencilModifierType; @@ -728,7 +730,7 @@ typedef struct SmoothGpencilModifierData { int pass_index; /** Several flags. */ int flag; - /** Factor of noise. */ + /** Factor of smooth. */ float factor; /** How many times apply smooth. */ int step; @@ -1073,6 +1075,60 @@ typedef struct LineartGpencilModifierData { } LineartGpencilModifierData; +typedef struct ShrinkwrapGpencilModifierData { + GpencilModifierData modifier; + /** Shrink target. */ + struct Object *target; + /** Additional shrink target. */ + struct Object *aux_target; + /** Material for filtering. */ + struct Material *material; + /** Layer name. */ + char layername[64]; + /** Optional vertexgroup filter name, MAX_VGROUP_NAME. */ + char vgname[64]; + /** Custom index for passes. */ + int pass_index; + /** Flags. */ + int flag; + /** Custom index for passes. */ + int layer_pass; + /** Distance offset to keep from mesh/projection point. */ + float keep_dist; + /** Shrink type projection. */ + short shrink_type; + /** Shrink options. */ + char shrink_opts; + /** Shrink to surface mode. */ + char shrink_mode; + /** Limit the projection ray cast. */ + float proj_limit; + /** Axis to project over. */ + char proj_axis; + + /** If using projection over vertex normal this controls the level of subsurface that must be + * done before getting the vertex coordinates and normal + */ + char subsurf_levels; + char _pad[6]; + /** Factor of smooth. */ + float smooth_factor; + /** How many times apply smooth. */ + int smooth_step; + + /** Runtime only. */ + struct ShrinkwrapTreeData *cache_data; +} ShrinkwrapGpencilModifierData; + +typedef enum eShrinkwrapGpencil_Flag { + GP_SHRINKWRAP_INVERT_LAYER = (1 << 0), + GP_SHRINKWRAP_INVERT_PASS = (1 << 1), + GP_SHRINKWRAP_INVERT_LAYERPASS = (1 << 3), + GP_SHRINKWRAP_INVERT_MATERIAL = (1 << 4), + /* Keep next bit as is to be equals to mesh modifier flag to reuse functions. */ + GP_SHRINKWRAP_INVERT_VGROUP = (1 << 6), +} eShrinkwrapGpencil_Flag; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index 59f30f7b2e3..6c8b4d0acb1 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -324,6 +324,7 @@ SDNA_DEFAULT_DECL_STRUCT(LineartGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(LengthGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierSegment); +SDNA_DEFAULT_DECL_STRUCT(ShrinkwrapGpencilModifierData); #undef SDNA_DEFAULT_DECL_STRUCT @@ -555,6 +556,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL(LengthGpencilModifierData), SDNA_DEFAULT_DECL(DashGpencilModifierData), SDNA_DEFAULT_DECL(DashGpencilModifierSegment), + SDNA_DEFAULT_DECL(ShrinkwrapGpencilModifierData) }; #undef SDNA_DEFAULT_DECL #undef SDNA_DEFAULT_DECL_EX diff --git a/source/blender/makesrna/RNA_enum_items.h b/source/blender/makesrna/RNA_enum_items.h index e9b7532584b..531af92c544 100644 --- a/source/blender/makesrna/RNA_enum_items.h +++ b/source/blender/makesrna/RNA_enum_items.h @@ -61,6 +61,8 @@ DEF_ENUM(rna_enum_object_shaderfx_type_items) DEF_ENUM(rna_enum_modifier_triangulate_quad_method_items) DEF_ENUM(rna_enum_modifier_triangulate_ngon_method_items) DEF_ENUM(rna_enum_modifier_shrinkwrap_mode_items) +DEF_ENUM(rna_enum_shrinkwrap_type_items) +DEF_ENUM(rna_enum_shrinkwrap_face_cull_items) DEF_ENUM(rna_enum_image_type_items) DEF_ENUM(rna_enum_image_color_mode_items) diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 82f3279146a..72401b460be 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -28,6 +28,7 @@ #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -144,6 +145,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { ICON_MOD_OFFSET, "Offset", "Change stroke location, rotation or scale"}, + {eGpencilModifierType_Shrinkwrap, + "SHRINKWRAP", + ICON_MOD_SHRINKWRAP, + "Shrinkwrap", + "Project the shape onto another object"}, {eGpencilModifierType_Smooth, "GP_SMOOTH", ICON_MOD_SMOOTH, "Smooth", "Smooth stroke"}, {eGpencilModifierType_Thick, "GP_THICK", @@ -269,6 +275,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_LengthGpencilModifier; case eGpencilModifierType_Mirror: return &RNA_MirrorGpencilModifier; + case eGpencilModifierType_Shrinkwrap: + return &RNA_ShrinkwrapGpencilModifier; case eGpencilModifierType_Smooth: return &RNA_SmoothGpencilModifier; case eGpencilModifierType_Hook: @@ -360,6 +368,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(WeightProx, vgname); RNA_GP_MOD_VGROUP_NAME_SET(WeightAngle, target_vgname); RNA_GP_MOD_VGROUP_NAME_SET(WeightAngle, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Shrinkwrap, vgname); # undef RNA_GP_MOD_VGROUP_NAME_SET @@ -392,6 +401,8 @@ RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE); RNA_GP_MOD_OBJECT_SET(Lattice, object, OB_LATTICE); RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY); RNA_GP_MOD_OBJECT_SET(WeightProx, object, OB_EMPTY); +RNA_GP_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH); +RNA_GP_MOD_OBJECT_SET(Shrinkwrap, aux_target, OB_MESH); # undef RNA_GP_MOD_OBJECT_SET @@ -685,6 +696,16 @@ static void rna_TextureGpencilModifier_material_set(PointerRNA *ptr, rna_GpencilModifier_material_set(ptr, value, ma_target, reports); } +static void rna_ShrinkwrapGpencilModifier_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *reports) +{ + ShrinkwrapGpencilModifierData *tmd = (ShrinkwrapGpencilModifierData *)ptr->data; + Material **ma_target = &tmd->material; + + rna_GpencilModifier_material_set(ptr, value, ma_target, reports); +} + static void rna_Lineart_start_level_set(PointerRNA *ptr, int value) { LineartGpencilModifierData *lmd = (LineartGpencilModifierData *)ptr->data; @@ -756,6 +777,18 @@ static void rna_DashGpencilModifierSegment_name_set(PointerRNA *ptr, const char BKE_animdata_fix_paths_rename_all(NULL, prefix, oldname, ds->name); } +static int rna_ShrinkwrapGpencilModifier_face_cull_get(PointerRNA *ptr) +{ + ShrinkwrapGpencilModifierData *swm = (ShrinkwrapGpencilModifierData *)ptr->data; + return swm->shrink_opts & MOD_SHRINKWRAP_CULL_TARGET_MASK; +} + +static void rna_ShrinkwrapGpencilModifier_face_cull_set(struct PointerRNA *ptr, int value) +{ + ShrinkwrapGpencilModifierData *swm = (ShrinkwrapGpencilModifierData *)ptr->data; + swm->shrink_opts = (swm->shrink_opts & ~MOD_SHRINKWRAP_CULL_TARGET_MASK) | value; +} + #else static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) @@ -3683,6 +3716,194 @@ static void rna_def_modifier_gpencildash(BlenderRNA *brna) RNA_define_lib_overridable(false); } +static void rna_def_modifier_gpencilshrinkwrap(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ShrinkwrapGpencilModifier", "GpencilModifier"); + RNA_def_struct_ui_text(srna, + "Shrinkwrap Modifier", + "Shrink wrapping modifier to shrink wrap and object to a target"); + RNA_def_struct_sdna(srna, "ShrinkwrapGpencilModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_SHRINKWRAP); + + RNA_define_lib_overridable(true); + + prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "shrink_type"); + RNA_def_property_enum_items(prop, rna_enum_shrinkwrap_type_items); + RNA_def_property_ui_text(prop, "Wrap Method", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + prop = RNA_def_property(srna, "wrap_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "shrink_mode"); + RNA_def_property_enum_items(prop, rna_enum_modifier_shrinkwrap_mode_items); + RNA_def_property_ui_text( + prop, "Snap Mode", "Select how vertices are constrained to the target surface"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + prop = RNA_def_property(srna, "cull_face", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "shrink_opts"); + RNA_def_property_enum_items(prop, rna_enum_shrinkwrap_face_cull_items); + RNA_def_property_enum_funcs(prop, + "rna_ShrinkwrapGpencilModifier_face_cull_get", + "rna_ShrinkwrapGpencilModifier_face_cull_set", + NULL); + RNA_def_property_ui_text( + prop, + "Face Cull", + "Stop vertices from projecting to a face on the target when facing towards/away"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Target", "Mesh target to shrink to"); + RNA_def_property_pointer_funcs( + prop, NULL, "rna_ShrinkwrapGpencilModifier_target_set", NULL, "rna_Mesh_object_poll"); + 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, "auxiliary_target", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "aux_target"); + RNA_def_property_ui_text(prop, "Auxiliary Target", "Additional mesh target to shrink to"); + RNA_def_property_pointer_funcs( + prop, NULL, "rna_ShrinkwrapGpencilModifier_aux_target_set", NULL, "rna_Mesh_object_poll"); + 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_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "keep_dist"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100, 100, 1, 2); + RNA_def_property_ui_text(prop, "Offset", "Distance to keep from the target"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "proj_limit"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text( + prop, "Project Limit", "Limit the distance used for projection (zero disables)"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS); + RNA_def_property_ui_text(prop, "X", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_project_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS); + RNA_def_property_ui_text(prop, "Y", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_project_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS); + RNA_def_property_ui_text(prop, "Z", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "subsurf_levels", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "subsurf_levels"); + RNA_def_property_range(prop, 0, 6); + RNA_def_property_ui_range(prop, 0, 6, 1, -1); + RNA_def_property_ui_text( + prop, + "Subdivision Levels", + "Number of subdivisions that must be performed before extracting vertices' " + "positions and normals"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_negative_direction", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shrink_opts", MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR); + RNA_def_property_ui_text( + prop, "Negative", "Allow vertices to move in the negative direction of axis"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_positive_direction", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shrink_opts", MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR); + RNA_def_property_ui_text( + prop, "Positive", "Allow vertices to move in the positive direction of axis"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_invert_cull", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shrink_opts", MOD_SHRINKWRAP_INVERT_CULL_TARGET); + RNA_def_property_ui_text( + prop, "Invert Cull", "When projecting in the negative direction invert the face cull mode"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "layername"); + RNA_def_property_ui_text(prop, "Layer", "Layer name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, + NULL, + "rna_ShrinkwrapGpencilModifier_material_set", + NULL, + "rna_GpencilModifier_material_poll"); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "vgname"); + RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ShrinkwrapGpencilModifier_vgname_set"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pass_index"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Pass index"); + 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_SHRINKWRAP_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_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SHRINKWRAP_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "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_SHRINKWRAP_INVERT_PASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SHRINKWRAP_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "layer_pass"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Layer pass index"); + 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_SHRINKWRAP_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, "smooth_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "smooth_factor"); + RNA_def_property_range(prop, 0, 1); + RNA_def_property_ui_text(prop, "Smooth Factor", "Amount of smoothing to apply"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "smooth_step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "smooth_step"); + RNA_def_property_range(prop, 1, 10); + RNA_def_property_ui_text( + prop, "Step", "Number of times to apply smooth (high numbers can reduce FPS)"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + RNA_define_lib_overridable(false); +} + void RNA_def_greasepencil_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -3772,6 +3993,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna) rna_def_modifier_gpencillineart(brna); rna_def_modifier_gpencillength(brna); rna_def_modifier_gpencildash(brna); + rna_def_modifier_gpencilshrinkwrap(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 9ad6771cda3..d46ae13b482 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -381,6 +381,42 @@ const EnumPropertyItem rna_enum_modifier_shrinkwrap_mode_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_shrinkwrap_type_items[] = { + {MOD_SHRINKWRAP_NEAREST_SURFACE, + "NEAREST_SURFACEPOINT", + 0, + "Nearest Surface Point", + "Shrink the mesh to the nearest target surface"}, + {MOD_SHRINKWRAP_PROJECT, + "PROJECT", + 0, + "Project", + "Shrink the mesh to the nearest target surface along a given axis"}, + {MOD_SHRINKWRAP_NEAREST_VERTEX, + "NEAREST_VERTEX", + 0, + "Nearest Vertex", + "Shrink the mesh to the nearest target vertex"}, + {MOD_SHRINKWRAP_TARGET_PROJECT, + "TARGET_PROJECT", + 0, + "Target Normal Project", + "Shrink the mesh to the nearest target surface " + "along the interpolated vertex normals of the target"}, + {0, NULL, 0, NULL, NULL}, +}; + +const EnumPropertyItem rna_enum_shrinkwrap_face_cull_items[] = { + {0, "OFF", 0, "Off", "No culling"}, + {MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, + "FRONT", + 0, + "Front", + "No projection when in front of the face"}, + {MOD_SHRINKWRAP_CULL_TARGET_BACKFACE, "BACK", 0, "Back", "No projection when behind the face"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifndef RNA_RUNTIME /* use eWarp_Falloff_*** & eHook_Falloff_***, they're in sync */ static const EnumPropertyItem modifier_warp_falloff_items[] = { @@ -4184,46 +4220,6 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static const EnumPropertyItem shrink_type_items[] = { - {MOD_SHRINKWRAP_NEAREST_SURFACE, - "NEAREST_SURFACEPOINT", - 0, - "Nearest Surface Point", - "Shrink the mesh to the nearest target surface"}, - {MOD_SHRINKWRAP_PROJECT, - "PROJECT", - 0, - "Project", - "Shrink the mesh to the nearest target surface along a given axis"}, - {MOD_SHRINKWRAP_NEAREST_VERTEX, - "NEAREST_VERTEX", - 0, - "Nearest Vertex", - "Shrink the mesh to the nearest target vertex"}, - {MOD_SHRINKWRAP_TARGET_PROJECT, - "TARGET_PROJECT", - 0, - "Target Normal Project", - "Shrink the mesh to the nearest target surface " - "along the interpolated vertex normals of the target"}, - {0, NULL, 0, NULL, NULL}, - }; - - static const EnumPropertyItem shrink_face_cull_items[] = { - {0, "OFF", 0, "Off", "No culling"}, - {MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, - "FRONT", - 0, - "Front", - "No projection when in front of the face"}, - {MOD_SHRINKWRAP_CULL_TARGET_BACKFACE, - "BACK", - 0, - "Back", - "No projection when behind the face"}, - {0, NULL, 0, NULL, NULL}, - }; - srna = RNA_def_struct(brna, "ShrinkwrapModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Shrinkwrap Modifier", @@ -4235,7 +4231,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shrinkType"); - RNA_def_property_enum_items(prop, shrink_type_items); + RNA_def_property_enum_items(prop, rna_enum_shrinkwrap_type_items); RNA_def_property_ui_text(prop, "Wrap Method", ""); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); @@ -4248,7 +4244,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) prop = RNA_def_property(srna, "cull_face", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shrinkOpts"); - RNA_def_property_enum_items(prop, shrink_face_cull_items); + RNA_def_property_enum_items(prop, rna_enum_shrinkwrap_face_cull_items); RNA_def_property_enum_funcs( prop, "rna_ShrinkwrapModifier_face_cull_get", "rna_ShrinkwrapModifier_face_cull_set", NULL); RNA_def_property_ui_text( |