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