Blender V4.3
MOD_weightvgedit.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 by Bastien Montagne. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstring>
10
11#include "BLI_utildefines.h"
12
13#include "BLI_ghash.h"
14#include "BLI_listbase.h"
15#include "BLI_rand.h"
16
17#include "BLT_translation.hh"
18
19#include "DNA_color_types.h" /* CurveMapping. */
20#include "DNA_defaults.h"
21#include "DNA_mesh_types.h"
22#include "DNA_meshdata_types.h"
23#include "DNA_modifier_types.h"
24#include "DNA_object_types.h"
25#include "DNA_screen_types.h"
26
27#include "BKE_colortools.hh" /* CurveMapping. */
28#include "BKE_customdata.hh"
29#include "BKE_deform.hh"
30#include "BKE_lib_query.hh"
31#include "BKE_mesh.hh"
32#include "BKE_modifier.hh"
33#include "BKE_texture.h" /* Texture masking. */
34
35#include "UI_interface.hh"
36#include "UI_resources.hh"
37
38#include "BLO_read_write.hh"
39
40#include "RNA_access.hh"
41#include "RNA_prototypes.hh"
42
45
46#include "MEM_guardedalloc.h"
47
48#include "MOD_ui_common.hh"
49#include "MOD_util.hh"
50#include "MOD_weightvg_util.hh"
51
52/**************************************
53 * Modifiers functions. *
54 **************************************/
66
72
73static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
74{
77
79
81}
82
83static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
84{
86
87 /* We need vertex groups! */
88 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
89
90 /* Ask for UV coordinates if we need them. */
92 r_cddata_masks->fmask |= CD_MASK_MTFACE;
93 }
94}
95
96static bool depends_on_time(Scene * /*scene*/, ModifierData *md)
97{
99
100 if (wmd->mask_texture) {
102 }
103 return false;
104}
105
106static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
107{
109
110 walk(user_data, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
111 walk(user_data, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP);
112}
113
114static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
115{
116 PointerRNA ptr = RNA_pointer_create(&ob->id, &RNA_Modifier, md);
117 PropertyRNA *prop = RNA_struct_find_property(&ptr, "mask_texture");
118 walk(user_data, ob, md, &ptr, prop);
119}
120
122{
124 bool need_transform_relation = false;
125
126 if (wmd->mask_texture != nullptr) {
127 DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGEdit Modifier");
128
129 if (wmd->mask_tex_map_obj != nullptr && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
131 ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGEdit Modifier");
132 need_transform_relation = true;
133 }
134 else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
135 need_transform_relation = true;
136 }
137 }
138
139 if (need_transform_relation) {
140 DEG_add_depends_on_transform_relation(ctx->node, "WeightVGEdit Modifier");
141 }
142}
143
144static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
145{
147 /* If no vertex group, bypass. */
148 return (wmd->defgrp_name[0] == '\0');
149}
150
151static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
152{
153 BLI_assert(mesh != nullptr);
154
156
157 MDeformWeight **dw = nullptr;
158 float *org_w; /* Array original weights. */
159 float *new_w; /* Array new weights. */
160 int i;
161 const bool invert_vgroup_mask = (wmd->edit_flags & MOD_WVG_EDIT_INVERT_VGROUP_MASK) != 0;
162
163 /* Flags. */
164 const bool do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
165 const bool do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
166 /* Only do weight-preview in Object, Sculpt and Pose modes! */
167#if 0
168 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
169#endif
170
171 /* Get number of verts. */
172 const int verts_num = mesh->verts_num;
173
174 /* Check if we can just return the original mesh.
175 * Must have verts and therefore verts assigned to vgroups to do anything useful!
176 */
177 if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
178 return mesh;
179 }
180
181 /* Get vgroup idx from its name. */
182 const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
183 if (defgrp_index == -1) {
184 return mesh;
185 }
186
187 const bool has_mdef = CustomData_has_layer(&mesh->vert_data, CD_MDEFORMVERT);
188 /* If no vertices were ever added to an object's vgroup, dvert might be nullptr. */
189 if (!has_mdef) {
190 /* If this modifier is not allowed to add vertices, just return. */
191 if (!do_add) {
192 return mesh;
193 }
194 }
195
196 MDeformVert *dvert = mesh->deform_verts_for_write().data();
197
198 /* Ultimate security check. */
199 if (!dvert) {
200 return mesh;
201 }
202
203 /* Get org weights, assuming 0.0 for vertices not in given vgroup. */
204 org_w = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float), __func__));
205 new_w = static_cast<float *>(MEM_malloc_arrayN(verts_num, sizeof(float), __func__));
206 dw = static_cast<MDeformWeight **>(
207 MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), __func__));
208 for (i = 0; i < verts_num; i++) {
209 dw[i] = BKE_defvert_find_index(&dvert[i], defgrp_index);
210 if (dw[i]) {
211 org_w[i] = new_w[i] = dw[i]->weight;
212 }
213 else {
214 org_w[i] = new_w[i] = wmd->default_weight;
215 }
216 }
217
218 /* Do mapping. */
219 const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0;
220 const bool do_normalize = (wmd->edit_flags & MOD_WVG_EDIT_WEIGHTS_NORMALIZE) != 0;
221 if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
222 RNG *rng = nullptr;
223
226 }
227
228 weightvg_do_map(verts_num, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng);
229
230 if (rng) {
231 BLI_rng_free(rng);
232 }
233 }
234
235 /* Do masking. */
238 verts_num,
239 nullptr,
240 org_w,
241 new_w,
242 ctx->object,
243 mesh,
244 wmd->mask_constant,
245 wmd->mask_defgrp_name,
246 scene,
247 wmd->mask_texture,
249 wmd->mask_tex_mapping,
250 wmd->mask_tex_map_obj,
253 invert_vgroup_mask);
254
255 /* Update/add/remove from vgroup. */
256 weightvg_update_vg(dvert,
257 defgrp_index,
258 dw,
259 verts_num,
260 nullptr,
261 org_w,
262 do_add,
263 wmd->add_threshold,
264 do_rem,
265 wmd->rem_threshold,
266 do_normalize);
267
268 /* If weight preview enabled... */
269#if 0 /* XXX Currently done in mod stack :/ */
270 if (do_prev) {
271 DM_update_weight_mcol(ob, dm, 0, org_w, 0, nullptr);
272 }
273#endif
274
275 /* Freeing stuff. */
276 MEM_freeN(org_w);
277 MEM_freeN(new_w);
278 MEM_freeN(dw);
279
280 mesh->runtime->is_original_bmesh = false;
281
282 /* Return the vgroup-modified mesh. */
283 return mesh;
284}
285
286static void panel_draw(const bContext * /*C*/, Panel *panel)
287{
288 uiLayout *sub, *col, *row;
289 uiLayout *layout = panel->layout;
290
291 PointerRNA ob_ptr;
293
294 uiLayoutSetPropSep(layout, true);
295
296 col = uiLayoutColumn(layout, true);
297 uiItemPointerR(col, ptr, "vertex_group", &ob_ptr, "vertex_groups", nullptr, ICON_GROUP_VERTEX);
298
299 uiItemR(layout, ptr, "default_weight", UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
300
301 col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Add"));
302 row = uiLayoutRow(col, true);
303 uiLayoutSetPropDecorate(row, false);
304 sub = uiLayoutRow(row, true);
305 uiItemR(sub, ptr, "use_add", UI_ITEM_NONE, "", ICON_NONE);
306 sub = uiLayoutRow(sub, true);
307 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_add"));
308 uiLayoutSetPropSep(sub, false);
309 uiItemR(sub, ptr, "add_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
310 uiItemDecoratorR(row, ptr, "add_threshold", 0);
311
312 col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Remove"));
313 row = uiLayoutRow(col, true);
314 uiLayoutSetPropDecorate(row, false);
315 sub = uiLayoutRow(row, true);
316 uiItemR(sub, ptr, "use_remove", UI_ITEM_NONE, "", ICON_NONE);
317 sub = uiLayoutRow(sub, true);
318 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_remove"));
319 uiLayoutSetPropSep(sub, false);
320 uiItemR(sub, ptr, "remove_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
321 uiItemDecoratorR(row, ptr, "remove_threshold", 0);
322
323 uiItemR(layout, ptr, "normalize", UI_ITEM_NONE, nullptr, ICON_NONE);
324
325 modifier_panel_end(layout, ptr);
326}
327
328static void falloff_panel_draw(const bContext * /*C*/, Panel *panel)
329{
330 uiLayout *row, *sub;
331 uiLayout *layout = panel->layout;
332
333 PointerRNA ob_ptr;
335
336 uiLayoutSetPropSep(layout, true);
337
338 row = uiLayoutRow(layout, true);
339 uiItemR(row, ptr, "falloff_type", UI_ITEM_NONE, IFACE_("Type"), ICON_NONE);
340 sub = uiLayoutRow(row, true);
341 uiLayoutSetPropSep(sub, false);
342 uiItemR(row, ptr, "invert_falloff", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
343 if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) {
344 uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false);
345 }
346}
347
348static void influence_panel_draw(const bContext *C, Panel *panel)
349{
350 uiLayout *layout = panel->layout;
351
352 PointerRNA ob_ptr;
354
355 weightvg_ui_common(C, &ob_ptr, ptr, layout);
356}
357
358static void panel_register(ARegionType *region_type)
359{
363 region_type, "falloff", "Falloff", nullptr, falloff_panel_draw, panel_type);
365 region_type, "influence", "Influence", nullptr, influence_panel_draw, panel_type);
366}
367
368static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
369{
370 const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md;
371
373
374 if (wmd->cmap_curve) {
376 }
377}
378
379static void blend_read(BlendDataReader *reader, ModifierData *md)
380{
382
384 if (wmd->cmap_curve) {
386 }
387}
388
390 /*idname*/ "VertexWeightEdit",
391 /*name*/ N_("VertexWeightEdit"),
392 /*struct_name*/ "WeightVGEditModifierData",
393 /*struct_size*/ sizeof(WeightVGEditModifierData),
394 /*srna*/ &RNA_VertexWeightEditModifier,
398 /*icon*/ ICON_MOD_VERTEX_WEIGHT,
399
400 /*copy_data*/ copy_data,
401
402 /*deform_verts*/ nullptr,
403 /*deform_matrices*/ nullptr,
404 /*deform_verts_EM*/ nullptr,
405 /*deform_matrices_EM*/ nullptr,
406 /*modify_mesh*/ modify_mesh,
407 /*modify_geometry_set*/ nullptr,
408
409 /*init_data*/ init_data,
410 /*required_data_mask*/ required_data_mask,
411 /*free_data*/ free_data,
412 /*is_disabled*/ is_disabled,
413 /*update_depsgraph*/ update_depsgraph,
414 /*depends_on_time*/ depends_on_time,
415 /*depends_on_normals*/ nullptr,
416 /*foreach_ID_link*/ foreach_ID_link,
417 /*foreach_tex_link*/ foreach_tex_link,
418 /*free_runtime_data*/ nullptr,
419 /*panel_register*/ panel_register,
420 /*blend_write*/ blend_write,
421 /*blend_read*/ blend_read,
422 /*foreach_cache*/ nullptr,
423};
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
CurveMapping * BKE_curvemapping_copy(const CurveMapping *cumap)
void BKE_curvemapping_init(CurveMapping *cumap)
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition colortools.cc:90
void BKE_curvemapping_free(CurveMapping *cumap)
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:543
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
void(*)(void *user_data, Object *ob, ModifierData *md, const PointerRNA *ptr, PropertyRNA *texture_prop) TexWalkFunc
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
bool BKE_texture_dependsOnTime(const struct Tex *texture)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_ghashutil_strhash(key)
Definition BLI_ghash.h:574
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition rand.cc:46
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define IFACE_(msgid)
void DEG_add_generic_id_relation(DepsNodeHandle *node_handle, ID *id, const char *description)
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MTFACE
@ CD_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ MOD_WVG_EDIT_INVERT_VGROUP_MASK
@ MOD_WVG_EDIT_WEIGHTS_NORMALIZE
@ MOD_WVG_INVERT_FALLOFF
@ MOD_WVG_EDIT_REMFVG
@ MOD_WVG_EDIT_ADD2VG
struct WeightVGEditModifierData WeightVGEditModifierData
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_GLOBAL
@ MOD_DISP_MAP_UV
@ eModifierType_WeightVGEdit
@ MOD_WVG_MAPPING_NONE
@ MOD_WVG_MAPPING_CURVE
@ MOD_WVG_MAPPING_RANDOM
Object is a sort of wrapper for general info.
static bool is_disabled
Read Guarded memory(de)allocation.
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void MOD_depsgraph_update_object_bone_relation(DepsNodeHandle *node, Object *object, const char *bonename, const char *description)
Definition MOD_util.cc:189
void weightvg_do_map(int num, float *new_w, short falloff_type, const bool do_invert, CurveMapping *cmap, RNG *rng)
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num, const int *indices, const float *weights, const bool do_add, const float add_thresh, const bool do_rem, const float rem_thresh, const bool do_normalize)
void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout)
void weightvg_do_mask(const ModifierEvalContext *ctx, const int num, const int *indices, float *org_w, const float *new_w, Object *ob, Mesh *mesh, const float fact, const char defgrp_name[MAX_VGROUP_NAME], Scene *, Tex *texture, const int tex_use_channel, const int tex_mapping, Object *tex_map_object, const char *text_map_bone, const char *tex_uvlayer_name, const bool invert_vgroup_mask)
static void influence_panel_draw(const bContext *C, Panel *panel)
static void init_data(ModifierData *md)
ModifierTypeInfo modifierType_WeightVGEdit
static void falloff_panel_draw(const bContext *, Panel *panel)
static void panel_register(ARegionType *region_type)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void free_data(ModifierData *md)
static void blend_read(BlendDataReader *reader, ModifierData *md)
static bool depends_on_time(Scene *, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
uiLayout * uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SLIDER
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
struct uiLayout * layout
Definition rand.cc:33
struct CurveMapping * cmap_curve
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138