Blender V4.5
object_deform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLT_translation.hh"
15
16#include "BLI_ghash.h"
17#include "BLI_listbase.h"
18#include "BLI_string_utils.hh"
19#include "BLI_utildefines.h"
20
21#include "DNA_armature_types.h"
22#include "DNA_cloth_types.h"
23#include "DNA_curve_types.h"
26#include "DNA_lattice_types.h"
27#include "DNA_mesh_types.h"
28#include "DNA_meshdata_types.h"
29#include "DNA_modifier_types.h"
31#include "DNA_object_types.h"
32#include "DNA_particle_types.h"
33#include "DNA_scene_types.h"
34
35#include "BKE_action.hh"
36#include "BKE_deform.hh"
37#include "BKE_editmesh.hh"
38#include "BKE_gpencil_legacy.h"
40#include "BKE_mesh.hh"
41#include "BKE_modifier.hh"
42#include "BKE_object.hh"
43#include "BKE_object_deform.h" /* own include */
44
45/* -------------------------------------------------------------------- */
48
50{
51 Lattice *lt = (Lattice *)id;
52 BLI_assert(GS(id->name) == ID_LT);
53 return (lt->editlatt) ? lt->editlatt->latt : lt;
54}
55
57{
58 /* these cases don't use names to refer to vertex groups, so when
59 * they get removed the numbers get out of sync, this corrects that */
60
61 if (ob->soft) {
62 ob->soft->vertgroup = map[ob->soft->vertgroup];
63 }
64
66 if (md->type == eModifierType_Explode) {
68 emd->vgroup = map[emd->vgroup];
69 }
70 else if (md->type == eModifierType_Cloth) {
72 ClothSimSettings *clsim = clmd->sim_parms;
73 ClothCollSettings *clcoll = clmd->coll_parms;
74
75 if (clsim) {
76 clsim->vgroup_mass = map[clsim->vgroup_mass];
77 clsim->vgroup_shrink = map[clsim->vgroup_shrink];
78 clsim->vgroup_struct = map[clsim->vgroup_struct];
79 clsim->vgroup_shear = map[clsim->vgroup_shear];
80 clsim->vgroup_bend = map[clsim->vgroup_bend];
81 clsim->vgroup_intern = map[clsim->vgroup_intern];
82 clsim->vgroup_pressure = map[clsim->vgroup_pressure];
83 clcoll->vgroup_selfcol = map[clcoll->vgroup_selfcol];
84 clcoll->vgroup_objcol = map[clcoll->vgroup_objcol];
85 }
86 }
87 }
88
90 for (int a = 0; a < PSYS_TOT_VG; a++) {
91 psys->vgroup[a] = map[psys->vgroup[a]];
92 }
93 }
94}
95
97
98/* -------------------------------------------------------------------- */
101
103{
104 bDeformGroup *defgroup;
105
106 if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type)) {
107 return nullptr;
108 }
109
110 defgroup = BKE_object_defgroup_new(ob, name);
112
113 return defgroup;
114}
115
120
122{
123 if (GS(id->name) == ID_ME) {
124 return ((Mesh *)id)->deform_verts_for_write().data();
125 }
126 if (GS(id->name) == ID_LT) {
127 Lattice *lt = (Lattice *)id;
129 size_t(lt->pntsu) * size_t(lt->pntsv) * size_t(lt->pntsw), "lattice deformVert");
130 return lt->dvert;
131 }
132
133 return nullptr;
134}
135
137
138/* -------------------------------------------------------------------- */
141
142bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
143{
144 MDeformVert *dv;
145 const ListBase *defbase = BKE_object_defgroup_list(ob);
146 const int def_nr = BLI_findindex(defbase, dg);
147 bool changed = false;
148
149 if (ob->type == OB_MESH) {
150 Mesh *mesh = static_cast<Mesh *>(ob->data);
151
152 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
153 const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
154
155 if (cd_dvert_offset != -1) {
156 BMVert *eve;
157 BMIter iter;
158
159 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
160 dv = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
161
162 if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
163 MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
164 BKE_defvert_remove_group(dv, dw); /* dw can be nullptr */
165 changed = true;
166 }
167 }
168 }
169 }
170 else {
171 if (mesh->deform_verts().data()) {
172 const bool *select_vert = (const bool *)CustomData_get_layer_named(
173 &mesh->vert_data, CD_PROP_BOOL, ".select_vert");
174 int i;
175
176 dv = mesh->deform_verts_for_write().data();
177
178 for (i = 0; i < mesh->verts_num; i++, dv++) {
179 if (dv->dw && (!use_selection || (select_vert && select_vert[i]))) {
180 MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
181 BKE_defvert_remove_group(dv, dw); /* dw can be nullptr */
182 changed = true;
183 }
184 }
185 }
186 }
187 }
188 else if (ob->type == OB_LATTICE) {
190
191 if (lt->dvert) {
192 BPoint *bp;
193 int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
194
195 for (i = 0, bp = lt->def; i < tot; i++, bp++) {
196 if (!use_selection || (bp->f1 & SELECT)) {
197 MDeformWeight *dw;
198
199 dv = &lt->dvert[i];
200
201 dw = BKE_defvert_find_index(dv, def_nr);
202 BKE_defvert_remove_group(dv, dw); /* dw can be nullptr */
203 changed = true;
204 }
205 }
206 }
207 }
208
209 return changed;
210}
211
212bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
213{
214 bool changed = false;
215
216 const ListBase *defbase = BKE_object_defgroup_list(ob);
217
218 LISTBASE_FOREACH (bDeformGroup *, dg, defbase) {
219 if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
220 changed = true;
221 }
222 }
223
224 return changed;
225}
226
228
229/* -------------------------------------------------------------------- */
232
233static void object_defgroup_remove_update_users(Object *ob, const int idx)
234{
235 int i, defbase_tot = BKE_object_defgroup_count(ob) + 1;
236 int *map = MEM_malloc_arrayN<int>(size_t(defbase_tot), "vgroup del");
237
238 map[idx] = map[0] = 0;
239 for (i = 1; i < idx; i++) {
240 map[i] = i;
241 }
242 for (i = idx + 1; i < defbase_tot; i++) {
243 map[i] = i - 1;
244 }
245
247 MEM_freeN(map);
248}
249
250static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
251{
253
254 /* Remove the group */
256
257 BLI_freelinkN(defbase, dg);
258
259 /* Update the active deform index if necessary */
260 const int active_index = BKE_object_defgroup_active_index_get(ob);
261 if (active_index > def_nr) {
262 BKE_object_defgroup_active_index_set(ob, active_index - 1);
263 }
264
265 /* Remove all deform-verts. */
266 if (BLI_listbase_is_empty(defbase)) {
267 if (ob->type == OB_MESH) {
268 Mesh *mesh = static_cast<Mesh *>(ob->data);
270 }
271 else if (ob->type == OB_LATTICE) {
273 MEM_SAFE_FREE(lt->dvert);
274 }
275 else if (ob->type == OB_GREASE_PENCIL) {
276 GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
278 }
279 }
280 else if (BKE_object_defgroup_active_index_get(ob) < 1) {
281 /* Keep a valid active index if we still have some vgroups. */
283 }
284}
285
287{
288 MDeformVert *dvert_array = nullptr;
289 int dvert_tot = 0;
290 const ListBase *defbase = BKE_object_defgroup_list(ob);
291
292 const int def_nr = BLI_findindex(defbase, dg);
293
294 BLI_assert(def_nr != -1);
295
296 BKE_object_defgroup_array_get(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot);
297
298 if (dvert_array) {
299 int i, j;
300 MDeformVert *dv;
301 for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
302 MDeformWeight *dw;
303
304 dw = BKE_defvert_find_index(dv, def_nr);
305 BKE_defvert_remove_group(dv, dw); /* dw can be nullptr */
306
307 /* inline, make into a function if anything else needs to do this */
308 for (j = 0; j < dv->totweight; j++) {
309 if (dv->dw[j].def_nr > def_nr) {
310 dv->dw[j].def_nr--;
311 }
312 }
313 /* done */
314 }
315 }
316
317 object_defgroup_remove_common(ob, dg, def_nr);
318}
319
321{
322 int i;
323 const ListBase *defbase = BKE_object_defgroup_list(ob);
324 const int def_nr = BLI_findindex(defbase, dg);
325
326 BLI_assert(def_nr != -1);
327
328 /* Make sure that no verts are using this group - if none were removed,
329 * we can skip next per-vert update. */
330 if (!BKE_object_defgroup_clear(ob, dg, false)) {
331 /* Nothing to do. */
332 }
333 /* Else, make sure that any groups with higher indices are adjusted accordingly */
334 else if (ob->type == OB_MESH) {
335 Mesh *mesh = static_cast<Mesh *>(ob->data);
336 BMEditMesh *em = mesh->runtime->edit_mesh.get();
337 const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
338
339 BMIter iter;
340 BMVert *eve;
341 MDeformVert *dvert;
342
343 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
344 dvert = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
345
346 if (dvert) {
347 for (i = 0; i < dvert->totweight; i++) {
348 if (dvert->dw[i].def_nr > def_nr) {
349 dvert->dw[i].def_nr--;
350 }
351 }
352 }
353 }
354 }
355 else if (ob->type == OB_LATTICE) {
356 Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
357 BPoint *bp;
358 MDeformVert *dvert = lt->dvert;
359 int a, tot;
360
361 if (dvert) {
362 tot = lt->pntsu * lt->pntsv * lt->pntsw;
363 for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
364 for (i = 0; i < dvert->totweight; i++) {
365 if (dvert->dw[i].def_nr > def_nr) {
366 dvert->dw[i].def_nr--;
367 }
368 }
369 }
370 }
371 }
372
373 object_defgroup_remove_common(ob, dg, def_nr);
374}
375
377{
380 }
381 else {
383 }
384
385 if (ob->type == OB_GREASE_PENCIL) {
387 *static_cast<GreasePencil *>(ob->data));
388 }
389
391}
392
393void BKE_object_defgroup_remove_all_ex(Object *ob, bool only_unlocked)
394{
396
397 bDeformGroup *dg = (bDeformGroup *)defbase->first;
398 const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
399
400 if (dg) {
401 while (dg) {
402 bDeformGroup *next_dg = dg->next;
403
404 if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
405 if (edit_mode) {
407 }
408 else {
410 }
411 }
412
413 dg = next_dg;
414 }
415 }
416 else { /* `defbase` is empty. */
417 /* Remove all deform-verts. */
418 if (ob->type == OB_MESH) {
419 Mesh *mesh = static_cast<Mesh *>(ob->data);
421 }
422 else if (ob->type == OB_LATTICE) {
424 MEM_SAFE_FREE(lt->dvert);
425 }
426 else if (ob->type == OB_GREASE_PENCIL) {
427 GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
429 }
430 /* Fix counters/indices */
432 }
433}
434
439
440int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
441{
442 const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
443 const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst);
444
445 /* Build src to merged mapping of vgroup indices. */
446 if (BLI_listbase_is_empty(src_defbase) || BLI_listbase_is_empty(dst_defbase)) {
447 *r_map_len = 0;
448 return nullptr;
449 }
450
451 bDeformGroup *dg_src;
452 *r_map_len = BLI_listbase_count(src_defbase);
453 int *vgroup_index_map = MEM_malloc_arrayN<int>(size_t(*r_map_len), "defgroup index map create");
454 bool is_vgroup_remap_needed = false;
455 int i;
456
457 for (dg_src = static_cast<bDeformGroup *>(src_defbase->first), i = 0; dg_src;
458 dg_src = dg_src->next, i++)
459 {
460 vgroup_index_map[i] = BKE_object_defgroup_name_index(ob_dst, dg_src->name);
461 is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
462 }
463
464 if (!is_vgroup_remap_needed) {
465 MEM_freeN(vgroup_index_map);
466 vgroup_index_map = nullptr;
467 *r_map_len = 0;
468 }
469
470 return vgroup_index_map;
471}
472
474 int dvert_len,
475 const int *map,
476 int map_len)
477{
478 if (map == nullptr || map_len == 0) {
479 return;
480 }
481
482 MDeformVert *dv = dvert;
483 for (int i = 0; i < dvert_len; i++, dv++) {
484 int totweight = dv->totweight;
485 for (int j = 0; j < totweight; j++) {
486 int def_nr = dv->dw[j].def_nr;
487 if (uint(def_nr) < uint(map_len) && map[def_nr] != -1) {
488 dv->dw[j].def_nr = map[def_nr];
489 }
490 else {
491 totweight--;
492 dv->dw[j] = dv->dw[totweight];
493 j--;
494 }
495 }
496 if (totweight != dv->totweight) {
497 if (totweight) {
498 dv->dw = static_cast<MDeformWeight *>(MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight));
499 }
500 else {
501 MEM_SAFE_FREE(dv->dw);
502 }
503 dv->totweight = totweight;
504 }
505 }
506}
507
508bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
509{
510 if (id) {
511 switch (GS(id->name)) {
512 case ID_ME: {
513 Mesh *mesh = (Mesh *)id;
514 *dvert_arr = mesh->deform_verts_for_write().data();
515 *dvert_tot = mesh->verts_num;
516 return true;
517 }
518 case ID_LT: {
520 *dvert_arr = lt->dvert;
521 *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
522 return true;
523 }
524 case ID_GP:
525 /* Should not be used with grease pencil objects. */
526 dvert_arr = nullptr;
527 return false;
528 default:
529 break;
530 }
531 }
532
533 *dvert_arr = nullptr;
534 *dvert_tot = 0;
535 return false;
536}
537
539
540/* --- functions for getting vgroup aligned maps --- */
541
542bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
543{
544 bool is_locked = false;
545 int i;
547 bool *lock_flags = MEM_malloc_arrayN<bool>(size_t(defbase_tot), "defflags");
548 bDeformGroup *defgroup;
549
550 for (i = 0, defgroup = static_cast<bDeformGroup *>(defbase->first); i < defbase_tot && defgroup;
551 defgroup = defgroup->next, i++)
552 {
553 lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
554 is_locked |= lock_flags[i];
555 }
556 if (is_locked) {
557 return lock_flags;
558 }
559
560 MEM_freeN(lock_flags);
561 return nullptr;
562}
563
564bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
565{
566 bDeformGroup *dg;
567 ModifierData *md;
568 bool *defgroup_validmap;
569 GHash *gh;
570 int i, step1 = 1;
571 const ListBase *defbase = BKE_object_defgroup_list(ob);
572 VirtualModifierData virtual_modifier_data;
573
574 if (BLI_listbase_is_empty(defbase)) {
575 return nullptr;
576 }
577
578 gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
579
580 /* add all names to a hash table */
581 LISTBASE_FOREACH (bDeformGroup *, dg, defbase) {
582 BLI_ghash_insert(gh, dg->name, nullptr);
583 }
584
585 BLI_assert(BLI_ghash_len(gh) == defbase_tot);
586
587 /* now loop through the armature modifiers and identify deform bones */
588 for (md = static_cast<ModifierData *>(ob->modifiers.first); md;
589 md = !md->next && step1 ? (step1 = 0),
590 BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data) :
591 md->next)
592 {
594 continue;
595 }
596
598 Object *object = (md->type == eModifierType_Armature) ?
599 ((ArmatureModifierData *)md)->object :
600 ((GreasePencilArmatureModifierData *)md)->object;
601 if (object && object->pose) {
602 bPose *pose = object->pose;
603
604 LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) {
605 void **val_p;
606 if (chan->bone->flag & BONE_NO_DEFORM) {
607 continue;
608 }
609
610 val_p = BLI_ghash_lookup_p(gh, chan->name);
611 if (val_p) {
612 *val_p = POINTER_FROM_INT(1);
613 }
614 }
615 }
616 }
617 }
618
619 defgroup_validmap = MEM_malloc_arrayN<bool>(size_t(defbase_tot), "wpaint valid map");
620
621 /* add all names to a hash table */
622 for (dg = static_cast<bDeformGroup *>(defbase->first), i = 0; dg; dg = dg->next, i++) {
623 defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != nullptr);
624 }
625
626 BLI_assert(i == BLI_ghash_len(gh));
627
628 BLI_ghash_free(gh, nullptr, nullptr);
629
630 return defgroup_validmap;
631}
632
633bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
634{
635 bool *dg_selection = MEM_malloc_arrayN<bool>(size_t(defbase_tot), __func__);
636 bDeformGroup *defgroup;
637 uint i;
639 (*r_dg_flags_sel_tot) = 0;
640
641 const ListBase *defbase = BKE_object_defgroup_list(ob);
642
643 if (armob) {
644 bPose *pose = armob->pose;
645 for (i = 0, defgroup = static_cast<bDeformGroup *>(defbase->first);
646 i < defbase_tot && defgroup;
647 defgroup = defgroup->next, i++)
648 {
649 bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
650 if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
651 dg_selection[i] = true;
652 (*r_dg_flags_sel_tot) += 1;
653 }
654 else {
655 dg_selection[i] = false;
656 }
657 }
658 }
659 else {
660 memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
661 }
662
663 return dg_selection;
664}
665
666bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags,
667 const bool *validmap,
668 int index)
669{
670 return validmap && validmap[index] && !(lock_flags && lock_flags[index]);
671}
672
674 const bool *lock_flags,
675 const bool *selected,
676 int sel_tot)
677{
678 if (lock_flags == nullptr) {
679 return true;
680 }
681
682 if (selected == nullptr || sel_tot <= 1) {
683 return true;
684 }
685
686 for (int i = 0; i < defbase_tot; i++) {
687 if (selected[i] && lock_flags[i]) {
688 return false;
689 }
690 }
691
692 return true;
693}
694
696{
697 bDeformGroup *dg;
698 switch (ob->type) {
699 case OB_GREASE_PENCIL: {
700 GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
701 dg = static_cast<bDeformGroup *>(BLI_findlink(&grease_pencil->vertex_group_names,
702 grease_pencil->vertex_group_active_index - 1));
703 break;
704 }
705 default: {
706 Mesh *mesh = static_cast<Mesh *>(ob->data);
707 dg = static_cast<bDeformGroup *>(
709 break;
710 }
711 }
712 return dg->flag & DG_LOCK_WEIGHT;
713}
714
716 int defbase_tot, const bool *locked, const bool *deform, bool *r_locked, bool *r_unlocked)
717{
718 if (!locked) {
719 if (r_unlocked != deform) {
720 memcpy(r_unlocked, deform, sizeof(bool) * defbase_tot);
721 }
722 if (r_locked) {
723 memset(r_locked, 0, sizeof(bool) * defbase_tot);
724 }
725 return;
726 }
727
728 for (int i = 0; i < defbase_tot; i++) {
729 bool is_locked = locked[i];
730 bool is_deform = deform[i];
731
732 r_locked[i] = is_deform && is_locked;
733 r_unlocked[i] = is_deform && !is_locked;
734 }
735}
736
738 int defbase_tot,
739 const bool *dg_selection,
740 bool *dg_flags_sel,
741 int *r_dg_flags_sel_tot)
742{
743 const ListBase *defbase = BKE_object_defgroup_list(ob);
744
745 bDeformGroup *defgroup;
746 uint i;
747 int i_mirr;
748
749 for (i = 0, defgroup = static_cast<bDeformGroup *>(defbase->first); i < defbase_tot && defgroup;
750 defgroup = defgroup->next, i++)
751 {
752 if (dg_selection[i]) {
753 char name_flip[MAXBONENAME];
754
755 BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
756 i_mirr = STREQ(name_flip, defgroup->name) ? i :
757 BKE_object_defgroup_name_index(ob, name_flip);
758
759 if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
760 dg_flags_sel[i_mirr] = true;
761 (*r_dg_flags_sel_tot) += 1;
762 }
763 }
764 }
765}
766
768 eVGroupSelect subset_type,
769 int *r_defgroup_tot,
770 int *r_subset_count)
771{
772 bool *defgroup_validmap = nullptr;
773
774 *r_defgroup_tot = BKE_object_defgroup_count(ob);
775
776 switch (subset_type) {
777 case WT_VGROUP_ACTIVE: {
778 const int def_nr_active = BKE_object_defgroup_active_index_get(ob) - 1;
779 defgroup_validmap = MEM_malloc_arrayN<bool>(size_t(*r_defgroup_tot), __func__);
780 memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
781 if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
782 *r_subset_count = 1;
783 defgroup_validmap[def_nr_active] = true;
784 }
785 else {
786 *r_subset_count = 0;
787 }
788 break;
789 }
791 defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
792 break;
793 }
795 int i;
796 defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
797 *r_subset_count = 0;
798 for (i = 0; i < *r_defgroup_tot; i++) {
799 if (defgroup_validmap[i] == true) {
800 *r_subset_count += 1;
801 }
802 }
803 break;
804 }
806 int i;
807 defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
808 *r_subset_count = 0;
809 for (i = 0; i < *r_defgroup_tot; i++) {
810 defgroup_validmap[i] = !defgroup_validmap[i];
811 if (defgroup_validmap[i] == true) {
812 *r_subset_count += 1;
813 }
814 }
815 break;
816 }
817 case WT_VGROUP_ALL:
818 default: {
819 defgroup_validmap = MEM_malloc_arrayN<bool>(size_t(*r_defgroup_tot), __func__);
820 memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
821 *r_subset_count = *r_defgroup_tot;
822 break;
823 }
824 }
825
826 return defgroup_validmap;
827}
828
829void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
830 const int defgroup_tot,
831 int *r_defgroup_subset_map)
832{
833 int i, j = 0;
834 for (i = 0; i < defgroup_tot; i++) {
835 if (defgroup_validmap[i]) {
836 r_defgroup_subset_map[j++] = i;
837 }
838 }
839}
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_free_layer_active(CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
void BKE_object_defgroup_active_index_set(Object *ob, int new_index)
Definition deform.cc:601
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:596
bDeformGroup * BKE_object_defgroup_new(Object *ob, blender::StringRef name)
Definition deform.cc:46
int BKE_object_defgroup_count(const Object *ob)
Definition deform.cc:591
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:574
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
ListBase * BKE_object_defgroup_list_mutable(Object *ob)
Definition deform.cc:585
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
Definition deform.cc:869
int BKE_object_defgroup_name_index(const Object *ob, blender::StringRef name)
Definition deform.cc:580
Utility functions for vertex groups in grease pencil objects.
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
General operations, lookup, etc. for blender objects.
void BKE_object_batch_cache_dirty_tag(Object *ob)
Object * BKE_object_pose_armature_get(Object *ob)
bool BKE_object_is_in_editmode_vgroup(const Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
#define BLI_assert(a)
Definition BLI_assert.h:46
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:745
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:702
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
size_t BLI_string_flip_side_name(char *name_dst, const char *name_src, bool strip_number, size_t name_dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define POINTER_FROM_INT(i)
#define ELEM(...)
#define STREQ(a, b)
#define DATA_(msgid)
@ ID_ME
@ ID_LT
@ ID_GP
#define MAXBONENAME
@ BONE_SELECTED
@ BONE_NO_DEFORM
@ CD_MDEFORMVERT
@ eModifierMode_Virtual
@ eModifierMode_Realtime
@ eModifierType_Explode
@ eModifierType_GreasePencilArmature
@ eModifierType_Cloth
@ eModifierType_Armature
Object is a sort of wrapper for general info.
@ DG_LOCK_WEIGHT
@ OB_LATTICE
@ OB_GREASE_PENCIL
@ OB_MESH
#define OB_TYPE_SUPPORT_VGROUP(_type)
@ PSYS_TOT_VG
eVGroupSelect
@ WT_VGROUP_BONE_SELECT
@ WT_VGROUP_ALL
@ WT_VGROUP_BONE_DEFORM_OFF
@ WT_VGROUP_ACTIVE
@ WT_VGROUP_BONE_DEFORM
Read Guarded memory(de)allocation.
@ BM_ELEM_SELECT
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
#define SELECT
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
#define GS(a)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
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
void clear_vertex_groups(GreasePencil &grease_pencil)
void validate_drawing_vertex_groups(GreasePencil &grease_pencil)
bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags, const bool *validmap, int index)
bool * BKE_object_defgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
void BKE_object_defgroup_mirror_selection(Object *ob, int defbase_tot, const bool *dg_selection, bool *dg_flags_sel, int *r_dg_flags_sel_tot)
bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
void BKE_object_defgroup_split_locked_validmap(int defbase_tot, const bool *locked, const bool *deform, bool *r_locked, bool *r_unlocked)
static void object_defgroup_remove_update_users(Object *ob, const int idx)
bool * BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
bool * BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
int * BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
bool BKE_object_defgroup_active_is_locked(const Object *ob)
static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
bool BKE_object_defgroup_check_lock_relative_multi(int defbase_tot, const bool *lock_flags, const bool *selected, int sel_tot)
void BKE_object_defgroup_index_map_apply(MDeformVert *dvert, int dvert_len, const int *map, int map_len)
bool * BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
void BKE_object_defgroup_remove_all_ex(Object *ob, bool only_unlocked)
void BKE_object_defgroup_remap_update_users(Object *ob, const int *map)
bDeformGroup * BKE_object_defgroup_add(Object *ob)
void BKE_object_defgroup_remove_all(Object *ob)
static Lattice * object_defgroup_lattice_get(ID *id)
void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
bDeformGroup * BKE_object_defgroup_add_name(Object *ob, const char *name)
MDeformVert * BKE_object_defgroup_data_create(ID *id)
CustomData vdata
uint8_t f1
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct Lattice * latt
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
struct MDeformVert * dvert
struct EditLatt * editlatt
struct BPoint * def
void * first
struct MDeformWeight * dw
unsigned int def_nr
MeshRuntimeHandle * runtime
ListBase vertex_group_names
CustomData vert_data
int vertex_group_active_index
int verts_num
struct ModifierData * next
ListBase particlesystem
struct bPose * pose
ListBase modifiers
struct SoftBody * soft
struct bDeformGroup * next
struct Bone * bone
ListBase chanbase
i
Definition text_draw.cc:230