diff options
author | Hans Goudey <h.goudey@me.com> | 2022-10-07 00:05:56 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-10-07 00:08:07 +0300 |
commit | 406a98aff893570eef1f2d217b87a5997a7a60d6 (patch) | |
tree | 39af815c97e1d9ec3b1cb5658186a8981e383a73 /source/blender/modifiers/intern/MOD_weightvgedit.cc | |
parent | 53d937a1700021e0cb7a52aa0c45da0014974e81 (diff) |
Cleanup: Move eight modifier files to C++
In preparation for moving mesh runtime data to C++.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_weightvgedit.cc')
-rw-r--r-- | source/blender/modifiers/intern/MOD_weightvgedit.cc | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.cc b/source/blender/modifiers/intern/MOD_weightvgedit.cc new file mode 100644 index 00000000000..bcfd47491d5 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_weightvgedit.cc @@ -0,0 +1,422 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2011 by Bastien Montagne. All rights reserved. */ + +/** \file + * \ingroup modifiers + */ + +#include <cstring> + +#include "BLI_utildefines.h" + +#include "BLI_ghash.h" +#include "BLI_listbase.h" +#include "BLI_rand.h" + +#include "BLT_translation.h" + +#include "DNA_color_types.h" /* CurveMapping. */ +#include "DNA_defaults.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" + +#include "BKE_colortools.h" /* CurveMapping. */ +#include "BKE_context.h" +#include "BKE_deform.h" +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_screen.h" +#include "BKE_texture.h" /* Texture masking. */ + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BLO_read_write.h" + +#include "RNA_access.h" +#include "RNA_prototypes.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_modifiertypes.h" +#include "MOD_ui_common.h" +#include "MOD_util.h" +#include "MOD_weightvg_util.h" + +/************************************** + * Modifiers functions. * + **************************************/ +static void initData(ModifierData *md) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier)); + + MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGEditModifierData), modifier); + + wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0); + BKE_curvemapping_init(wmd->cmap_curve); +} + +static void freeData(ModifierData *md) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + BKE_curvemapping_free(wmd->cmap_curve); +} + +static void copyData(const ModifierData *md, ModifierData *target, const int flag) +{ + const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md; + WeightVGEditModifierData *twmd = (WeightVGEditModifierData *)target; + + BKE_modifier_copydata_generic(md, target, flag); + + twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve); +} + +static void requiredDataMask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + /* We need vertex groups! */ + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; + + /* Ask for UV coordinates if we need them. */ + if (wmd->mask_tex_mapping == MOD_DISP_MAP_UV) { + r_cddata_masks->fmask |= CD_MASK_MTFACE; + } + + /* No need to ask for CD_PREVIEW_MLOOPCOL... */ +} + +static bool dependsOnTime(Scene *UNUSED(scene), ModifierData *md) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + if (wmd->mask_texture) { + return BKE_texture_dependsOnTime(wmd->mask_texture); + } + return false; +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER); + walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP); +} + +static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) +{ + walk(userData, ob, md, "mask_texture"); +} + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + bool need_transform_relation = false; + + if (wmd->mask_texture != nullptr) { + DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGEdit Modifier"); + + if (wmd->mask_tex_map_obj != nullptr && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { + MOD_depsgraph_update_object_bone_relation( + ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGEdit Modifier"); + need_transform_relation = true; + } + else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) { + need_transform_relation = true; + } + } + + if (need_transform_relation) { + DEG_add_depends_on_transform_relation(ctx->node, "WeightVGEdit Modifier"); + } +} + +static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams)) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + /* If no vertex group, bypass. */ + return (wmd->defgrp_name[0] == '\0'); +} + +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +{ + BLI_assert(mesh != nullptr); + + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + MDeformWeight **dw = nullptr; + float *org_w; /* Array original weights. */ + float *new_w; /* Array new weights. */ + int i; + const bool invert_vgroup_mask = (wmd->edit_flags & MOD_WVG_EDIT_INVERT_VGROUP_MASK) != 0; + + /* Flags. */ + const bool do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0; + const bool do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0; + /* Only do weight-preview in Object, Sculpt and Pose modes! */ +#if 0 + const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); +#endif + + /* Get number of verts. */ + const int verts_num = mesh->totvert; + + /* Check if we can just return the original mesh. + * Must have verts and therefore verts assigned to vgroups to do anything useful! + */ + if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) { + return mesh; + } + + /* Get vgroup idx from its name. */ + const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name); + if (defgrp_index == -1) { + return mesh; + } + + const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT); + /* If no vertices were ever added to an object's vgroup, dvert might be nullptr. */ + if (!has_mdef) { + /* If this modifier is not allowed to add vertices, just return. */ + if (!do_add) { + return mesh; + } + } + + MDeformVert *dvert = BKE_mesh_deform_verts_for_write(mesh); + + /* Ultimate security check. */ + if (!dvert) { + return mesh; + } + + /* Get org weights, assuming 0.0 for vertices not in given vgroup. */ + org_w = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float), __func__)); + new_w = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float), __func__)); + dw = static_cast<MDeformWeight **>( + MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), __func__)); + for (i = 0; i < verts_num; i++) { + dw[i] = BKE_defvert_find_index(&dvert[i], defgrp_index); + if (dw[i]) { + org_w[i] = new_w[i] = dw[i]->weight; + } + else { + org_w[i] = new_w[i] = wmd->default_weight; + } + } + + /* Do mapping. */ + const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0; + const bool do_normalize = (wmd->edit_flags & MOD_WVG_EDIT_WEIGHTS_NORMALIZE) != 0; + if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) { + RNG *rng = nullptr; + + if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM) { + rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ctx->object->id.name + 2)); + } + + weightvg_do_map(verts_num, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng); + + if (rng) { + BLI_rng_free(rng); + } + } + + /* Do masking. */ + Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); + weightvg_do_mask(ctx, + verts_num, + nullptr, + org_w, + new_w, + ctx->object, + mesh, + wmd->mask_constant, + wmd->mask_defgrp_name, + scene, + wmd->mask_texture, + wmd->mask_tex_use_channel, + wmd->mask_tex_mapping, + wmd->mask_tex_map_obj, + wmd->mask_tex_map_bone, + wmd->mask_tex_uvlayer_name, + invert_vgroup_mask); + + /* Update/add/remove from vgroup. */ + weightvg_update_vg(dvert, + defgrp_index, + dw, + verts_num, + nullptr, + org_w, + do_add, + wmd->add_threshold, + do_rem, + wmd->rem_threshold, + do_normalize); + + /* If weight preview enabled... */ +#if 0 /* XXX Currently done in mod stack :/ */ + if (do_prev) { + DM_update_weight_mcol(ob, dm, 0, org_w, 0, nullptr); + } +#endif + + /* Freeing stuff. */ + MEM_freeN(org_w); + MEM_freeN(new_w); + MEM_freeN(dw); + + mesh->runtime.is_original_bmesh = false; + + /* Return the vgroup-modified mesh. */ + return mesh; +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *sub, *col, *row; + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + uiLayoutSetPropSep(layout, true); + + col = uiLayoutColumn(layout, true); + uiItemPointerR(col, ptr, "vertex_group", &ob_ptr, "vertex_groups", nullptr, ICON_NONE); + + uiItemR(layout, ptr, "default_weight", UI_ITEM_R_SLIDER, nullptr, ICON_NONE); + + col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Add")); + row = uiLayoutRow(col, true); + uiLayoutSetPropDecorate(row, false); + sub = uiLayoutRow(row, true); + uiItemR(sub, ptr, "use_add", 0, "", ICON_NONE); + sub = uiLayoutRow(sub, true); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_add")); + uiLayoutSetPropSep(sub, false); + uiItemR(sub, ptr, "add_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE); + uiItemDecoratorR(row, ptr, "add_threshold", 0); + + col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Remove")); + row = uiLayoutRow(col, true); + uiLayoutSetPropDecorate(row, false); + sub = uiLayoutRow(row, true); + uiItemR(sub, ptr, "use_remove", 0, "", ICON_NONE); + sub = uiLayoutRow(sub, true); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_remove")); + uiLayoutSetPropSep(sub, false); + uiItemR(sub, ptr, "remove_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE); + uiItemDecoratorR(row, ptr, "remove_threshold", 0); + + uiItemR(layout, ptr, "normalize", 0, nullptr, ICON_NONE); + + modifier_panel_end(layout, ptr); +} + +static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *row, *sub; + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + uiLayoutSetPropSep(layout, true); + + row = uiLayoutRow(layout, true); + uiItemR(row, ptr, "falloff_type", 0, IFACE_("Type"), ICON_NONE); + sub = uiLayoutRow(row, true); + uiLayoutSetPropSep(sub, false); + uiItemR(row, ptr, "invert_falloff", 0, "", ICON_ARROW_LEFTRIGHT); + if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) { + uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false); + } +} + +static void influence_panel_draw(const bContext *C, Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA ob_ptr; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); + + weightvg_ui_common(C, &ob_ptr, ptr, layout); +} + +static void panelRegister(ARegionType *region_type) +{ + PanelType *panel_type = modifier_panel_register( + region_type, eModifierType_WeightVGEdit, panel_draw); + modifier_subpanel_register( + region_type, "falloff", "Falloff", nullptr, falloff_panel_draw, panel_type); + modifier_subpanel_register( + region_type, "influence", "Influence", nullptr, influence_panel_draw, panel_type); +} + +static void blendWrite(BlendWriter *writer, const ID *UNUSED(id_owner), const ModifierData *md) +{ + const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md; + + BLO_write_struct(writer, WeightVGEditModifierData, wmd); + + if (wmd->cmap_curve) { + BKE_curvemapping_blend_write(writer, wmd->cmap_curve); + } +} + +static void blendRead(BlendDataReader *reader, ModifierData *md) +{ + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + BLO_read_data_address(reader, &wmd->cmap_curve); + if (wmd->cmap_curve) { + BKE_curvemapping_blend_read(reader, wmd->cmap_curve); + } +} + +ModifierTypeInfo modifierType_WeightVGEdit = { + /* name */ N_("VertexWeightEdit"), + /* structName */ "WeightVGEditModifierData", + /* structSize */ sizeof(WeightVGEditModifierData), + /* srna */ &RNA_VertexWeightEditModifier, + /* type */ eModifierTypeType_NonGeometrical, + /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | + eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, + /* icon */ ICON_MOD_VERTEX_WEIGHT, + + /* copyData */ copyData, + + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, + /* modifyMesh */ modifyMesh, + /* modifyGeometrySet */ nullptr, + + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ nullptr, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ foreachTexLink, + /* freeRuntimeData */ nullptr, + /* panelRegister */ panelRegister, + /* blendWrite */ blendWrite, + /* blendRead */ blendRead, +}; |