ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / object_deform.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup bke
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "MEM_guardedalloc.h"
25
26 #include "BLT_translation.h"
27
28 #include "BLI_utildefines.h"
29 #include "BLI_ghash.h"
30 #include "BLI_listbase.h"
31 #include "BLI_string_utils.h"
32
33 #include "DNA_armature_types.h"
34 #include "DNA_cloth_types.h"
35 #include "DNA_curve_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_modifier_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_object_force_types.h"
42 #include "DNA_particle_types.h"
43 #include "DNA_scene_types.h"
44
45 #include "BKE_action.h"
46 #include "BKE_deform.h"
47 #include "BKE_editmesh.h"
48 #include "BKE_object_deform.h" /* own include */
49 #include "BKE_object.h"
50 #include "BKE_mesh.h"
51 #include "BKE_modifier.h"
52 #include "BKE_gpencil.h"
53
54 /** \name Misc helpers
55  * \{ */
56
57 static Lattice *object_defgroup_lattice_get(ID *id)
58 {
59   Lattice *lt = (Lattice *)id;
60   BLI_assert(GS(id->name) == ID_LT);
61   return (lt->editlatt) ? lt->editlatt->latt : lt;
62 }
63
64 /**
65  * Update users of vgroups from this object, according to given map.
66  *
67  * Use it when you remove or reorder vgroups in the object.
68  *
69  * \param map: an array mapping old indices to new indices.
70  */
71 void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
72 {
73   ModifierData *md;
74   ParticleSystem *psys;
75   int a;
76
77   /* these cases don't use names to refer to vertex groups, so when
78    * they get removed the numbers get out of sync, this corrects that */
79
80   if (ob->soft) {
81     ob->soft->vertgroup = map[ob->soft->vertgroup];
82   }
83
84   for (md = ob->modifiers.first; md; md = md->next) {
85     if (md->type == eModifierType_Explode) {
86       ExplodeModifierData *emd = (ExplodeModifierData *)md;
87       emd->vgroup = map[emd->vgroup];
88     }
89     else if (md->type == eModifierType_Cloth) {
90       ClothModifierData *clmd = (ClothModifierData *)md;
91       ClothSimSettings *clsim = clmd->sim_parms;
92
93       if (clsim) {
94         clsim->vgroup_mass = map[clsim->vgroup_mass];
95         clsim->vgroup_bend = map[clsim->vgroup_bend];
96         clsim->vgroup_struct = map[clsim->vgroup_struct];
97       }
98     }
99   }
100
101   for (psys = ob->particlesystem.first; psys; psys = psys->next) {
102     for (a = 0; a < PSYS_TOT_VG; a++) {
103       psys->vgroup[a] = map[psys->vgroup[a]];
104     }
105   }
106 }
107 /** \} */
108
109 /** \name Group creation
110  * \{ */
111
112 /**
113  * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all!
114  */
115 bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
116 {
117   bDeformGroup *defgroup;
118
119   if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
120     return NULL;
121
122   defgroup = BKE_defgroup_new(ob, name);
123
124   ob->actdef = BLI_listbase_count(&ob->defbase);
125
126   return defgroup;
127 }
128
129 /**
130  * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all!
131  */
132 bDeformGroup *BKE_object_defgroup_add(Object *ob)
133 {
134   return BKE_object_defgroup_add_name(ob, DATA_("Group"));
135 }
136
137 /**
138  * Create MDeformVert data for given ID. Work in Object mode only.
139  */
140 MDeformVert *BKE_object_defgroup_data_create(ID *id)
141 {
142   if (GS(id->name) == ID_ME) {
143     Mesh *me = (Mesh *)id;
144     me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
145     return me->dvert;
146   }
147   else if (GS(id->name) == ID_LT) {
148     Lattice *lt = (Lattice *)id;
149     lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw,
150                             "lattice deformVert");
151     return lt->dvert;
152   }
153
154   return NULL;
155 }
156 /** \} */
157
158 /** \name Group clearing
159  * \{ */
160
161 /**
162  * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
163  *
164  * \param use_selection: Only operate on selection.
165  * \return True if any vertex was removed, false otherwise.
166  */
167 bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
168 {
169   MDeformVert *dv;
170   const int def_nr = BLI_findindex(&ob->defbase, dg);
171   bool changed = false;
172
173   if (ob->type == OB_MESH) {
174     Mesh *me = ob->data;
175
176     if (me->edit_mesh) {
177       BMEditMesh *em = me->edit_mesh;
178       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
179
180       if (cd_dvert_offset != -1) {
181         BMVert *eve;
182         BMIter iter;
183
184         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
185           dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
186
187           if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
188             MDeformWeight *dw = defvert_find_index(dv, def_nr);
189             defvert_remove_group(dv, dw); /* dw can be NULL */
190             changed = true;
191           }
192         }
193       }
194     }
195     else {
196       if (me->dvert) {
197         MVert *mv;
198         int i;
199
200         mv = me->mvert;
201         dv = me->dvert;
202
203         for (i = 0; i < me->totvert; i++, mv++, dv++) {
204           if (dv->dw && (!use_selection || (mv->flag & SELECT))) {
205             MDeformWeight *dw = defvert_find_index(dv, def_nr);
206             defvert_remove_group(dv, dw); /* dw can be NULL */
207             changed = true;
208           }
209         }
210       }
211     }
212   }
213   else if (ob->type == OB_LATTICE) {
214     Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
215
216     if (lt->dvert) {
217       BPoint *bp;
218       int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
219
220       for (i = 0, bp = lt->def; i < tot; i++, bp++) {
221         if (!use_selection || (bp->f1 & SELECT)) {
222           MDeformWeight *dw;
223
224           dv = &lt->dvert[i];
225
226           dw = defvert_find_index(dv, def_nr);
227           defvert_remove_group(dv, dw); /* dw can be NULL */
228           changed = true;
229         }
230       }
231     }
232   }
233
234   return changed;
235 }
236
237 /**
238  * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
239  *
240  * \param use_selection: Only operate on selection.
241  * \return True if any vertex was removed, false otherwise.
242  */
243 bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
244 {
245   bDeformGroup *dg;
246   bool changed = false;
247
248   for (dg = ob->defbase.first; dg; dg = dg->next) {
249     if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
250       changed = true;
251     }
252   }
253
254   return changed;
255 }
256 /** \} */
257
258 /** \name Group removal
259  * \{ */
260
261 static void object_defgroup_remove_update_users(Object *ob, const int idx)
262 {
263   int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
264   int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
265
266   map[idx] = map[0] = 0;
267   for (i = 1; i < idx; i++) {
268     map[i] = i;
269   }
270   for (i = idx + 1; i < defbase_tot; i++) {
271     map[i] = i - 1;
272   }
273
274   BKE_object_defgroup_remap_update_users(ob, map);
275   MEM_freeN(map);
276 }
277
278 static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
279 {
280   object_defgroup_remove_update_users(ob, def_nr + 1);
281
282   /* Remove the group */
283   BLI_freelinkN(&ob->defbase, dg);
284
285   /* Update the active deform index if necessary */
286   if (ob->actdef > def_nr)
287     ob->actdef--;
288
289   /* remove all dverts */
290   if (BLI_listbase_is_empty(&ob->defbase)) {
291     if (ob->type == OB_MESH) {
292       Mesh *me = ob->data;
293       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
294       me->dvert = NULL;
295     }
296     else if (ob->type == OB_LATTICE) {
297       Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
298       if (lt->dvert) {
299         MEM_freeN(lt->dvert);
300         lt->dvert = NULL;
301       }
302     }
303   }
304   else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */
305     ob->actdef = 1;
306   }
307 }
308
309 static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
310 {
311   MDeformVert *dvert_array = NULL;
312   int dvert_tot = 0;
313   const int def_nr = BLI_findindex(&ob->defbase, dg);
314
315   BLI_assert(def_nr != -1);
316
317   BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot);
318
319   if (dvert_array) {
320     int i, j;
321     MDeformVert *dv;
322     for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
323       MDeformWeight *dw;
324
325       dw = defvert_find_index(dv, def_nr);
326       defvert_remove_group(dv, dw); /* dw can be NULL */
327
328       /* inline, make into a function if anything else needs to do this */
329       for (j = 0; j < dv->totweight; j++) {
330         if (dv->dw[j].def_nr > def_nr) {
331           dv->dw[j].def_nr--;
332         }
333       }
334       /* done */
335     }
336   }
337
338   object_defgroup_remove_common(ob, dg, def_nr);
339 }
340
341 static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
342 {
343   int i;
344   const int def_nr = BLI_findindex(&ob->defbase, dg);
345
346   BLI_assert(def_nr != -1);
347
348   /* Make sure that no verts are using this group - if none were removed, we can skip next per-vert update. */
349   if (!BKE_object_defgroup_clear(ob, dg, false)) {
350     /* Nothing to do. */
351   }
352   /* Else, make sure that any groups with higher indices are adjusted accordingly */
353   else if (ob->type == OB_MESH) {
354     Mesh *me = ob->data;
355     BMEditMesh *em = me->edit_mesh;
356     const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
357
358     BMIter iter;
359     BMVert *eve;
360     MDeformVert *dvert;
361
362     BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
363       dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
364
365       if (dvert) {
366         for (i = 0; i < dvert->totweight; i++) {
367           if (dvert->dw[i].def_nr > def_nr) {
368             dvert->dw[i].def_nr--;
369           }
370         }
371       }
372     }
373   }
374   else if (ob->type == OB_LATTICE) {
375     Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
376     BPoint *bp;
377     MDeformVert *dvert = lt->dvert;
378     int a, tot;
379
380     if (dvert) {
381       tot = lt->pntsu * lt->pntsv * lt->pntsw;
382       for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
383         for (i = 0; i < dvert->totweight; i++) {
384           if (dvert->dw[i].def_nr > def_nr) {
385             dvert->dw[i].def_nr--;
386           }
387         }
388       }
389     }
390   }
391
392   object_defgroup_remove_common(ob, dg, def_nr);
393 }
394
395 /**
396  * Remove given vgroup from object. Work in Object and Edit modes.
397  */
398 void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
399 {
400   if (ob->type == OB_GPENCIL) {
401     BKE_gpencil_vgroup_remove(ob, defgroup);
402   }
403   else {
404     if (BKE_object_is_in_editmode_vgroup(ob))
405       object_defgroup_remove_edit_mode(ob, defgroup);
406     else
407       object_defgroup_remove_object_mode(ob, defgroup);
408
409     BKE_object_batch_cache_dirty_tag(ob);
410   }
411 }
412
413 /**
414  * Remove all vgroups from object. Work in Object and Edit modes.
415  * When only_unlocked=true, locked vertex groups are not removed.
416  */
417 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
418 {
419   bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
420   const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
421
422   if (dg) {
423     while (dg) {
424       bDeformGroup *next_dg = dg->next;
425
426       if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
427         if (edit_mode)
428           object_defgroup_remove_edit_mode(ob, dg);
429         else
430           object_defgroup_remove_object_mode(ob, dg);
431       }
432
433       dg = next_dg;
434     }
435   }
436   else { /* ob->defbase is empty... */
437     /* remove all dverts */
438     if (ob->type == OB_MESH) {
439       Mesh *me = ob->data;
440       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
441       me->dvert = NULL;
442     }
443     else if (ob->type == OB_LATTICE) {
444       Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
445       if (lt->dvert) {
446         MEM_freeN(lt->dvert);
447         lt->dvert = NULL;
448       }
449     }
450     /* Fix counters/indices */
451     ob->actdef = 0;
452   }
453 }
454
455 /**
456  * Remove all vgroups from object. Work in Object and Edit modes.
457  */
458 void BKE_object_defgroup_remove_all(struct Object *ob)
459 {
460   BKE_object_defgroup_remove_all_ex(ob, false);
461 }
462
463 /**
464  * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
465  * Returns null if no remapping is required.
466  * The returned array has to be freed.
467  */
468 int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
469 {
470   /* Build src to merged mapping of vgroup indices. */
471   if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
472     *r_map_len = 0;
473     return NULL;
474   }
475
476   bDeformGroup *dg_src;
477   *r_map_len = BLI_listbase_count(&ob_src->defbase);
478   int *vgroup_index_map = MEM_malloc_arrayN(
479       *r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
480   bool is_vgroup_remap_needed = false;
481   int i;
482
483   for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
484     vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
485     is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
486   }
487
488   if (!is_vgroup_remap_needed) {
489     MEM_freeN(vgroup_index_map);
490     vgroup_index_map = NULL;
491     *r_map_len = 0;
492   }
493
494   return vgroup_index_map;
495 }
496
497 void BKE_object_defgroup_index_map_apply(MDeformVert *dvert,
498                                          int dvert_len,
499                                          const int *map,
500                                          int map_len)
501 {
502   if (map == NULL || map_len == 0) {
503     return;
504   }
505
506   MDeformVert *dv = dvert;
507   for (int i = 0; i < dvert_len; i++, dv++) {
508     int totweight = dv->totweight;
509     for (int j = 0; j < totweight; j++) {
510       int def_nr = dv->dw[j].def_nr;
511       if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
512         dv->dw[j].def_nr = map[def_nr];
513       }
514       else {
515         totweight--;
516         dv->dw[j] = dv->dw[totweight];
517         j--;
518       }
519     }
520     if (totweight != dv->totweight) {
521       if (totweight) {
522         dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
523       }
524       else {
525         MEM_SAFE_FREE(dv->dw);
526       }
527       dv->totweight = totweight;
528     }
529   }
530 }
531
532 /**
533  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
534  *
535  * \return True if the id type supports weights.
536  */
537 bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
538 {
539   if (id) {
540     switch (GS(id->name)) {
541       case ID_ME: {
542         Mesh *me = (Mesh *)id;
543         *dvert_arr = me->dvert;
544         *dvert_tot = me->totvert;
545         return true;
546       }
547       case ID_LT: {
548         Lattice *lt = object_defgroup_lattice_get(id);
549         *dvert_arr = lt->dvert;
550         *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
551         return true;
552       }
553       default:
554         break;
555     }
556   }
557
558   *dvert_arr = NULL;
559   *dvert_tot = 0;
560   return false;
561 }
562 /** \} */
563
564 /* --- functions for getting vgroup aligned maps --- */
565
566 /**
567  * gets the status of "flag" for each bDeformGroup
568  * in ob->defbase and returns an array containing them
569  */
570 bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
571 {
572   bool is_locked = false;
573   int i;
574   //int defbase_tot = BLI_listbase_count(&ob->defbase);
575   bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
576   bDeformGroup *defgroup;
577
578   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
579        defgroup = defgroup->next, i++) {
580     lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
581     is_locked |= lock_flags[i];
582   }
583   if (is_locked) {
584     return lock_flags;
585   }
586
587   MEM_freeN(lock_flags);
588   return NULL;
589 }
590
591 bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
592 {
593   bDeformGroup *dg;
594   ModifierData *md;
595   bool *defgroup_validmap;
596   GHash *gh;
597   int i, step1 = 1;
598   //int defbase_tot = BLI_listbase_count(&ob->defbase);
599   VirtualModifierData virtualModifierData;
600
601   if (BLI_listbase_is_empty(&ob->defbase)) {
602     return NULL;
603   }
604
605   gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
606
607   /* add all names to a hash table */
608   for (dg = ob->defbase.first; dg; dg = dg->next) {
609     BLI_ghash_insert(gh, dg->name, NULL);
610   }
611
612   BLI_assert(BLI_ghash_len(gh) == defbase_tot);
613
614   /* now loop through the armature modifiers and identify deform bones */
615   for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0),
616       modifiers_getVirtualModifierList(ob, &virtualModifierData) :
617                                      md->next) {
618     if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
619       continue;
620
621     if (md->type == eModifierType_Armature) {
622       ArmatureModifierData *amd = (ArmatureModifierData *)md;
623
624       if (amd->object && amd->object->pose) {
625         bPose *pose = amd->object->pose;
626         bPoseChannel *chan;
627
628         for (chan = pose->chanbase.first; chan; chan = chan->next) {
629           void **val_p;
630           if (chan->bone->flag & BONE_NO_DEFORM)
631             continue;
632
633           val_p = BLI_ghash_lookup_p(gh, chan->name);
634           if (val_p) {
635             *val_p = POINTER_FROM_INT(1);
636           }
637         }
638       }
639     }
640   }
641
642   defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
643
644   /* add all names to a hash table */
645   for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
646     defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
647   }
648
649   BLI_assert(i == BLI_ghash_len(gh));
650
651   BLI_ghash_free(gh, NULL, NULL);
652
653   return defgroup_validmap;
654 }
655
656 /* Returns total selected vgroups,
657  * wpi.defbase_sel is assumed malloc'd, all values are set */
658 bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
659 {
660   bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
661   bDeformGroup *defgroup;
662   unsigned int i;
663   Object *armob = BKE_object_pose_armature_get(ob);
664   (*r_dg_flags_sel_tot) = 0;
665
666   if (armob) {
667     bPose *pose = armob->pose;
668     for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
669          defgroup = defgroup->next, i++) {
670       bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
671       if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
672         dg_selection[i] = true;
673         (*r_dg_flags_sel_tot) += 1;
674       }
675       else {
676         dg_selection[i] = false;
677       }
678     }
679   }
680   else {
681     memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
682   }
683
684   return dg_selection;
685 }
686
687 /* Marks mirror vgroups in output and counts them. Output and counter assumed to be already initialized.
688  * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
689  */
690 void BKE_object_defgroup_mirror_selection(struct Object *ob,
691                                           int defbase_tot,
692                                           const bool *dg_selection,
693                                           bool *dg_flags_sel,
694                                           int *r_dg_flags_sel_tot)
695 {
696   bDeformGroup *defgroup;
697   unsigned int i;
698   int i_mirr;
699
700   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
701        defgroup = defgroup->next, i++) {
702     if (dg_selection[i]) {
703       char name_flip[MAXBONENAME];
704
705       BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
706       i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
707
708       if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
709         dg_flags_sel[i_mirr] = true;
710         (*r_dg_flags_sel_tot) += 1;
711       }
712     }
713   }
714 }
715
716 /**
717  * Return the subset type of the Vertex Group Selection
718  */
719 bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
720                                                   eVGroupSelect subset_type,
721                                                   int *r_defgroup_tot,
722                                                   int *r_subset_count)
723 {
724   bool *defgroup_validmap = NULL;
725   *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
726
727   switch (subset_type) {
728     case WT_VGROUP_ACTIVE: {
729       const int def_nr_active = ob->actdef - 1;
730       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
731       memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
732       if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
733         *r_subset_count = 1;
734         defgroup_validmap[def_nr_active] = true;
735       }
736       else {
737         *r_subset_count = 0;
738       }
739       break;
740     }
741     case WT_VGROUP_BONE_SELECT: {
742       defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
743       break;
744     }
745     case WT_VGROUP_BONE_DEFORM: {
746       int i;
747       defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
748       *r_subset_count = 0;
749       for (i = 0; i < *r_defgroup_tot; i++) {
750         if (defgroup_validmap[i] == true) {
751           *r_subset_count += 1;
752         }
753       }
754       break;
755     }
756     case WT_VGROUP_BONE_DEFORM_OFF: {
757       int i;
758       defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
759       *r_subset_count = 0;
760       for (i = 0; i < *r_defgroup_tot; i++) {
761         defgroup_validmap[i] = !defgroup_validmap[i];
762         if (defgroup_validmap[i] == true) {
763           *r_subset_count += 1;
764         }
765       }
766       break;
767     }
768     case WT_VGROUP_ALL:
769     default: {
770       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
771       memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
772       *r_subset_count = *r_defgroup_tot;
773       break;
774     }
775   }
776
777   return defgroup_validmap;
778 }
779
780 /**
781  * store indices from the defgroup_validmap (faster lookups in some cases)
782  */
783 void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
784                                                const int defgroup_tot,
785                                                int *r_defgroup_subset_map)
786 {
787   int i, j = 0;
788   for (i = 0; i < defgroup_tot; i++) {
789     if (defgroup_validmap[i]) {
790       r_defgroup_subset_map[j++] = i;
791     }
792   }
793 }