Blender V4.5
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
8
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#include "DNA_texture_types.h"
27
28#include "BKE_colortools.hh" /* CurveMapping. */
29#include "BKE_customdata.hh"
30#include "BKE_deform.hh"
31#include "BKE_lib_query.hh"
32#include "BKE_mesh.hh"
33#include "BKE_modifier.hh"
34#include "BKE_texture.h" /* Texture masking. */
35
36#include "UI_interface.hh"
37#include "UI_resources.hh"
38
39#include "BLO_read_write.hh"
40
41#include "RNA_access.hh"
42#include "RNA_prototypes.hh"
43
46
47#include "MEM_guardedalloc.h"
48
49#include "MOD_ui_common.hh"
50#include "MOD_util.hh"
51#include "MOD_weightvg_util.hh"
52
53/**************************************
54 * Modifiers functions. *
55 **************************************/
67
73
74static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
75{
78
80
82}
83
84static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
85{
87
88 /* We need vertex groups! */
89 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
90
91 /* Ask for UV coordinates if we need them. */
93 r_cddata_masks->fmask |= CD_MASK_MTFACE;
94 }
95}
96
97static bool depends_on_time(Scene * /*scene*/, ModifierData *md)
98{
100
101 if (wmd->mask_texture) {
103 }
104 return false;
105}
106
107static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
108{
110
111 walk(user_data, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
112 walk(user_data, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP);
113}
114
115static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
116{
117 PointerRNA ptr = RNA_pointer_create_discrete(&ob->id, &RNA_Modifier, md);
118 PropertyRNA *prop = RNA_struct_find_property(&ptr, "mask_texture");
119 walk(user_data, ob, md, &ptr, prop);
120}
121
123{
125 bool need_transform_relation = false;
126
127 if (wmd->mask_texture != nullptr) {
128 DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGEdit Modifier");
129
130 if (wmd->mask_tex_map_obj != nullptr && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
132 ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGEdit Modifier");
133 need_transform_relation = true;
134 }
135 else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
136 need_transform_relation = true;
137 }
138 }
139
140 if (need_transform_relation) {
141 DEG_add_depends_on_transform_relation(ctx->node, "WeightVGEdit Modifier");
142 }
143}
144
145static bool is_disabled(const Scene * /*scene*/, ModifierData *md, bool /*use_render_params*/)
146{
148 /* If no vertex group, bypass. */
149 return (wmd->defgrp_name[0] == '\0');
150}
151
152static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
153{
154 BLI_assert(mesh != nullptr);
155
157
158 MDeformWeight **dw = nullptr;
159 float *org_w; /* Array original weights. */
160 float *new_w; /* Array new weights. */
161 int i;
162 const bool invert_vgroup_mask = (wmd->edit_flags & MOD_WVG_EDIT_INVERT_VGROUP_MASK) != 0;
163
164 /* Flags. */
165 const bool do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
166 const bool do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
167 /* Only do weight-preview in Object, Sculpt and Pose modes! */
168#if 0
169 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
170#endif
171
172 /* Get number of verts. */
173 const int verts_num = mesh->verts_num;
174
175 /* Check if we can just return the original mesh.
176 * Must have verts and therefore verts assigned to vgroups to do anything useful!
177 */
178 if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
179 return mesh;
180 }
181
182 /* Get vgroup idx from its name. */
183 const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
184 if (defgrp_index == -1) {
185 return mesh;
186 }
187
188 const bool has_mdef = CustomData_has_layer(&mesh->vert_data, CD_MDEFORMVERT);
189 /* If no vertices were ever added to an object's vgroup, dvert might be nullptr. */
190 if (!has_mdef) {
191 /* If this modifier is not allowed to add vertices, just return. */
192 if (!do_add) {
193 return mesh;
194 }
195 }
196
197 MDeformVert *dvert = mesh->deform_verts_for_write().data();
198
199 /* Ultimate security check. */
200 if (!dvert) {
201 return mesh;
202 }
203
204 /* Get org weights, assuming 0.0 for vertices not in given vgroup. */
205 org_w = MEM_malloc_arrayN<float>(size_t(verts_num), __func__);
206 new_w = MEM_malloc_arrayN<float>(size_t(verts_num), __func__);
207 dw = MEM_malloc_arrayN<MDeformWeight *>(size_t(verts_num), __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 = &layout->column(true);
298 col, ptr, "vertex_group", &ob_ptr, "vertex_groups", std::nullopt, ICON_GROUP_VERTEX);
299
300 layout->prop(ptr, "default_weight", UI_ITEM_R_SLIDER, std::nullopt, ICON_NONE);
301
302 col = &layout->column(false, IFACE_("Group Add"));
303 row = &col->row(true);
304 uiLayoutSetPropDecorate(row, false);
305 sub = &row->row(true);
306 sub->prop(ptr, "use_add", UI_ITEM_NONE, "", ICON_NONE);
307 sub = &sub->row(true);
308 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_add"));
309 uiLayoutSetPropSep(sub, false);
310 sub->prop(ptr, "add_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
311 uiItemDecoratorR(row, ptr, "add_threshold", 0);
312
313 col = &layout->column(false, IFACE_("Group Remove"));
314 row = &col->row(true);
315 uiLayoutSetPropDecorate(row, false);
316 sub = &row->row(true);
317 sub->prop(ptr, "use_remove", UI_ITEM_NONE, "", ICON_NONE);
318 sub = &sub->row(true);
319 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_remove"));
320 uiLayoutSetPropSep(sub, false);
321 sub->prop(ptr, "remove_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
322 uiItemDecoratorR(row, ptr, "remove_threshold", 0);
323
324 layout->prop(ptr, "normalize", UI_ITEM_NONE, std::nullopt, ICON_NONE);
325
327}
328
329static void falloff_panel_draw(const bContext * /*C*/, Panel *panel)
330{
331 uiLayout *row, *sub;
332 uiLayout *layout = panel->layout;
333
334 PointerRNA ob_ptr;
336
337 uiLayoutSetPropSep(layout, true);
338
339 row = &layout->row(true);
340 row->prop(ptr, "falloff_type", UI_ITEM_NONE, IFACE_("Type"), ICON_NONE);
341 sub = &row->row(true);
342 uiLayoutSetPropSep(sub, false);
343 row->prop(ptr, "invert_falloff", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
344 if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) {
345 uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false);
346 }
347}
348
349static void influence_panel_draw(const bContext *C, Panel *panel)
350{
351 uiLayout *layout = panel->layout;
352
353 PointerRNA ob_ptr;
355
356 weightvg_ui_common(C, &ob_ptr, ptr, layout);
357}
358
359static void panel_register(ARegionType *region_type)
360{
364 region_type, "falloff", "Falloff", nullptr, falloff_panel_draw, panel_type);
366 region_type, "influence", "Influence", nullptr, influence_panel_draw, panel_type);
367}
368
369static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
370{
371 const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md;
372
374
375 if (wmd->cmap_curve) {
377 }
378}
379
380static void blend_read(BlendDataReader *reader, ModifierData *md)
381{
383
385 if (wmd->cmap_curve) {
387 }
388}
389
391 /*idname*/ "VertexWeightEdit",
392 /*name*/ N_("VertexWeightEdit"),
393 /*struct_name*/ "WeightVGEditModifierData",
394 /*struct_size*/ sizeof(WeightVGEditModifierData),
395 /*srna*/ &RNA_VertexWeightEditModifier,
399 /*icon*/ ICON_MOD_VERTEX_WEIGHT,
400
401 /*copy_data*/ copy_data,
402
403 /*deform_verts*/ nullptr,
404 /*deform_matrices*/ nullptr,
405 /*deform_verts_EM*/ nullptr,
406 /*deform_matrices_EM*/ nullptr,
407 /*modify_mesh*/ modify_mesh,
408 /*modify_geometry_set*/ nullptr,
409
410 /*init_data*/ init_data,
411 /*required_data_mask*/ required_data_mask,
412 /*free_data*/ free_data,
413 /*is_disabled*/ is_disabled,
414 /*update_depsgraph*/ update_depsgraph,
415 /*depends_on_time*/ depends_on_time,
416 /*depends_on_normals*/ nullptr,
417 /*foreach_ID_link*/ foreach_ID_link,
418 /*foreach_tex_link*/ foreach_tex_link,
419 /*free_runtime_data*/ nullptr,
420 /*panel_register*/ panel_register,
421 /*blend_write*/ blend_write,
422 /*blend_read*/ blend_read,
423 /*foreach_cache*/ nullptr,
424};
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:89
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:538
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
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
bool BKE_texture_dependsOnTime(const struct Tex *texture)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_ghashutil_strhash(key)
Definition BLI_ghash.h:570
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:53
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)
@ CD_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_GLOBAL
@ MOD_DISP_MAP_UV
@ MOD_WVG_MAPPING_NONE
@ MOD_WVG_MAPPING_CURVE
@ MOD_WVG_MAPPING_RANDOM
@ eModifierType_WeightVGEdit
@ MOD_WVG_EDIT_INVERT_VGROUP_MASK
@ MOD_WVG_EDIT_WEIGHTS_NORMALIZE
@ MOD_WVG_INVERT_FALLOFF
@ MOD_WVG_EDIT_REMFVG
@ MOD_WVG_EDIT_ADD2VG
Object is a sort of wrapper for general info.
static bool is_disabled
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void blend_read(BlendDataReader *, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:271
static void blend_write(BlendWriter *writer, const ID *, const ModifierData *md)
Definition MOD_bevel.cc:433
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_build.cc:47
static void foreach_tex_link(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
static void falloff_panel_draw(const bContext *, Panel *panel)
Definition MOD_hook.cc:484
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
void MOD_depsgraph_update_object_bone_relation(DepsNodeHandle *node, Object *object, const char *bonename, const char *description)
Definition MOD_util.cc:186
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)
#define C
Definition RandGen.cpp:29
void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
@ UI_ITEM_R_SLIDER
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *searchptr, blender::StringRefNull searchpropname, std::optional< blender::StringRefNull > name, int icon)
void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, std::optional< blender::StringRefNull > propname, int index)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uint col
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MTFACE
static void update_depsgraph(tGraphSliderOp *gso)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
MeshRuntimeHandle * runtime
ListBase vertex_group_names
CustomData vert_data
int verts_num
struct uiLayout * layout
Definition rand.cc:33
struct CurveMapping * cmap_curve
uiLayout & column(bool align)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4226
uint8_t flag
Definition wm_window.cc:139