Blender  V3.3
MOD_weightvgedit.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 by Bastien Montagne. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "BLI_utildefines.h"
11 
12 #include "BLI_ghash.h"
13 #include "BLI_listbase.h"
14 #include "BLI_rand.h"
15 
16 #include "BLT_translation.h"
17 
18 #include "DNA_color_types.h" /* CurveMapping. */
19 #include "DNA_defaults.h"
20 #include "DNA_mesh_types.h"
21 #include "DNA_meshdata_types.h"
22 #include "DNA_modifier_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_screen_types.h"
25 
26 #include "BKE_colortools.h" /* CurveMapping. */
27 #include "BKE_context.h"
28 #include "BKE_deform.h"
29 #include "BKE_lib_query.h"
30 #include "BKE_modifier.h"
31 #include "BKE_screen.h"
32 #include "BKE_texture.h" /* Texture masking. */
33 
34 #include "UI_interface.h"
35 #include "UI_resources.h"
36 
37 #include "BLO_read_write.h"
38 
39 #include "RNA_access.h"
40 #include "RNA_prototypes.h"
41 
42 #include "DEG_depsgraph_build.h"
43 #include "DEG_depsgraph_query.h"
44 
45 #include "MEM_guardedalloc.h"
46 
47 #include "MOD_modifiertypes.h"
48 #include "MOD_ui_common.h"
49 #include "MOD_util.h"
50 #include "MOD_weightvg_util.h"
51 
52 /**************************************
53  * Modifiers functions. *
54  **************************************/
55 static void initData(ModifierData *md)
56 {
58 
60 
62 
63  wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
65 }
66 
67 static void freeData(ModifierData *md)
68 {
71 }
72 
73 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
74 {
75  const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md;
77 
78  BKE_modifier_copydata_generic(md, target, flag);
79 
81 }
82 
83 static void requiredDataMask(Object *UNUSED(ob),
84  ModifierData *md,
85  CustomData_MeshMasks *r_cddata_masks)
86 {
88 
89  /* We need vertex groups! */
90  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
91 
92  /* Ask for UV coordinates if we need them. */
93  if (wmd->mask_tex_mapping == MOD_DISP_MAP_UV) {
94  r_cddata_masks->fmask |= CD_MASK_MTFACE;
95  }
96 
97  /* No need to ask for CD_PREVIEW_MLOOPCOL... */
98 }
99 
100 static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
101 {
103 
104  if (wmd->mask_texture) {
106  }
107  return false;
108 }
109 
110 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
111 {
113 
114  walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
115  walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP);
116 }
117 
118 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
119 {
120  walk(userData, ob, md, "mask_texture");
121 }
122 
124 {
126  bool need_transform_relation = false;
127 
128  if (wmd->mask_texture != NULL) {
129  DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGEdit Modifier");
130 
133  ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGEdit Modifier");
134  need_transform_relation = true;
135  }
136  else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
137  need_transform_relation = true;
138  }
139  }
140 
141  if (need_transform_relation) {
142  DEG_add_modifier_to_transform_relation(ctx->node, "WeightVGEdit Modifier");
143  }
144 }
145 
146 static bool isDisabled(const struct Scene *UNUSED(scene),
147  ModifierData *md,
148  bool UNUSED(useRenderParams))
149 {
151  /* If no vertex group, bypass. */
152  return (wmd->defgrp_name[0] == '\0');
153 }
154 
156 {
157  BLI_assert(mesh != NULL);
158 
160 
161  MDeformVert *dvert = NULL;
162  MDeformWeight **dw = NULL;
163  float *org_w; /* Array original weights. */
164  float *new_w; /* Array new weights. */
165  int i;
166  const bool invert_vgroup_mask = (wmd->edit_flags & MOD_WVG_EDIT_INVERT_VGROUP_MASK) != 0;
167 
168  /* Flags. */
169  const bool do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
170  const bool do_rem = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
171  /* Only do weight-preview in Object, Sculpt and Pose modes! */
172 #if 0
173  const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview);
174 #endif
175 
176  /* Get number of verts. */
177  const int verts_num = mesh->totvert;
178 
179  /* Check if we can just return the original mesh.
180  * Must have verts and therefore verts assigned to vgroups to do anything useful!
181  */
182  if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
183  return mesh;
184  }
185 
186  /* Get vgroup idx from its name. */
187  const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name);
188  if (defgrp_index == -1) {
189  return mesh;
190  }
191 
192  const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT);
193  /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
194  if (!has_mdef) {
195  /* If this modifier is not allowed to add vertices, just return. */
196  if (!do_add) {
197  return mesh;
198  }
199  }
200 
201  if (has_mdef) {
203  }
204  else {
205  /* Add a valid data layer! */
206  dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num);
207  }
208  /* Ultimate security check. */
209  if (!dvert) {
210  return mesh;
211  }
212  mesh->dvert = dvert;
213 
214  /* Get org weights, assuming 0.0 for vertices not in given vgroup. */
215  org_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, org_w");
216  new_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, new_w");
217  dw = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGEdit Modifier, dw");
218  for (i = 0; i < verts_num; i++) {
219  dw[i] = BKE_defvert_find_index(&dvert[i], defgrp_index);
220  if (dw[i]) {
221  org_w[i] = new_w[i] = dw[i]->weight;
222  }
223  else {
224  org_w[i] = new_w[i] = wmd->default_weight;
225  }
226  }
227 
228  /* Do mapping. */
229  const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0;
230  const bool do_normalize = (wmd->edit_flags & MOD_WVG_EDIT_WEIGHTS_NORMALIZE) != 0;
231  if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
232  RNG *rng = NULL;
233 
234  if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM) {
236  }
237 
238  weightvg_do_map(verts_num, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng);
239 
240  if (rng) {
241  BLI_rng_free(rng);
242  }
243  }
244 
245  /* Do masking. */
247  weightvg_do_mask(ctx,
248  verts_num,
249  NULL,
250  org_w,
251  new_w,
252  ctx->object,
253  mesh,
254  wmd->mask_constant,
255  wmd->mask_defgrp_name,
256  scene,
257  wmd->mask_texture,
259  wmd->mask_tex_mapping,
260  wmd->mask_tex_map_obj,
261  wmd->mask_tex_map_bone,
263  invert_vgroup_mask);
264 
265  /* Update/add/remove from vgroup. */
266  weightvg_update_vg(dvert,
267  defgrp_index,
268  dw,
269  verts_num,
270  NULL,
271  org_w,
272  do_add,
273  wmd->add_threshold,
274  do_rem,
275  wmd->rem_threshold,
276  do_normalize);
277 
278  /* If weight preview enabled... */
279 #if 0 /* XXX Currently done in mod stack :/ */
280  if (do_prev) {
281  DM_update_weight_mcol(ob, dm, 0, org_w, 0, NULL);
282  }
283 #endif
284 
285  /* Freeing stuff. */
286  MEM_freeN(org_w);
287  MEM_freeN(new_w);
288  MEM_freeN(dw);
289 
290  mesh->runtime.is_original = false;
291 
292  /* Return the vgroup-modified mesh. */
293  return mesh;
294 }
295 
296 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
297 {
298  uiLayout *sub, *col, *row;
299  uiLayout *layout = panel->layout;
300 
301  PointerRNA ob_ptr;
303 
304  uiLayoutSetPropSep(layout, true);
305 
306  col = uiLayoutColumn(layout, true);
307  uiItemPointerR(col, ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
308 
309  uiItemR(layout, ptr, "default_weight", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
310 
311  col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Add"));
312  row = uiLayoutRow(col, true);
313  uiLayoutSetPropDecorate(row, false);
314  sub = uiLayoutRow(row, true);
315  uiItemR(sub, ptr, "use_add", 0, "", ICON_NONE);
316  sub = uiLayoutRow(sub, true);
317  uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_add"));
318  uiLayoutSetPropSep(sub, false);
319  uiItemR(sub, ptr, "add_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
320  uiItemDecoratorR(row, ptr, "add_threshold", 0);
321 
322  col = uiLayoutColumnWithHeading(layout, false, IFACE_("Group Remove"));
323  row = uiLayoutRow(col, true);
324  uiLayoutSetPropDecorate(row, false);
325  sub = uiLayoutRow(row, true);
326  uiItemR(sub, ptr, "use_remove", 0, "", ICON_NONE);
327  sub = uiLayoutRow(sub, true);
328  uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_remove"));
329  uiLayoutSetPropSep(sub, false);
330  uiItemR(sub, ptr, "remove_threshold", UI_ITEM_R_SLIDER, IFACE_("Threshold"), ICON_NONE);
331  uiItemDecoratorR(row, ptr, "remove_threshold", 0);
332 
333  uiItemR(layout, ptr, "normalize", 0, NULL, ICON_NONE);
334 
335  modifier_panel_end(layout, ptr);
336 }
337 
338 static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
339 {
340  uiLayout *row, *sub;
341  uiLayout *layout = panel->layout;
342 
343  PointerRNA ob_ptr;
345 
346  uiLayoutSetPropSep(layout, true);
347 
348  row = uiLayoutRow(layout, true);
349  uiItemR(row, ptr, "falloff_type", 0, IFACE_("Type"), ICON_NONE);
350  sub = uiLayoutRow(row, true);
351  uiLayoutSetPropSep(sub, false);
352  uiItemR(row, ptr, "invert_falloff", 0, "", ICON_ARROW_LEFTRIGHT);
353  if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) {
354  uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false);
355  }
356 }
357 
358 static void influence_panel_draw(const bContext *C, Panel *panel)
359 {
360  uiLayout *layout = panel->layout;
361 
362  PointerRNA ob_ptr;
364 
365  weightvg_ui_common(C, &ob_ptr, ptr, layout);
366 }
367 
368 static void panelRegister(ARegionType *region_type)
369 {
370  PanelType *panel_type = modifier_panel_register(
371  region_type, eModifierType_WeightVGEdit, panel_draw);
373  region_type, "falloff", "Falloff", NULL, falloff_panel_draw, panel_type);
375  region_type, "influence", "Influence", NULL, influence_panel_draw, panel_type);
376 }
377 
378 static void blendWrite(BlendWriter *writer, const ID *UNUSED(id_owner), const ModifierData *md)
379 {
380  const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md;
381 
383 
384  if (wmd->cmap_curve) {
386  }
387 }
388 
389 static void blendRead(BlendDataReader *reader, ModifierData *md)
390 {
392 
393  BLO_read_data_address(reader, &wmd->cmap_curve);
394  if (wmd->cmap_curve) {
396  }
397 }
398 
400  /* name */ N_("VertexWeightEdit"),
401  /* structName */ "WeightVGEditModifierData",
402  /* structSize */ sizeof(WeightVGEditModifierData),
403  /* srna */ &RNA_VertexWeightEditModifier,
407  /* icon */ ICON_MOD_VERTEX_WEIGHT,
408 
409  /* copyData */ copyData,
410 
411  /* deformVerts */ NULL,
412  /* deformMatrices */ NULL,
413  /* deformVertsEM */ NULL,
414  /* deformMatricesEM */ NULL,
415  /* modifyMesh */ modifyMesh,
416  /* modifyGeometrySet */ NULL,
417 
418  /* initData */ initData,
419  /* requiredDataMask */ requiredDataMask,
420  /* freeData */ freeData,
421  /* isDisabled */ isDisabled,
422  /* updateDepsgraph */ updateDepsgraph,
423  /* dependsOnTime */ dependsOnTime,
424  /* dependsOnNormals */ NULL,
425  /* foreachIDLink */ foreachIDLink,
426  /* foreachTexLink */ foreachTexLink,
427  /* freeRuntimeData */ NULL,
428  /* panelRegister */ panelRegister,
429  /* blendWrite */ blendWrite,
430  /* blendRead */ blendRead,
431 };
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
struct CurveMapping * BKE_curvemapping_copy(const struct CurveMapping *cumap)
void BKE_curvemapping_blend_read(struct BlendDataReader *reader, struct CurveMapping *cumap)
Definition: colortools.c:1300
void BKE_curvemapping_blend_write(struct BlendWriter *writer, const struct CurveMapping *cumap)
void BKE_curvemapping_free(struct CurveMapping *cumap)
Definition: colortools.c:103
struct CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition: colortools.c:72
@ CD_CALLOC
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void * CustomData_duplicate_referenced_layer(struct CustomData *data, int type, int totelem)
Definition: customdata.cc:2976
support for deformation groups and hooks.
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, int defgroup)
int BKE_id_defgroup_name_index(const struct ID *id, const char *name)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:68
@ eModifierTypeFlag_UsesPreview
Definition: BKE_modifier.h:99
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void(* TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname)
Definition: BKE_modifier.h:108
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_NonGeometrical
Definition: BKE_modifier.h:62
bool BKE_texture_dependsOnTime(const struct Tex *texture)
Definition: texture.c:670
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_ghashutil_strhash(key)
Definition: BLI_ghash.h:573
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
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 UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define IFACE_(msgid)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle, struct ID *id, const char *description)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MTFACE
@ CD_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ 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
@ eModifierType_WeightVGEdit
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_GLOBAL
@ MOD_DISP_MAP_UV
@ MOD_WVG_MAPPING_NONE
@ MOD_WVG_MAPPING_CURVE
@ MOD_WVG_MAPPING_RANDOM
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void MOD_depsgraph_update_object_bone_relation(struct DepsNodeHandle *node, Object *object, const char *bonename, const char *description)
Definition: MOD_util.c:258
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_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 *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)
void weightvg_ui_common(const bContext *C, PointerRNA *ob_ptr, PointerRNA *ptr, uiLayout *layout)
static void influence_panel_draw(const bContext *C, Panel *panel)
ModifierTypeInfo modifierType_WeightVGEdit
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
static void blendRead(BlendDataReader *reader, ModifierData *md)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
static void blendWrite(BlendWriter *writer, const ID *UNUSED(id_owner), const ModifierData *md)
static void freeData(ModifierData *md)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
#define C
Definition: RandGen.cpp:25
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemDecoratorR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int index)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
Scene scene
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
CustomData vdata
struct MDeformVert * dvert
ListBase vertex_group_names
int totvert
Mesh_Runtime runtime
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
struct uiLayout * layout
Definition: rand.cc:33
struct CurveMapping * cmap_curve
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480