Blender  V3.3
MOD_weightvgmix.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 "BLI_utildefines.h"
9 
10 #include "BLI_listbase.h"
11 #include "BLI_math.h"
12 
13 #include "BLT_translation.h"
14 
15 #include "DNA_defaults.h"
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 #include "DNA_modifier_types.h"
19 #include "DNA_object_types.h"
20 #include "DNA_screen_types.h"
21 
22 #include "BKE_context.h"
23 #include "BKE_customdata.h"
24 #include "BKE_deform.h"
25 #include "BKE_lib_query.h"
26 #include "BKE_modifier.h"
27 #include "BKE_screen.h"
28 #include "BKE_texture.h" /* Texture masking. */
29 
30 #include "UI_interface.h"
31 #include "UI_resources.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_prototypes.h"
35 
36 #include "DEG_depsgraph_build.h"
37 #include "DEG_depsgraph_query.h"
38 
39 #include "MEM_guardedalloc.h"
40 
41 #include "MOD_modifiertypes.h"
42 #include "MOD_ui_common.h"
43 #include "MOD_util.h"
44 #include "MOD_weightvg_util.h"
45 
49 static float mix_weight(float weight, float weight2, char mix_mode)
50 {
51 #if 0
52  /*
53  * XXX Don't know why, but the switch version takes many CPU time,
54  * and produces lag in realtime playback...
55  */
56  switch (mix_mode) {
57  case MOD_WVG_MIX_ADD:
58  return (weight + weight2);
59  case MOD_WVG_MIX_SUB:
60  return (weight - weight2);
61  case MOD_WVG_MIX_MUL:
62  return (weight * weight2);
63  case MOD_WVG_MIX_DIV:
64  /* Avoid dividing by zero (or really small values). */
65  if (0.0 <= weight2 < MOD_WVG_ZEROFLOOR) {
66  weight2 = MOD_WVG_ZEROFLOOR;
67  }
68  else if (-MOD_WVG_ZEROFLOOR < weight2) {
69  weight2 = -MOD_WVG_ZEROFLOOR;
70  }
71  return (weight / weight2);
72  case MOD_WVG_MIX_DIF:
73  return (weight < weight2 ? weight2 - weight : weight - weight2);
74  case MOD_WVG_MIX_AVG:
75  return (weight + weight2) / 2.0;
76  case MOD_WVG_MIX_SET:
77  default:
78  return weight2;
79  }
80 #endif
81  if (mix_mode == MOD_WVG_MIX_SET) {
82  return weight2;
83  }
84  if (mix_mode == MOD_WVG_MIX_ADD) {
85  return (weight + weight2);
86  }
87  if (mix_mode == MOD_WVG_MIX_SUB) {
88  return (weight - weight2);
89  }
90  if (mix_mode == MOD_WVG_MIX_MUL) {
91  return (weight * weight2);
92  }
93  if (mix_mode == MOD_WVG_MIX_DIV) {
94  /* Avoid dividing by zero (or really small values). */
95  if (weight2 < 0.0f && weight2 > -MOD_WVG_ZEROFLOOR) {
96  weight2 = -MOD_WVG_ZEROFLOOR;
97  }
98  else if (weight2 >= 0.0f && weight2 < MOD_WVG_ZEROFLOOR) {
99  weight2 = MOD_WVG_ZEROFLOOR;
100  }
101  return (weight / weight2);
102  }
103  if (mix_mode == MOD_WVG_MIX_DIF) {
104  return (weight < weight2 ? weight2 - weight : weight - weight2);
105  }
106  if (mix_mode == MOD_WVG_MIX_AVG) {
107  return (weight + weight2) * 0.5f;
108  }
109  if (mix_mode == MOD_WVG_MIX_MIN) {
110  return (weight < weight2 ? weight : weight2);
111  }
112  if (mix_mode == MOD_WVG_MIX_MAX) {
113  return (weight > weight2 ? weight : weight2);
114  }
115 
116  return weight2;
117 }
118 
119 /**************************************
120  * Modifiers functions. *
121  **************************************/
122 static void initData(ModifierData *md)
123 {
125 
126  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
127 
129 }
130 
131 static void requiredDataMask(Object *UNUSED(ob),
132  ModifierData *md,
133  CustomData_MeshMasks *r_cddata_masks)
134 {
136 
137  /* We need vertex groups! */
138  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
139 
140  /* Ask for UV coordinates if we need them. */
141  if (wmd->mask_tex_mapping == MOD_DISP_MAP_UV) {
142  r_cddata_masks->fmask |= CD_MASK_MTFACE;
143  }
144 
145  /* No need to ask for CD_PREVIEW_MLOOPCOL... */
146 }
147 
148 static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
149 {
151 
152  if (wmd->mask_texture) {
154  }
155  return false;
156 }
157 
158 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
159 {
161 
162  walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
163  walk(userData, ob, (ID **)&wmd->mask_tex_map_obj, IDWALK_CB_NOP);
164 }
165 
166 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
167 {
168  walk(userData, ob, md, "mask_texture");
169 }
170 
172 {
174  bool need_transform_relation = false;
175 
176  if (wmd->mask_texture != NULL) {
177  DEG_add_generic_id_relation(ctx->node, &wmd->mask_texture->id, "WeightVGMix Modifier");
178 
181  ctx->node, wmd->mask_tex_map_obj, wmd->mask_tex_map_bone, "WeightVGMix Modifier");
182  need_transform_relation = true;
183  }
184  else if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) {
185  need_transform_relation = true;
186  }
187  }
188 
189  if (need_transform_relation) {
190  DEG_add_modifier_to_transform_relation(ctx->node, "WeightVGMix Modifier");
191  }
192 }
193 
194 static bool isDisabled(const struct Scene *UNUSED(scene),
195  ModifierData *md,
196  bool UNUSED(useRenderParams))
197 {
199  /* If no vertex group, bypass. */
200  return (wmd->defgrp_name_a[0] == '\0');
201 }
202 
204 {
205  BLI_assert(mesh != NULL);
206 
208 
209  MDeformVert *dvert = NULL;
210  MDeformWeight **dw1, **tdw1, **dw2, **tdw2;
211  float *org_w;
212  float *new_w;
213  int *tidx, *indices = NULL;
214  int index_num = 0;
215  int i;
216  const bool invert_vgroup_mask = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_MASK) != 0;
217  const bool do_normalize = (wmd->flag & MOD_WVG_MIX_WEIGHTS_NORMALIZE) != 0;
218 
219  /*
220  * Note that we only invert the weight values within provided vgroups, the selection based on
221  * which vertex is affected because it belongs or not to a group remains unchanged.
222  * In other words, vertices not belonging to a group won't be affected, even though their
223  * inverted 'virtual' weight would be 1.0f.
224  */
225  const bool invert_vgroup_a = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_A) != 0;
226  const bool invert_vgroup_b = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_B) != 0;
227 
228  /* Flags. */
229 #if 0
230  const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0;
231 #endif
232 
233  /* Get number of verts. */
234  const int verts_num = mesh->totvert;
235 
236  /* Check if we can just return the original mesh.
237  * Must have verts and therefore verts assigned to vgroups to do anything useful!
238  */
239  if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
240  return mesh;
241  }
242 
243  /* Get vgroup idx from its name. */
244  const int defgrp_index = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_a);
245  if (defgrp_index == -1) {
246  return mesh;
247  }
248  /* Get second vgroup idx from its name, if given. */
249  int defgrp_index_other = -1;
250  if (wmd->defgrp_name_b[0] != '\0') {
251  defgrp_index_other = BKE_id_defgroup_name_index(&mesh->id, wmd->defgrp_name_b);
252  if (defgrp_index_other == -1) {
253  return mesh;
254  }
255  }
256 
257  const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT);
258  /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
259  if (!has_mdef) {
260  /* If not affecting all vertices, just return. */
261  if (wmd->mix_set != MOD_WVG_SET_ALL) {
262  return mesh;
263  }
264  }
265 
266  if (has_mdef) {
268  }
269  else {
270  /* Add a valid data layer! */
271  dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num);
272  }
273  /* Ultimate security check. */
274  if (!dvert) {
275  return mesh;
276  }
277  mesh->dvert = dvert;
278 
279  /* Find out which vertices to work on. */
280  tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGMix Modifier, tidx");
281  tdw1 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1");
282  tdw2 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2");
283  switch (wmd->mix_set) {
284  case MOD_WVG_SET_A:
285  /* All vertices in first vgroup. */
286  for (i = 0; i < verts_num; i++) {
287  MDeformWeight *dw = BKE_defvert_find_index(&dvert[i], defgrp_index);
288  if (dw) {
289  tdw1[index_num] = dw;
290  tdw2[index_num] = (defgrp_index_other >= 0) ?
291  BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
292  NULL;
293  tidx[index_num++] = i;
294  }
295  }
296  break;
297  case MOD_WVG_SET_B:
298  /* All vertices in second vgroup. */
299  for (i = 0; i < verts_num; i++) {
300  MDeformWeight *dw = (defgrp_index_other >= 0) ?
301  BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
302  NULL;
303  if (dw) {
304  tdw1[index_num] = BKE_defvert_find_index(&dvert[i], defgrp_index);
305  tdw2[index_num] = dw;
306  tidx[index_num++] = i;
307  }
308  }
309  break;
310  case MOD_WVG_SET_OR:
311  /* All vertices in one vgroup or the other. */
312  for (i = 0; i < verts_num; i++) {
313  MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index);
314  MDeformWeight *bdw = (defgrp_index_other >= 0) ?
315  BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
316  NULL;
317  if (adw || bdw) {
318  tdw1[index_num] = adw;
319  tdw2[index_num] = bdw;
320  tidx[index_num++] = i;
321  }
322  }
323  break;
324  case MOD_WVG_SET_AND:
325  /* All vertices in both vgroups. */
326  for (i = 0; i < verts_num; i++) {
327  MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index);
328  MDeformWeight *bdw = (defgrp_index_other >= 0) ?
329  BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
330  NULL;
331  if (adw && bdw) {
332  tdw1[index_num] = adw;
333  tdw2[index_num] = bdw;
334  tidx[index_num++] = i;
335  }
336  }
337  break;
338  case MOD_WVG_SET_ALL:
339  default:
340  /* Use all vertices. */
341  for (i = 0; i < verts_num; i++) {
342  tdw1[i] = BKE_defvert_find_index(&dvert[i], defgrp_index);
343  tdw2[i] = (defgrp_index_other >= 0) ?
344  BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
345  NULL;
346  }
347  index_num = -1;
348  break;
349  }
350  if (index_num == 0) {
351  /* Use no vertices! Hence, return org data. */
352  MEM_freeN(tdw1);
353  MEM_freeN(tdw2);
354  MEM_freeN(tidx);
355  return mesh;
356  }
357  if (index_num != -1) {
358  indices = MEM_malloc_arrayN(index_num, sizeof(int), "WeightVGMix Modifier, indices");
359  memcpy(indices, tidx, sizeof(int) * index_num);
360  dw1 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1");
361  memcpy(dw1, tdw1, sizeof(MDeformWeight *) * index_num);
362  MEM_freeN(tdw1);
363  dw2 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2");
364  memcpy(dw2, tdw2, sizeof(MDeformWeight *) * index_num);
365  MEM_freeN(tdw2);
366  }
367  else {
368  /* Use all vertices. */
369  index_num = verts_num;
370  /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */
371  dw1 = tdw1;
372  dw2 = tdw2;
373  }
374  MEM_freeN(tidx);
375 
376  org_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, org_w");
377  new_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, new_w");
378 
379  /* Mix weights. */
380  for (i = 0; i < index_num; i++) {
381  float weight2;
382  if (invert_vgroup_a) {
383  org_w[i] = 1.0f - (dw1[i] ? dw1[i]->weight : wmd->default_weight_a);
384  }
385  else {
386  org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
387  }
388  if (invert_vgroup_b) {
389  weight2 = 1.0f - (dw2[i] ? dw2[i]->weight : wmd->default_weight_b);
390  }
391  else {
392  weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
393  }
394 
395  new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode);
396  }
397 
398  /* Do masking. */
400  weightvg_do_mask(ctx,
401  index_num,
402  indices,
403  org_w,
404  new_w,
405  ctx->object,
406  mesh,
407  wmd->mask_constant,
408  wmd->mask_defgrp_name,
409  scene,
410  wmd->mask_texture,
412  wmd->mask_tex_mapping,
413  wmd->mask_tex_map_obj,
414  wmd->mask_tex_map_bone,
416  invert_vgroup_mask);
417 
418  /* Update (add to) vgroup.
419  * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
420  */
421  weightvg_update_vg(dvert,
422  defgrp_index,
423  dw1,
424  index_num,
425  indices,
426  org_w,
427  true,
428  -FLT_MAX,
429  false,
430  0.0f,
431  do_normalize);
432 
433  /* If weight preview enabled... */
434 #if 0 /* XXX Currently done in mod stack :/ */
435  if (do_prev) {
436  DM_update_weight_mcol(ob, dm, 0, org_w, index_num, indices);
437  }
438 #endif
439 
440  /* Freeing stuff. */
441  MEM_freeN(org_w);
442  MEM_freeN(new_w);
443  MEM_freeN(dw1);
444  MEM_freeN(dw2);
446 
447  mesh->runtime.is_original = false;
448 
449  /* Return the vgroup-modified mesh. */
450  return mesh;
451 }
452 
453 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
454 {
455  uiLayout *layout = panel->layout;
456 
457  PointerRNA ob_ptr;
459 
460  uiLayoutSetPropSep(layout, true);
461 
462  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group_a", "invert_vertex_group_a", NULL);
463  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group_b", "invert_vertex_group_b", IFACE_("B"));
464 
465  uiItemS(layout);
466 
467  uiItemR(layout, ptr, "default_weight_a", 0, NULL, ICON_NONE);
468  uiItemR(layout, ptr, "default_weight_b", 0, IFACE_("B"), ICON_NONE);
469 
470  uiItemS(layout);
471 
472  uiItemR(layout, ptr, "mix_set", 0, NULL, ICON_NONE);
473  uiItemR(layout, ptr, "mix_mode", 0, NULL, ICON_NONE);
474 
475  uiItemR(layout, ptr, "normalize", 0, NULL, ICON_NONE);
476 
477  modifier_panel_end(layout, ptr);
478 }
479 
480 static void influence_panel_draw(const bContext *C, Panel *panel)
481 {
482  uiLayout *layout = panel->layout;
483 
484  PointerRNA ob_ptr;
486 
487  weightvg_ui_common(C, &ob_ptr, ptr, layout);
488 }
489 
490 static void panelRegister(ARegionType *region_type)
491 {
492  PanelType *panel_type = modifier_panel_register(
493  region_type, eModifierType_WeightVGMix, panel_draw);
495  region_type, "influence", "Influence", NULL, influence_panel_draw, panel_type);
496 }
497 
499  /* name */ N_("VertexWeightMix"),
500  /* structName */ "WeightVGMixModifierData",
501  /* structSize */ sizeof(WeightVGMixModifierData),
502  /* srna */ &RNA_VertexWeightMixModifier,
506  /* icon */ ICON_MOD_VERTEX_WEIGHT,
507 
508  /* copyData */ BKE_modifier_copydata_generic,
509 
510  /* deformVerts */ NULL,
511  /* deformMatrices */ NULL,
512  /* deformVertsEM */ NULL,
513  /* deformMatricesEM */ NULL,
514  /* modifyMesh */ modifyMesh,
515  /* modifyGeometrySet */ NULL,
516 
517  /* initData */ initData,
518  /* requiredDataMask */ requiredDataMask,
519  /* freeData */ NULL,
520  /* isDisabled */ isDisabled,
521  /* updateDepsgraph */ updateDepsgraph,
522  /* dependsOnTime */ dependsOnTime,
523  /* dependsOnNormals */ NULL,
524  /* foreachIDLink */ foreachIDLink,
525  /* foreachTexLink */ foreachTexLink,
526  /* freeRuntimeData */ NULL,
527  /* panelRegister */ panelRegister,
528  /* blendWrite */ NULL,
529  /* blendRead */ NULL,
530 };
CustomData interface, see also DNA_customdata_types.h.
@ 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
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#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_SET_AND
@ MOD_WVG_SET_B
@ MOD_WVG_SET_ALL
@ MOD_WVG_SET_OR
@ MOD_WVG_SET_A
@ MOD_WVG_MIX_INVERT_VGROUP_MASK
@ MOD_WVG_MIX_INVERT_VGROUP_B
@ MOD_WVG_MIX_WEIGHTS_NORMALIZE
@ MOD_WVG_MIX_INVERT_VGROUP_A
@ eModifierType_WeightVGMix
@ MOD_DISP_MAP_OBJECT
@ MOD_DISP_MAP_GLOBAL
@ MOD_DISP_MAP_UV
struct WeightVGMixModifierData WeightVGMixModifierData
@ MOD_WVG_MIX_ADD
@ MOD_WVG_MIX_SUB
@ MOD_WVG_MIX_MIN
@ MOD_WVG_MIX_DIF
@ MOD_WVG_MIX_SET
@ MOD_WVG_MIX_MAX
@ MOD_WVG_MIX_DIV
@ MOD_WVG_MIX_AVG
@ MOD_WVG_MIX_MUL
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
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)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
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_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)
#define MOD_WVG_ZEROFLOOR
static void influence_panel_draw(const bContext *C, Panel *panel)
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
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 float mix_weight(float weight, float weight2, char mix_mode)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
ModifierTypeInfo modifierType_WeightVGMix
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 requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
#define C
Definition: RandGen.cpp:25
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
Scene scene
ccl_gpu_kernel_postfix int ccl_global int * indices
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
Definition: DNA_ID.h:368
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
struct Object * mask_tex_map_obj
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480