GPv3: Shrinkwrap modifier
Port of shrinkwrap modifier from GPv2. Adds a new API function in `BKE_shrinkwrap.hh` for the modifier. Pull Request: https://projects.blender.org/blender/blender/pulls/119118
This commit is contained in:
@@ -205,6 +205,7 @@ class OBJECT_MT_modifier_add_deform(ModifierAddMenu, Menu):
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_LATTICE')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_NOISE')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_OFFSET')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_SHRINKWRAP')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_SMOOTH')
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_THICKNESS')
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
struct BVHTree;
|
||||
struct GreasePencilShrinkwrapModifierData;
|
||||
struct MDeformVert;
|
||||
struct Mesh;
|
||||
struct ModifierEvalContext;
|
||||
@@ -118,6 +119,39 @@ void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd,
|
||||
float (*vertexCos)[3],
|
||||
int numVerts);
|
||||
|
||||
struct ShrinkwrapParams {
|
||||
/** Shrink target. */
|
||||
Object *target = nullptr;
|
||||
/** Additional shrink target. */
|
||||
Object *aux_target = nullptr;
|
||||
/* Use inverse vertex group weights. */
|
||||
bool invert_vertex_weights = false;
|
||||
/** Distance offset to keep from mesh/projection point. */
|
||||
float keep_distance = 0.05f;
|
||||
/** Shrink type projection. */
|
||||
short shrink_type = 0 /*MOD_SHRINKWRAP_NEAREST_SURFACE*/;
|
||||
/** Shrink options. */
|
||||
char shrink_options = 0 /*MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR*/;
|
||||
/** Shrink to surface mode. */
|
||||
char shrink_mode = 0 /*MOD_SHRINKWRAP_ON_SURFACE*/;
|
||||
/** Limit the projection ray cast. */
|
||||
float projection_limit = 0.0f;
|
||||
/** Axis to project over. */
|
||||
char projection_axis = 0 /*MOD_SHRINKWRAP_PROJECT_OVER_NORMAL*/;
|
||||
/**
|
||||
* 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 = 0;
|
||||
};
|
||||
|
||||
void shrinkwrapParams_deform(const ShrinkwrapParams ¶ms,
|
||||
Object &object,
|
||||
ShrinkwrapTreeData &tree,
|
||||
blender::Span<MDeformVert> dvert,
|
||||
int defgrp_index,
|
||||
blender::MutableSpan<blender::float3> positions);
|
||||
|
||||
/**
|
||||
* Used in `editmesh_mask_extract.cc` to shrink-wrap the extracted mesh to the sculpt.
|
||||
*/
|
||||
|
||||
@@ -1358,6 +1358,48 @@ static void legacy_object_modifier_outline(Object &object, GpencilModifierData &
|
||||
false);
|
||||
}
|
||||
|
||||
static void legacy_object_modifier_shrinkwrap(Object &object, GpencilModifierData &legacy_md)
|
||||
{
|
||||
ModifierData &md = legacy_object_modifier_common(
|
||||
object, eModifierType_GreasePencilShrinkwrap, legacy_md);
|
||||
auto &md_shrinkwrap = reinterpret_cast<GreasePencilShrinkwrapModifierData &>(md);
|
||||
auto &legacy_md_shrinkwrap = reinterpret_cast<ShrinkwrapGpencilModifierData &>(legacy_md);
|
||||
|
||||
/* Shrinkwrap enums and flags do not have named types. */
|
||||
/* MOD_SHRINKWRAP_NEAREST_SURFACE etc. */
|
||||
md_shrinkwrap.shrink_type = legacy_md_shrinkwrap.shrink_type;
|
||||
/* MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR etc. */
|
||||
md_shrinkwrap.shrink_opts = legacy_md_shrinkwrap.shrink_opts;
|
||||
/* MOD_SHRINKWRAP_ON_SURFACE etc. */
|
||||
md_shrinkwrap.shrink_mode = legacy_md_shrinkwrap.shrink_mode;
|
||||
/* MOD_SHRINKWRAP_PROJECT_OVER_NORMAL etc. */
|
||||
md_shrinkwrap.proj_axis = legacy_md_shrinkwrap.proj_axis;
|
||||
|
||||
md_shrinkwrap.target = legacy_md_shrinkwrap.target;
|
||||
legacy_md_shrinkwrap.target = nullptr;
|
||||
md_shrinkwrap.aux_target = legacy_md_shrinkwrap.aux_target;
|
||||
legacy_md_shrinkwrap.aux_target = nullptr;
|
||||
md_shrinkwrap.keep_dist = legacy_md_shrinkwrap.keep_dist;
|
||||
md_shrinkwrap.proj_limit = legacy_md_shrinkwrap.proj_limit;
|
||||
md_shrinkwrap.subsurf_levels = legacy_md_shrinkwrap.subsurf_levels;
|
||||
md_shrinkwrap.smooth_factor = legacy_md_shrinkwrap.smooth_factor;
|
||||
md_shrinkwrap.smooth_step = legacy_md_shrinkwrap.smooth_step;
|
||||
|
||||
legacy_object_modifier_influence(md_shrinkwrap.influence,
|
||||
legacy_md_shrinkwrap.layername,
|
||||
legacy_md_shrinkwrap.layer_pass,
|
||||
legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYER,
|
||||
legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_LAYERPASS,
|
||||
&legacy_md_shrinkwrap.material,
|
||||
legacy_md_shrinkwrap.pass_index,
|
||||
legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_MATERIAL,
|
||||
legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_PASS,
|
||||
legacy_md_shrinkwrap.vgname,
|
||||
legacy_md_shrinkwrap.flag & GP_SHRINKWRAP_INVERT_VGROUP,
|
||||
nullptr,
|
||||
false);
|
||||
}
|
||||
|
||||
static void legacy_object_modifier_smooth(Object &object, GpencilModifierData &legacy_md)
|
||||
{
|
||||
ModifierData &md = legacy_object_modifier_common(
|
||||
@@ -1734,6 +1776,9 @@ static void legacy_object_modifiers(Main & /*bmain*/, Object &object)
|
||||
case eGpencilModifierType_Outline:
|
||||
legacy_object_modifier_outline(object, *gpd_md);
|
||||
break;
|
||||
case eGpencilModifierType_Shrinkwrap:
|
||||
legacy_object_modifier_shrinkwrap(object, *gpd_md);
|
||||
break;
|
||||
case eGpencilModifierType_Smooth:
|
||||
legacy_object_modifier_smooth(object, *gpd_md);
|
||||
break;
|
||||
@@ -1761,7 +1806,6 @@ static void legacy_object_modifiers(Main & /*bmain*/, Object &object)
|
||||
case eGpencilModifierType_Build:
|
||||
case eGpencilModifierType_Simplify:
|
||||
case eGpencilModifierType_Texture:
|
||||
case eGpencilModifierType_Shrinkwrap:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1518,6 +1518,56 @@ void shrinkwrapGpencilModifier_deform(ShrinkwrapGpencilModifierData *mmd,
|
||||
}
|
||||
}
|
||||
|
||||
void shrinkwrapParams_deform(const ShrinkwrapParams ¶ms,
|
||||
Object &object,
|
||||
ShrinkwrapTreeData &tree,
|
||||
const blender::Span<MDeformVert> dvert,
|
||||
const int defgrp_index,
|
||||
const blender::MutableSpan<blender::float3> positions)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
|
||||
ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData;
|
||||
/* Convert params struct to use the same struct and function used with meshes. */
|
||||
ShrinkwrapModifierData smd;
|
||||
smd.target = params.target;
|
||||
smd.auxTarget = params.aux_target;
|
||||
smd.keepDist = params.keep_distance;
|
||||
smd.shrinkType = params.shrink_type;
|
||||
smd.shrinkOpts = params.shrink_options;
|
||||
smd.shrinkMode = params.shrink_mode;
|
||||
smd.projLimit = params.projection_limit;
|
||||
smd.projAxis = params.projection_axis;
|
||||
|
||||
/* Configure Shrinkwrap calc data. */
|
||||
calc.smd = &smd;
|
||||
calc.ob = &object;
|
||||
calc.numVerts = int(positions.size());
|
||||
calc.vertexCos = reinterpret_cast<float(*)[3]>(positions.data());
|
||||
calc.dvert = dvert.is_empty() ? nullptr : dvert.data();
|
||||
calc.vgroup = defgrp_index;
|
||||
calc.invert_vgroup = params.invert_vertex_weights;
|
||||
|
||||
BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, &object, params.target);
|
||||
calc.keepDist = params.keep_distance;
|
||||
calc.tree = &tree;
|
||||
|
||||
switch (params.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(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob_source,
|
||||
|
||||
@@ -1030,4 +1030,19 @@
|
||||
.outline_material = NULL, \
|
||||
}
|
||||
|
||||
#define _DNA_DEFAULT_GreasePencilShrinkwrapModifierData \
|
||||
{ \
|
||||
.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 = MOD_SHRINKWRAP_ON_SURFACE, \
|
||||
.proj_limit = 0.0f, \
|
||||
.proj_axis = MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, \
|
||||
.subsurf_levels = 0, \
|
||||
.smooth_factor = 0.05f, \
|
||||
.smooth_step = 1, \
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
@@ -117,6 +117,7 @@ typedef enum ModifierType {
|
||||
eModifierType_GreasePencilTime = 80,
|
||||
eModifierType_GreasePencilEnvelope = 81,
|
||||
eModifierType_GreasePencilOutline = 82,
|
||||
eModifierType_GreasePencilShrinkwrap = 83,
|
||||
NUM_MODIFIER_TYPES,
|
||||
} ModifierType;
|
||||
|
||||
@@ -3273,3 +3274,39 @@ typedef struct GreasePencilOutlineModifierData {
|
||||
typedef enum GreasePencilOutlineModifierFlag {
|
||||
MOD_GREASE_PENCIL_OUTLINE_KEEP_SHAPE = (1 << 0),
|
||||
} GreasePencilOutlineModifierFlag;
|
||||
|
||||
typedef struct GreasePencilShrinkwrapModifierData {
|
||||
ModifierData modifier;
|
||||
GreasePencilModifierInfluenceData influence;
|
||||
|
||||
/** Shrink target. */
|
||||
struct Object *target;
|
||||
/** Additional shrink target. */
|
||||
struct Object *aux_target;
|
||||
/** 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[2];
|
||||
/** Factor of smooth. */
|
||||
float smooth_factor;
|
||||
/** How many times apply smooth. */
|
||||
int smooth_step;
|
||||
|
||||
/** Runtime only. */
|
||||
struct ShrinkwrapTreeData *cache_data;
|
||||
} GreasePencilShrinkwrapModifierData;
|
||||
|
||||
@@ -351,6 +351,7 @@ SDNA_DEFAULT_DECL_STRUCT(GreasePencilTimeModifierSegment);
|
||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilTimeModifierData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilEnvelopeModifierData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilOutlineModifierData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilShrinkwrapModifierData);
|
||||
|
||||
#undef SDNA_DEFAULT_DECL_STRUCT
|
||||
|
||||
@@ -621,6 +622,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
|
||||
SDNA_DEFAULT_DECL(GreasePencilTimeModifierData),
|
||||
SDNA_DEFAULT_DECL(GreasePencilEnvelopeModifierData),
|
||||
SDNA_DEFAULT_DECL(GreasePencilOutlineModifierData),
|
||||
SDNA_DEFAULT_DECL(GreasePencilShrinkwrapModifierData),
|
||||
};
|
||||
#undef SDNA_DEFAULT_DECL
|
||||
#undef SDNA_DEFAULT_DECL_EX
|
||||
|
||||
@@ -389,6 +389,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
|
||||
ICON_MOD_ARMATURE,
|
||||
"Armature",
|
||||
"Deform stroke points using armature object"},
|
||||
{eModifierType_GreasePencilShrinkwrap,
|
||||
"GREASE_PENCIL_SHRINKWRAP",
|
||||
ICON_MOD_SHRINKWRAP,
|
||||
"Shrinkwrap",
|
||||
"Project the shape onto another object"},
|
||||
|
||||
RNA_ENUM_ITEM_HEADING(N_("Physics"), nullptr),
|
||||
{eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""},
|
||||
@@ -1022,6 +1027,8 @@ RNA_MOD_OBJECT_SET(GreasePencilWeightProximity, object, OB_EMPTY);
|
||||
RNA_MOD_OBJECT_SET(GreasePencilHook, object, OB_EMPTY);
|
||||
RNA_MOD_OBJECT_SET(GreasePencilArmature, object, OB_ARMATURE);
|
||||
RNA_MOD_OBJECT_SET(GreasePencilOutline, object, OB_EMPTY);
|
||||
RNA_MOD_OBJECT_SET(GreasePencilShrinkwrap, target, OB_MESH);
|
||||
RNA_MOD_OBJECT_SET(GreasePencilShrinkwrap, aux_target, OB_MESH);
|
||||
|
||||
static void rna_HookModifier_object_set(PointerRNA *ptr,
|
||||
PointerRNA value,
|
||||
@@ -1961,6 +1968,7 @@ RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilWeightProximity);
|
||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilHook);
|
||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilEnvelope);
|
||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOutline);
|
||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilShrinkwrap);
|
||||
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOffset);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity);
|
||||
@@ -1974,6 +1982,7 @@ RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilWeightProximity);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilHook);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilArmature);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilEnvelope);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilShrinkwrap);
|
||||
|
||||
static void rna_GreasePencilLineartModifier_material_set(PointerRNA *ptr,
|
||||
PointerRNA value,
|
||||
@@ -2184,6 +2193,20 @@ static void rna_GreasePencilOutlineModifier_outline_material_set(PointerRNA *ptr
|
||||
rna_GreasePencilModifier_material_set(ptr, value, reports, &omd->outline_material);
|
||||
}
|
||||
|
||||
static int rna_GreasePencilShrinkwrapModifier_face_cull_get(PointerRNA *ptr)
|
||||
{
|
||||
const GreasePencilShrinkwrapModifierData *smd =
|
||||
static_cast<GreasePencilShrinkwrapModifierData *>(ptr->data);
|
||||
return smd->shrink_opts & MOD_SHRINKWRAP_CULL_TARGET_MASK;
|
||||
}
|
||||
|
||||
static void rna_GreasePencilShrinkwrapModifier_face_cull_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
GreasePencilShrinkwrapModifierData *smd = static_cast<GreasePencilShrinkwrapModifierData *>(
|
||||
ptr->data);
|
||||
smd->shrink_opts = (smd->shrink_opts & ~MOD_SHRINKWRAP_CULL_TARGET_MASK) | value;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_modifier_panel_open_prop(StructRNA *srna, const char *identifier, const int id)
|
||||
@@ -10271,6 +10294,152 @@ static void rna_def_modifier_grease_pencil_outline(BlenderRNA *brna)
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_shrinkwrap(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "GreasePencilShrinkwrapModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna,
|
||||
"Shrinkwrap Modifier",
|
||||
"Shrink wrapping modifier to shrink wrap an object to a target");
|
||||
RNA_def_struct_sdna(srna, "GreasePencilShrinkwrapModifierData");
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_SHRINKWRAP);
|
||||
|
||||
rna_def_modifier_grease_pencil_layer_filter(srna);
|
||||
rna_def_modifier_grease_pencil_material_filter(
|
||||
srna, "rna_GreasePencilShrinkwrapModifier_material_filter_set");
|
||||
rna_def_modifier_grease_pencil_vertex_group(
|
||||
srna, "rna_GreasePencilShrinkwrapModifier_vertex_group_name_set");
|
||||
|
||||
rna_def_modifier_panel_open_prop(srna, "open_influence_panel", 0);
|
||||
|
||||
RNA_define_lib_overridable(true);
|
||||
|
||||
prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "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_Modifier_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "wrap_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "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_Modifier_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "cull_face", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "shrink_opts");
|
||||
RNA_def_property_enum_items(prop, rna_enum_shrinkwrap_face_cull_items);
|
||||
RNA_def_property_enum_funcs(prop,
|
||||
"rna_GreasePencilShrinkwrapModifier_face_cull_get",
|
||||
"rna_GreasePencilShrinkwrapModifier_face_cull_set",
|
||||
nullptr);
|
||||
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_Modifier_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,
|
||||
nullptr,
|
||||
"rna_GreasePencilShrinkwrapModifier_target_set",
|
||||
nullptr,
|
||||
"rna_Mesh_object_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "auxiliary_target", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "aux_target");
|
||||
RNA_def_property_ui_text(prop, "Auxiliary Target", "Additional mesh target to shrink to");
|
||||
RNA_def_property_pointer_funcs(prop,
|
||||
nullptr,
|
||||
"rna_GreasePencilShrinkwrapModifier_aux_target_set",
|
||||
nullptr,
|
||||
"rna_Mesh_object_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||
|
||||
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS);
|
||||
RNA_def_property_ui_text(prop, "X", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_project_y", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS);
|
||||
RNA_def_property_ui_text(prop, "Y", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_project_z", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "proj_axis", MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS);
|
||||
RNA_def_property_ui_text(prop, "Z", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "subsurf_levels", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_negative_direction", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_positive_direction", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_invert_cull", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "smooth_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "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_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "smooth_step", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "smooth_step");
|
||||
RNA_def_property_range(prop, 1, 10);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Steps", "Number of times to apply smooth (high numbers can reduce FPS)");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
void RNA_def_modifier(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -10462,6 +10631,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
||||
rna_def_modifier_grease_pencil_time(brna);
|
||||
rna_def_modifier_grease_pencil_envelope(brna);
|
||||
rna_def_modifier_grease_pencil_outline(brna);
|
||||
rna_def_modifier_grease_pencil_shrinkwrap(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,6 +63,7 @@ set(SRC
|
||||
intern/MOD_grease_pencil_offset.cc
|
||||
intern/MOD_grease_pencil_opacity.cc
|
||||
intern/MOD_grease_pencil_outline.cc
|
||||
intern/MOD_grease_pencil_shrinkwrap.cc
|
||||
intern/MOD_grease_pencil_smooth.cc
|
||||
intern/MOD_grease_pencil_subdiv.cc
|
||||
intern/MOD_grease_pencil_thickness.cc
|
||||
|
||||
@@ -95,6 +95,7 @@ extern ModifierTypeInfo modifierType_GreasePencilArmature;
|
||||
extern ModifierTypeInfo modifierType_GreasePencilTime;
|
||||
extern ModifierTypeInfo modifierType_GreasePencilEnvelope;
|
||||
extern ModifierTypeInfo modifierType_GreasePencilOutline;
|
||||
extern ModifierTypeInfo modifierType_GreasePencilShrinkwrap;
|
||||
|
||||
/* MOD_util.cc */
|
||||
|
||||
|
||||
365
source/blender/modifiers/intern/MOD_grease_pencil_shrinkwrap.cc
Normal file
365
source/blender/modifiers/intern/MOD_grease_pencil_shrinkwrap.cc
Normal file
@@ -0,0 +1,365 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_material.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_instances.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_screen.hh"
|
||||
#include "BKE_shrinkwrap.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "GEO_smooth_curves.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "MOD_grease_pencil_util.hh"
|
||||
#include "MOD_ui_common.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
static void init_data(ModifierData *md)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
|
||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier));
|
||||
|
||||
MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(GreasePencilShrinkwrapModifierData), modifier);
|
||||
modifier::greasepencil::init_influence_data(&smd->influence, false);
|
||||
}
|
||||
|
||||
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
|
||||
{
|
||||
const auto *smd = reinterpret_cast<const GreasePencilShrinkwrapModifierData *>(md);
|
||||
auto *tsmd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(target);
|
||||
|
||||
modifier::greasepencil::free_influence_data(&tsmd->influence);
|
||||
|
||||
BKE_modifier_copydata_generic(md, target, flag);
|
||||
modifier::greasepencil::copy_influence_data(&smd->influence, &tsmd->influence, flag);
|
||||
}
|
||||
|
||||
static void free_data(ModifierData *md)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
modifier::greasepencil::free_influence_data(&smd->influence);
|
||||
|
||||
if (smd->cache_data) {
|
||||
BKE_shrinkwrap_free_tree(smd->cache_data);
|
||||
MEM_SAFE_FREE(smd->cache_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
modifier::greasepencil::foreach_influence_ID_link(&smd->influence, ob, walk, user_data);
|
||||
walk(user_data, ob, (ID **)&smd->target, IDWALK_CB_NOP);
|
||||
walk(user_data, ob, (ID **)&smd->aux_target, IDWALK_CB_NOP);
|
||||
}
|
||||
|
||||
static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(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 (smd->target == nullptr || smd->target->type != OB_MESH) {
|
||||
return true;
|
||||
}
|
||||
if (smd->aux_target != nullptr && smd->aux_target->type != OB_MESH) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
CustomData_MeshMasks mask = {0};
|
||||
|
||||
if (BKE_shrinkwrap_needs_normals(smd->shrink_type, smd->shrink_mode)) {
|
||||
mask.lmask |= CD_MASK_CUSTOMLOOPNORMAL;
|
||||
}
|
||||
|
||||
if (smd->target != nullptr) {
|
||||
DEG_add_object_relation(
|
||||
ctx->node, smd->target, DEG_OB_COMP_TRANSFORM, "Grease Pencil Shrinkwrap Modifier");
|
||||
DEG_add_object_relation(
|
||||
ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Grease Pencil Shrinkwrap Modifier");
|
||||
DEG_add_customdata_mask(ctx->node, smd->target, &mask);
|
||||
if (smd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
|
||||
DEG_add_special_eval_flag(ctx->node, &smd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
|
||||
}
|
||||
}
|
||||
if (smd->aux_target != nullptr) {
|
||||
DEG_add_object_relation(
|
||||
ctx->node, smd->aux_target, DEG_OB_COMP_TRANSFORM, "Grease Pencil Shrinkwrap Modifier");
|
||||
DEG_add_object_relation(
|
||||
ctx->node, smd->aux_target, DEG_OB_COMP_GEOMETRY, "Grease Pencil Shrinkwrap Modifier");
|
||||
DEG_add_customdata_mask(ctx->node, smd->aux_target, &mask);
|
||||
if (smd->shrink_type == MOD_SHRINKWRAP_TARGET_PROJECT) {
|
||||
DEG_add_special_eval_flag(
|
||||
ctx->node, &smd->aux_target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
|
||||
}
|
||||
}
|
||||
DEG_add_depends_on_transform_relation(ctx->node, "Grease Pencil Shrinkwrap Modifier");
|
||||
}
|
||||
|
||||
static void modify_drawing(const GreasePencilShrinkwrapModifierData &smd,
|
||||
const ModifierEvalContext &ctx,
|
||||
bke::greasepencil::Drawing &drawing)
|
||||
{
|
||||
bke::CurvesGeometry &curves = drawing.strokes_for_write();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const Span<MDeformVert> dverts = curves.deform_verts();
|
||||
const MutableSpan<float3> positions = curves.positions_for_write();
|
||||
const int defgrp_idx = BKE_object_defgroup_name_index(ctx.object,
|
||||
smd.influence.vertex_group_name);
|
||||
|
||||
/* Selected source curves. */
|
||||
IndexMaskMemory curve_mask_memory;
|
||||
const IndexMask curves_mask = modifier::greasepencil::get_filtered_stroke_mask(
|
||||
ctx.object, drawing.strokes(), smd.influence, curve_mask_memory);
|
||||
|
||||
ShrinkwrapParams params;
|
||||
params.target = smd.target;
|
||||
params.aux_target = smd.aux_target;
|
||||
params.invert_vertex_weights = smd.influence.flag & GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP;
|
||||
params.keep_distance = smd.keep_dist;
|
||||
params.shrink_type = smd.shrink_type;
|
||||
params.shrink_options = smd.shrink_opts;
|
||||
params.shrink_mode = smd.shrink_mode;
|
||||
params.projection_limit = smd.proj_limit;
|
||||
params.projection_axis = smd.proj_axis;
|
||||
params.subsurf_levels = smd.subsurf_levels;
|
||||
|
||||
curves_mask.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const Span<MDeformVert> curve_dverts = dverts.is_empty() ? dverts : dverts.slice(points);
|
||||
const MutableSpan<float3> curve_positions = positions.slice(points);
|
||||
|
||||
shrinkwrapParams_deform(
|
||||
params, *ctx.object, *smd.cache_data, curve_dverts, defgrp_idx, curve_positions);
|
||||
});
|
||||
|
||||
/* Optional smoothing after shrinkwrap. */
|
||||
const VArray<bool> point_selection = VArray<bool>::ForSingle(true, curves.points_num());
|
||||
const bool smooth_ends = false;
|
||||
const bool keep_shape = true;
|
||||
geometry::smooth_curve_attribute(curves_mask,
|
||||
points_by_curve,
|
||||
point_selection,
|
||||
curves.cyclic(),
|
||||
smd.smooth_step,
|
||||
smd.smooth_factor,
|
||||
smooth_ends,
|
||||
keep_shape,
|
||||
positions);
|
||||
|
||||
drawing.tag_positions_changed();
|
||||
}
|
||||
|
||||
static void ensure_shrinkwrap_cache_data(GreasePencilShrinkwrapModifierData &smd,
|
||||
const ModifierEvalContext &ctx)
|
||||
{
|
||||
if (smd.cache_data) {
|
||||
BKE_shrinkwrap_free_tree(smd.cache_data);
|
||||
MEM_SAFE_FREE(smd.cache_data);
|
||||
}
|
||||
Object *target_ob = DEG_get_evaluated_object(ctx.depsgraph, smd.target);
|
||||
Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(target_ob);
|
||||
|
||||
smd.cache_data = static_cast<ShrinkwrapTreeData *>(
|
||||
MEM_callocN(sizeof(ShrinkwrapTreeData), __func__));
|
||||
const bool tree_ok = BKE_shrinkwrap_init_tree(
|
||||
smd.cache_data, target_mesh, smd.shrink_type, smd.shrink_mode, false);
|
||||
if (!tree_ok) {
|
||||
MEM_SAFE_FREE(smd.cache_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void modify_geometry_set(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
bke::GeometrySet *geometry_set)
|
||||
{
|
||||
using bke::greasepencil::Drawing;
|
||||
using bke::greasepencil::Layer;
|
||||
using modifier::greasepencil::LayerDrawingInfo;
|
||||
|
||||
auto &smd = *reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
BLI_assert(smd.target != nullptr);
|
||||
if (smd.target == ctx->object || smd.aux_target == ctx->object) {
|
||||
return;
|
||||
}
|
||||
if (!geometry_set->has_grease_pencil()) {
|
||||
return;
|
||||
}
|
||||
GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
|
||||
const int frame = grease_pencil.runtime->eval_frame;
|
||||
|
||||
ensure_shrinkwrap_cache_data(smd, *ctx);
|
||||
|
||||
IndexMaskMemory mask_memory;
|
||||
const IndexMask layer_mask = modifier::greasepencil::get_filtered_layer_mask(
|
||||
grease_pencil, smd.influence, mask_memory);
|
||||
|
||||
const Vector<Drawing *> drawings = modifier::greasepencil::get_drawings_for_write(
|
||||
grease_pencil, layer_mask, frame);
|
||||
threading::parallel_for_each(drawings,
|
||||
[&](Drawing *drawing) { modify_drawing(smd, *ctx, *drawing); });
|
||||
}
|
||||
|
||||
static void panel_draw(const bContext *C, Panel *panel)
|
||||
{
|
||||
static const eUI_Item_Flag toggles_flag = UI_ITEM_R_TOGGLE | UI_ITEM_R_FORCE_BLANK_DECORATE;
|
||||
|
||||
uiLayout *layout = panel->layout;
|
||||
|
||||
PointerRNA ob_ptr;
|
||||
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||
int wrap_method = RNA_enum_get(ptr, "wrap_method");
|
||||
uiLayout *col, *row;
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
uiItemR(layout, ptr, "wrap_method", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
if (ELEM(wrap_method,
|
||||
MOD_SHRINKWRAP_PROJECT,
|
||||
MOD_SHRINKWRAP_NEAREST_SURFACE,
|
||||
MOD_SHRINKWRAP_TARGET_PROJECT))
|
||||
{
|
||||
uiItemR(layout, ptr, "wrap_mode", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
if (wrap_method == MOD_SHRINKWRAP_PROJECT) {
|
||||
uiItemR(layout, ptr, "project_limit", UI_ITEM_NONE, IFACE_("Limit"), ICON_NONE);
|
||||
uiItemR(layout, ptr, "subsurf_levels", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
row = uiLayoutRowWithHeading(col, true, IFACE_("Axis"));
|
||||
uiItemR(row, ptr, "use_project_x", toggles_flag, nullptr, ICON_NONE);
|
||||
uiItemR(row, ptr, "use_project_y", toggles_flag, nullptr, ICON_NONE);
|
||||
uiItemR(row, ptr, "use_project_z", toggles_flag, nullptr, ICON_NONE);
|
||||
|
||||
uiItemR(col, ptr, "use_negative_direction", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "use_positive_direction", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
uiItemR(layout, ptr, "cull_face", UI_ITEM_R_EXPAND, nullptr, 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", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
uiItemR(layout, ptr, "target", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
if (wrap_method == MOD_SHRINKWRAP_PROJECT) {
|
||||
uiItemR(layout, ptr, "auxiliary_target", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
uiItemR(layout, ptr, "offset", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
uiItemR(layout, ptr, "smooth_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "smooth_step", UI_ITEM_NONE, IFACE_("Repeat"), ICON_NONE);
|
||||
|
||||
if (uiLayout *influence_panel = uiLayoutPanelProp(
|
||||
C, layout, ptr, "open_influence_panel", "Influence"))
|
||||
{
|
||||
modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr);
|
||||
modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr);
|
||||
modifier::greasepencil::draw_vertex_group_settings(C, influence_panel, ptr);
|
||||
}
|
||||
|
||||
modifier_panel_end(layout, ptr);
|
||||
}
|
||||
|
||||
static void panel_register(ARegionType *region_type)
|
||||
{
|
||||
modifier_panel_register(region_type, eModifierType_GreasePencilShrinkwrap, panel_draw);
|
||||
}
|
||||
|
||||
static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
|
||||
{
|
||||
const auto *smd = reinterpret_cast<const GreasePencilShrinkwrapModifierData *>(md);
|
||||
|
||||
BLO_write_struct(writer, GreasePencilShrinkwrapModifierData, smd);
|
||||
modifier::greasepencil::write_influence_data(writer, &smd->influence);
|
||||
}
|
||||
|
||||
static void blend_read(BlendDataReader *reader, ModifierData *md)
|
||||
{
|
||||
auto *smd = reinterpret_cast<GreasePencilShrinkwrapModifierData *>(md);
|
||||
|
||||
modifier::greasepencil::read_influence_data(reader, &smd->influence);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
|
||||
ModifierTypeInfo modifierType_GreasePencilShrinkwrap = {
|
||||
/*idname*/ "GreasePencilShrinkwrap",
|
||||
/*name*/ N_("Shrinkwrap"),
|
||||
/*struct_name*/ "GreasePencilShrinkwrapModifierData",
|
||||
/*struct_size*/ sizeof(GreasePencilShrinkwrapModifierData),
|
||||
/*srna*/ &RNA_GreasePencilShrinkwrapModifier,
|
||||
/*type*/ ModifierTypeType::OnlyDeform,
|
||||
/*flags*/ eModifierTypeFlag_AcceptsGreasePencil | eModifierTypeFlag_SupportsEditmode |
|
||||
eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping,
|
||||
/*icon*/ ICON_MOD_SHRINKWRAP,
|
||||
|
||||
/*copy_data*/ blender::copy_data,
|
||||
|
||||
/*deform_verts*/ nullptr,
|
||||
/*deform_matrices*/ nullptr,
|
||||
/*deform_verts_EM*/ nullptr,
|
||||
/*deform_matrices_EM*/ nullptr,
|
||||
/*modify_mesh*/ nullptr,
|
||||
/*modify_geometry_set*/ blender::modify_geometry_set,
|
||||
|
||||
/*init_data*/ blender::init_data,
|
||||
/*required_data_mask*/ nullptr,
|
||||
/*free_data*/ blender::free_data,
|
||||
/*is_disabled*/ blender::is_disabled,
|
||||
/*update_depsgraph*/ blender::update_depsgraph,
|
||||
/*depends_on_time*/ nullptr,
|
||||
/*depends_on_normals*/ nullptr,
|
||||
/*foreach_ID_link*/ blender::foreach_ID_link,
|
||||
/*foreach_tex_link*/ nullptr,
|
||||
/*free_runtime_data*/ nullptr,
|
||||
/*panel_register*/ blender::panel_register,
|
||||
/*blend_write*/ blender::blend_write,
|
||||
/*blend_read*/ blender::blend_read,
|
||||
};
|
||||
@@ -286,5 +286,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
||||
INIT_TYPE(GreasePencilTime);
|
||||
INIT_TYPE(GreasePencilEnvelope);
|
||||
INIT_TYPE(GreasePencilOutline);
|
||||
INIT_TYPE(GreasePencilShrinkwrap);
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user