From 4d387843e92457475235e17011b54e2c1623f190 Mon Sep 17 00:00:00 2001 From: YimingWu Date: Thu, 18 Jan 2024 13:02:53 +0100 Subject: [PATCH] GPv3: Subdivide Modifier This ports the Subdivide modifier from GPv2. Pull Request: https://projects.blender.org/blender/blender/pulls/117056 --- .../startup/bl_ui/properties_data_modifier.py | 4 +- .../blender/makesdna/DNA_modifier_defaults.h | 5 + source/blender/makesdna/DNA_modifier_types.h | 17 ++ source/blender/makesdna/intern/dna_defaults.c | 2 + .../blender/makesrna/intern/rna_modifier.cc | 43 ++++ source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/MOD_modifiertypes.hh | 1 + .../intern/MOD_grease_pencil_subdiv.cc | 205 ++++++++++++++++++ source/blender/modifiers/intern/MOD_util.cc | 1 + 9 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc diff --git a/scripts/startup/bl_ui/properties_data_modifier.py b/scripts/startup/bl_ui/properties_data_modifier.py index 7d046148de7..63bd27be7ab 100644 --- a/scripts/startup/bl_ui/properties_data_modifier.py +++ b/scripts/startup/bl_ui/properties_data_modifier.py @@ -73,7 +73,7 @@ class OBJECT_MT_modifier_add(ModifierAddMenu, Menu): layout.separator() if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'GREASEPENCIL'}: layout.menu("OBJECT_MT_modifier_add_edit") - if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME'}: + if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME', 'GREASEPENCIL'}: layout.menu("OBJECT_MT_modifier_add_generate") if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'VOLUME'}: layout.menu("OBJECT_MT_modifier_add_deform") @@ -149,6 +149,8 @@ class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu): self.operator_modifier_add(layout, 'WELD') if ob_type == 'MESH': self.operator_modifier_add(layout, 'WIREFRAME') + if ob_type == 'GREASEPENCIL': + self.operator_modifier_add(layout, 'GREASEPENCIL_SUBDIV') layout.template_modifier_asset_menu_items(catalog_path=self.bl_label) diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 288fa3b4473..0488d563232 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -808,4 +808,9 @@ .hardness_factor = 1.0f, \ } +#define _DNA_DEFAULT_GreasePencilSubdivModifierData \ + { \ + .level = 1, \ + } + /* clang-format off */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 7bc475c24f1..33ee5887127 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -94,6 +94,7 @@ typedef enum ModifierType { eModifierType_VolumeDisplace = 59, eModifierType_VolumeToMesh = 60, eModifierType_GreasePencilOpacity = 61, + eModifierType_GreasePencilSubdiv = 62, NUM_MODIFIER_TYPES, } ModifierType; @@ -2547,3 +2548,19 @@ typedef enum GreasePencilOpacityModifierFlag { /* Set the opacity for every point in a stroke, otherwise multiply existing opacity. */ MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY = (1 << 2), } GreasePencilOpacityModifierFlag; + +typedef struct GreasePencilSubdivModifierData { + ModifierData modifier; + GreasePencilModifierInfluenceData influence; + /** `GreasePencilSubdivModifierFlag`. */ + int flag; + /** Number of subdivisions. */ + int level; + + char _pad[8]; + void *_pad1; +} GreasePencilSubdivModifierData; + +typedef enum GreasePencilSubdivModifierFlag { + MOD_GREASE_PENCIL_SUBDIV_OPEN_INFLUENCE_PANEL = (1 << 0), +} GreasePencilSubdivModifierFlag; diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index 5249d684906..06620e0236e 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -292,6 +292,7 @@ SDNA_DEFAULT_DECL_STRUCT(WeightVGMixModifierData); SDNA_DEFAULT_DECL_STRUCT(WeightVGProximityModifierData); SDNA_DEFAULT_DECL_STRUCT(WeldModifierData); SDNA_DEFAULT_DECL_STRUCT(WireframeModifierData); +SDNA_DEFAULT_DECL_STRUCT(GreasePencilSubdivModifierData); /* DNA_gpencil_modifier_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(ArmatureGpencilModifierData); @@ -537,6 +538,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL(WeightVGProximityModifierData), SDNA_DEFAULT_DECL(WeldModifierData), SDNA_DEFAULT_DECL(WireframeModifierData), + SDNA_DEFAULT_DECL(GreasePencilSubdivModifierData), /* DNA_gpencil_modifier_defaults.h */ SDNA_DEFAULT_DECL(ArmatureGpencilModifierData), diff --git a/source/blender/makesrna/intern/rna_modifier.cc b/source/blender/makesrna/intern/rna_modifier.cc index 42cb63b998d..5c1f9f348c2 100644 --- a/source/blender/makesrna/intern/rna_modifier.cc +++ b/source/blender/makesrna/intern/rna_modifier.cc @@ -12,6 +12,7 @@ #include "DNA_armature_types.h" #include "DNA_cachefile_types.h" +#include "DNA_gpencil_modifier_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_force_types.h" @@ -200,6 +201,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_MOD_WIREFRAME, "Wireframe", "Convert faces into thickened edges"}, + {eModifierType_GreasePencilSubdiv, + "GREASEPENCIL_SUBDIV", + ICON_GREASEPENCIL, + "Subdivide strokes", + "Grease Pencil subdivide modifier"}, RNA_ENUM_ITEM_HEADING(N_("Deform"), nullptr), {eModifierType_Armature, @@ -1796,6 +1802,8 @@ static void rna_GreasePencilModifier_material_set(PointerRNA *ptr, RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOpacity); RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity); +RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilSubdiv); +RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilSubdiv); static void rna_GreasePencilOpacityModifier_opacity_factor_range( PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax) @@ -7730,6 +7738,40 @@ static void rna_def_modifier_grease_pencil_opacity(BlenderRNA *brna) prop, nullptr, "flag", MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY); RNA_def_property_ui_text( prop, "Uniform Opacity", "Replace the stroke opacity instead of modulating each point"); + + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); +} + +static void rna_def_modifier_grease_pencil_subdiv(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "GreasePencilSubdivModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Subdivision Modifier", "Subdivide Stroke modifier"); + RNA_def_struct_sdna(srna, "GreasePencilSubdivModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_SUBSURF); + + rna_def_modifier_grease_pencil_layer_filter(srna); + rna_def_modifier_grease_pencil_material_filter( + srna, "rna_GreasePencilSubdivModifier_material_filter_set"); + rna_def_modifier_grease_pencil_vertex_group( + srna, "rna_GreasePencilSubdivModifier_vertex_group_name_set"); + rna_def_modifier_grease_pencil_custom_curve(srna); + + rna_def_modifier_panel_open_prop(srna, "open_influence_panel", 0); + + RNA_define_lib_overridable(true); + + prop = RNA_def_property(srna, "level", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, nullptr, "level"); + /* Since the new subdiv algorithm uses linear cut count, we set the limits as 2^n the old value + * to get the same range as before. */ + RNA_def_property_range(prop, 0, 65536); + RNA_def_property_ui_range(prop, 0, 32, 1, 0); + RNA_def_property_ui_text(prop, "Level", "Number of subdivisions"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); RNA_define_lib_overridable(false); @@ -7896,6 +7938,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_volume_displace(brna); rna_def_modifier_volume_to_mesh(brna); rna_def_modifier_grease_pencil_opacity(brna); + rna_def_modifier_grease_pencil_subdiv(brna); } #endif diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index f3920f2560f..dafd5ecbcf9 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -45,6 +45,7 @@ set(SRC intern/MOD_explode.cc intern/MOD_fluid.cc intern/MOD_grease_pencil_opacity.cc + intern/MOD_grease_pencil_subdiv.cc intern/MOD_grease_pencil_util.cc intern/MOD_hook.cc intern/MOD_laplaciandeform.cc diff --git a/source/blender/modifiers/MOD_modifiertypes.hh b/source/blender/modifiers/MOD_modifiertypes.hh index 909e6b3ce18..3dd36537c8a 100644 --- a/source/blender/modifiers/MOD_modifiertypes.hh +++ b/source/blender/modifiers/MOD_modifiertypes.hh @@ -74,6 +74,7 @@ extern ModifierTypeInfo modifierType_MeshToVolume; extern ModifierTypeInfo modifierType_VolumeDisplace; extern ModifierTypeInfo modifierType_VolumeToMesh; extern ModifierTypeInfo modifierType_GreasePencilOpacity; +extern ModifierTypeInfo modifierType_GreasePencilSubdiv; /* MOD_util.cc */ diff --git a/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc b/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc new file mode 100644 index 00000000000..f0c4d338023 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_grease_pencil_subdiv.cc @@ -0,0 +1,205 @@ +/* SPDX-FileCopyrightText: 2005 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup modifiers + */ + +#include "BLI_array.hh" +#include "BLI_index_mask.hh" +#include "BLI_math_vector_types.hh" +#include "BLI_task.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BLO_read_write.hh" + +#include "DNA_defaults.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BKE_context.hh" +#include "BKE_curves.hh" +#include "BKE_geometry_set.hh" +#include "BKE_grease_pencil.hh" +#include "BKE_lib_query.h" +#include "BKE_modifier.hh" +#include "BKE_screen.hh" + +#include "GEO_subdivide_curves.hh" + +#include "UI_interface.hh" +#include "UI_resources.hh" + +#include "ED_grease_pencil.hh" + +#include "MOD_grease_pencil_util.hh" +#include "MOD_modifiertypes.hh" +#include "MOD_ui_common.hh" + +#include "RNA_prototypes.h" + +#include "DEG_depsgraph.hh" +#include "DEG_depsgraph_query.hh" + +namespace blender { + +static void init_data(ModifierData *md) +{ + GreasePencilSubdivModifierData *gpmd = reinterpret_cast(md); + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier)); + + MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(GreasePencilSubdivModifierData), modifier); + modifier::greasepencil::init_influence_data(&gpmd->influence, true); +} + +static void free_data(ModifierData *md) +{ + GreasePencilSubdivModifierData *mmd = reinterpret_cast(md); + + modifier::greasepencil::free_influence_data(&mmd->influence); +} + +static void copy_data(const ModifierData *md, ModifierData *target, int flag) +{ + const GreasePencilSubdivModifierData *gmd = + reinterpret_cast(md); + GreasePencilSubdivModifierData *tgmd = reinterpret_cast( + target); + + BKE_modifier_copydata_generic(md, target, flag); + modifier::greasepencil::copy_influence_data(&gmd->influence, &tgmd->influence, flag); +} + +static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md) +{ + const GreasePencilSubdivModifierData *mmd = + reinterpret_cast(md); + + BLO_write_struct(writer, GreasePencilSubdivModifierData, mmd); + modifier::greasepencil::write_influence_data(writer, &mmd->influence); +} + +static void blend_read(BlendDataReader *reader, ModifierData *md) +{ + GreasePencilSubdivModifierData *mmd = reinterpret_cast(md); + + modifier::greasepencil::read_influence_data(reader, &mmd->influence); +} + +static void deform_drawing(ModifierData &md, + Depsgraph * /*depsgraph*/, + Object &ob, + bke::greasepencil::Drawing &drawing) +{ + GreasePencilSubdivModifierData &mmd = reinterpret_cast(md); + + IndexMaskMemory memory; + const IndexMask strokes = modifier::greasepencil::get_filtered_stroke_mask( + &ob, drawing.strokes_for_write(), mmd.influence, memory); + + VArray cuts = VArray::ForSingle(mmd.level, drawing.strokes().points_num()); + + drawing.strokes_for_write() = geometry::subdivide_curves( + drawing.strokes(), strokes, std::move(cuts), {}); + drawing.tag_topology_changed(); +} + +static void modify_geometry_set(ModifierData *md, + const ModifierEvalContext *ctx, + bke::GeometrySet *geometry_set) +{ + GreasePencilSubdivModifierData *mmd = reinterpret_cast(md); + + if (mmd->level < 1 || !geometry_set->has_grease_pencil()) { + return; + } + + GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write(); + const int current_frame = DEG_get_evaluated_scene(ctx->depsgraph)->r.cfra; + + IndexMaskMemory mask_memory; + const IndexMask layer_mask = modifier::greasepencil::get_filtered_layer_mask( + grease_pencil, mmd->influence, mask_memory); + const Vector drawings = + modifier::greasepencil::get_drawings_for_write(grease_pencil, layer_mask, current_frame); + + threading::parallel_for_each(drawings, [&](bke::greasepencil::Drawing *drawing) { + deform_drawing(*md, ctx->depsgraph, *ctx->object, *drawing); + }); +} + +static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data) +{ + GreasePencilSubdivModifierData *mmd = reinterpret_cast(md); + + modifier::greasepencil::foreach_influence_ID_link(&mmd->influence, ob, walk, user_data); +} + +static void panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); + + uiLayoutSetPropSep(layout, true); + + uiItemR(layout, ptr, "level", UI_ITEM_NONE, IFACE_("Subdivisions"), ICON_NONE); + + if (uiLayout *influence_panel = uiLayoutPanel( + C, layout, "Influence", ptr, "open_influence_panel")) + { + 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_GreasePencilSubdiv, panel_draw); +} + +} // namespace blender + +ModifierTypeInfo modifierType_GreasePencilSubdiv = { + /*idname*/ "GreasePencilSubdivModifier", + /*name*/ N_("Subdivide"), + /*struct_name*/ "GreasePencilSubdivModifierData", + /*struct_size*/ sizeof(GreasePencilSubdivModifierData), + /*srna*/ &RNA_GreasePencilSubdivModifier, + /*type*/ ModifierTypeType::Constructive, + /*flags*/ + (eModifierTypeFlag_AcceptsGreasePencil | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode), + /*icon*/ ICON_MOD_SUBSURF, + + /*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*/ nullptr, + /*update_depsgraph*/ nullptr, + /*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, +}; diff --git a/source/blender/modifiers/intern/MOD_util.cc b/source/blender/modifiers/intern/MOD_util.cc index 7db69740186..4a2964a983b 100644 --- a/source/blender/modifiers/intern/MOD_util.cc +++ b/source/blender/modifiers/intern/MOD_util.cc @@ -271,5 +271,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(VolumeToMesh); INIT_TYPE(Nodes); INIT_TYPE(GreasePencilOpacity); + INIT_TYPE(GreasePencilSubdiv); #undef INIT_TYPE }