Cleanup: comments (long lines) in blenkernel
[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
123   defgroup = BKE_defgroup_new(ob, name);
124
125   ob->actdef = BLI_listbase_count(&ob->defbase);
126
127   return defgroup;
128 }
129
130 /**
131  * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all!
132  */
133 bDeformGroup *BKE_object_defgroup_add(Object *ob)
134 {
135   return BKE_object_defgroup_add_name(ob, DATA_("Group"));
136 }
137
138 /**
139  * Create MDeformVert data for given ID. Work in Object mode only.
140  */
141 MDeformVert *BKE_object_defgroup_data_create(ID *id)
142 {
143   if (GS(id->name) == ID_ME) {
144     Mesh *me = (Mesh *)id;
145     me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
146     return me->dvert;
147   }
148   else if (GS(id->name) == ID_LT) {
149     Lattice *lt = (Lattice *)id;
150     lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw,
151                             "lattice deformVert");
152     return lt->dvert;
153   }
154
155   return NULL;
156 }
157 /** \} */
158
159 /** \name Group clearing
160  * \{ */
161
162 /**
163  * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes.
164  *
165  * \param use_selection: Only operate on selection.
166  * \return True if any vertex was removed, false otherwise.
167  */
168 bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection)
169 {
170   MDeformVert *dv;
171   const int def_nr = BLI_findindex(&ob->defbase, dg);
172   bool changed = false;
173
174   if (ob->type == OB_MESH) {
175     Mesh *me = ob->data;
176
177     if (me->edit_mesh) {
178       BMEditMesh *em = me->edit_mesh;
179       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
180
181       if (cd_dvert_offset != -1) {
182         BMVert *eve;
183         BMIter iter;
184
185         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
186           dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
187
188           if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
189             MDeformWeight *dw = defvert_find_index(dv, def_nr);
190             defvert_remove_group(dv, dw); /* dw can be NULL */
191             changed = true;
192           }
193         }
194       }
195     }
196     else {
197       if (me->dvert) {
198         MVert *mv;
199         int i;
200
201         mv = me->mvert;
202         dv = me->dvert;
203
204         for (i = 0; i < me->totvert; i++, mv++, dv++) {
205           if (dv->dw && (!use_selection || (mv->flag & SELECT))) {
206             MDeformWeight *dw = defvert_find_index(dv, def_nr);
207             defvert_remove_group(dv, dw); /* dw can be NULL */
208             changed = true;
209           }
210         }
211       }
212     }
213   }
214   else if (ob->type == OB_LATTICE) {
215     Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
216
217     if (lt->dvert) {
218       BPoint *bp;
219       int i, tot = lt->pntsu * lt->pntsv * lt->pntsw;
220
221       for (i = 0, bp = lt->def; i < tot; i++, bp++) {
222         if (!use_selection || (bp->f1 & SELECT)) {
223           MDeformWeight *dw;
224
225           dv = &lt->dvert[i];
226
227           dw = defvert_find_index(dv, def_nr);
228           defvert_remove_group(dv, dw); /* dw can be NULL */
229           changed = true;
230         }
231       }
232     }
233   }
234
235   return changed;
236 }
237
238 /**
239  * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes.
240  *
241  * \param use_selection: Only operate on selection.
242  * \return True if any vertex was removed, false otherwise.
243  */
244 bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection)
245 {
246   bDeformGroup *dg;
247   bool changed = false;
248
249   for (dg = ob->defbase.first; dg; dg = dg->next) {
250     if (BKE_object_defgroup_clear(ob, dg, use_selection)) {
251       changed = true;
252     }
253   }
254
255   return changed;
256 }
257 /** \} */
258
259 /** \name Group removal
260  * \{ */
261
262 static void object_defgroup_remove_update_users(Object *ob, const int idx)
263 {
264   int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
265   int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
266
267   map[idx] = map[0] = 0;
268   for (i = 1; i < idx; i++) {
269     map[i] = i;
270   }
271   for (i = idx + 1; i < defbase_tot; i++) {
272     map[i] = i - 1;
273   }
274
275   BKE_object_defgroup_remap_update_users(ob, map);
276   MEM_freeN(map);
277 }
278
279 static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
280 {
281   object_defgroup_remove_update_users(ob, def_nr + 1);
282
283   /* Remove the group */
284   BLI_freelinkN(&ob->defbase, dg);
285
286   /* Update the active deform index if necessary */
287   if (ob->actdef > def_nr) {
288     ob->actdef--;
289   }
290
291   /* remove all dverts */
292   if (BLI_listbase_is_empty(&ob->defbase)) {
293     if (ob->type == OB_MESH) {
294       Mesh *me = ob->data;
295       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
296       me->dvert = NULL;
297     }
298     else if (ob->type == OB_LATTICE) {
299       Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
300       if (lt->dvert) {
301         MEM_freeN(lt->dvert);
302         lt->dvert = NULL;
303       }
304     }
305   }
306   else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */
307     ob->actdef = 1;
308   }
309 }
310
311 static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
312 {
313   MDeformVert *dvert_array = NULL;
314   int dvert_tot = 0;
315   const int def_nr = BLI_findindex(&ob->defbase, dg);
316
317   BLI_assert(def_nr != -1);
318
319   BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot);
320
321   if (dvert_array) {
322     int i, j;
323     MDeformVert *dv;
324     for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
325       MDeformWeight *dw;
326
327       dw = defvert_find_index(dv, def_nr);
328       defvert_remove_group(dv, dw); /* dw can be NULL */
329
330       /* inline, make into a function if anything else needs to do this */
331       for (j = 0; j < dv->totweight; j++) {
332         if (dv->dw[j].def_nr > def_nr) {
333           dv->dw[j].def_nr--;
334         }
335       }
336       /* done */
337     }
338   }
339
340   object_defgroup_remove_common(ob, dg, def_nr);
341 }
342
343 static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
344 {
345   int i;
346   const int def_nr = BLI_findindex(&ob->defbase, dg);
347
348   BLI_assert(def_nr != -1);
349
350   /* Make sure that no verts are using this group - if none were removed,
351    * we can skip next per-vert update. */
352   if (!BKE_object_defgroup_clear(ob, dg, false)) {
353     /* Nothing to do. */
354   }
355   /* Else, make sure that any groups with higher indices are adjusted accordingly */
356   else if (ob->type == OB_MESH) {
357     Mesh *me = ob->data;
358     BMEditMesh *em = me->edit_mesh;
359     const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
360
361     BMIter iter;
362     BMVert *eve;
363     MDeformVert *dvert;
364
365     BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
366       dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
367
368       if (dvert) {
369         for (i = 0; i < dvert->totweight; i++) {
370           if (dvert->dw[i].def_nr > def_nr) {
371             dvert->dw[i].def_nr--;
372           }
373         }
374       }
375     }
376   }
377   else if (ob->type == OB_LATTICE) {
378     Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
379     BPoint *bp;
380     MDeformVert *dvert = lt->dvert;
381     int a, tot;
382
383     if (dvert) {
384       tot = lt->pntsu * lt->pntsv * lt->pntsw;
385       for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
386         for (i = 0; i < dvert->totweight; i++) {
387           if (dvert->dw[i].def_nr > def_nr) {
388             dvert->dw[i].def_nr--;
389           }
390         }
391       }
392     }
393   }
394
395   object_defgroup_remove_common(ob, dg, def_nr);
396 }
397
398 /**
399  * Remove given vgroup from object. Work in Object and Edit modes.
400  */
401 void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
402 {
403   if (ob->type == OB_GPENCIL) {
404     BKE_gpencil_vgroup_remove(ob, defgroup);
405   }
406   else {
407     if (BKE_object_is_in_editmode_vgroup(ob)) {
408       object_defgroup_remove_edit_mode(ob, defgroup);
409     }
410     else {
411       object_defgroup_remove_object_mode(ob, defgroup);
412     }
413
414     BKE_object_batch_cache_dirty_tag(ob);
415   }
416 }
417
418 /**
419  * Remove all vgroups from object. Work in Object and Edit modes.
420  * When only_unlocked=true, locked vertex groups are not removed.
421  */
422 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
423 {
424   bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
425   const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
426
427   if (dg) {
428     while (dg) {
429       bDeformGroup *next_dg = dg->next;
430
431       if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
432         if (edit_mode) {
433           object_defgroup_remove_edit_mode(ob, dg);
434         }
435         else {
436           object_defgroup_remove_object_mode(ob, dg);
437         }
438       }
439
440       dg = next_dg;
441     }
442   }
443   else { /* ob->defbase is empty... */
444     /* remove all dverts */
445     if (ob->type == OB_MESH) {
446       Mesh *me = ob->data;
447       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
448       me->dvert = NULL;
449     }
450     else if (ob->type == OB_LATTICE) {
451       Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
452       if (lt->dvert) {
453         MEM_freeN(lt->dvert);
454         lt->dvert = NULL;
455       }
456     }
457     /* Fix counters/indices */
458     ob->actdef = 0;
459   }
460 }
461
462 /**
463  * Remove all vgroups from object. Work in Object and Edit modes.
464  */
465 void BKE_object_defgroup_remove_all(struct Object *ob)
466 {
467   BKE_object_defgroup_remove_all_ex(ob, false);
468 }
469
470 /**
471  * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
472  * Returns null if no remapping is required.
473  * The returned array has to be freed.
474  */
475 int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
476 {
477   /* Build src to merged mapping of vgroup indices. */
478   if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
479     *r_map_len = 0;
480     return NULL;
481   }
482
483   bDeformGroup *dg_src;
484   *r_map_len = BLI_listbase_count(&ob_src->defbase);
485   int *vgroup_index_map = MEM_malloc_arrayN(
486       *r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
487   bool is_vgroup_remap_needed = false;
488   int i;
489
490   for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
491     vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
492     is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
493   }
494
495   if (!is_vgroup_remap_needed) {
496     MEM_freeN(vgroup_index_map);
497     vgroup_index_map = NULL;
498     *r_map_len = 0;
499   }
500
501   return vgroup_index_map;
502 }
503
504 void BKE_object_defgroup_index_map_apply(MDeformVert *dvert,
505                                          int dvert_len,
506                                          const int *map,
507                                          int map_len)
508 {
509   if (map == NULL || map_len == 0) {
510     return;
511   }
512
513   MDeformVert *dv = dvert;
514   for (int i = 0; i < dvert_len; i++, dv++) {
515     int totweight = dv->totweight;
516     for (int j = 0; j < totweight; j++) {
517       int def_nr = dv->dw[j].def_nr;
518       if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
519         dv->dw[j].def_nr = map[def_nr];
520       }
521       else {
522         totweight--;
523         dv->dw[j] = dv->dw[totweight];
524         j--;
525       }
526     }
527     if (totweight != dv->totweight) {
528       if (totweight) {
529         dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
530       }
531       else {
532         MEM_SAFE_FREE(dv->dw);
533       }
534       dv->totweight = totweight;
535     }
536   }
537 }
538
539 /**
540  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
541  *
542  * \return True if the id type supports weights.
543  */
544 bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
545 {
546   if (id) {
547     switch (GS(id->name)) {
548       case ID_ME: {
549         Mesh *me = (Mesh *)id;
550         *dvert_arr = me->dvert;
551         *dvert_tot = me->totvert;
552         return true;
553       }
554       case ID_LT: {
555         Lattice *lt = object_defgroup_lattice_get(id);
556         *dvert_arr = lt->dvert;
557         *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
558         return true;
559       }
560       default:
561         break;
562     }
563   }
564
565   *dvert_arr = NULL;
566   *dvert_tot = 0;
567   return false;
568 }
569 /** \} */
570
571 /* --- functions for getting vgroup aligned maps --- */
572
573 /**
574  * gets the status of "flag" for each bDeformGroup
575  * in ob->defbase and returns an array containing them
576  */
577 bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
578 {
579   bool is_locked = false;
580   int i;
581   //int defbase_tot = BLI_listbase_count(&ob->defbase);
582   bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
583   bDeformGroup *defgroup;
584
585   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
586        defgroup = defgroup->next, i++) {
587     lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
588     is_locked |= lock_flags[i];
589   }
590   if (is_locked) {
591     return lock_flags;
592   }
593
594   MEM_freeN(lock_flags);
595   return NULL;
596 }
597
598 bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
599 {
600   bDeformGroup *dg;
601   ModifierData *md;
602   bool *defgroup_validmap;
603   GHash *gh;
604   int i, step1 = 1;
605   //int defbase_tot = BLI_listbase_count(&ob->defbase);
606   VirtualModifierData virtualModifierData;
607
608   if (BLI_listbase_is_empty(&ob->defbase)) {
609     return NULL;
610   }
611
612   gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
613
614   /* add all names to a hash table */
615   for (dg = ob->defbase.first; dg; dg = dg->next) {
616     BLI_ghash_insert(gh, dg->name, NULL);
617   }
618
619   BLI_assert(BLI_ghash_len(gh) == defbase_tot);
620
621   /* now loop through the armature modifiers and identify deform bones */
622   for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0),
623       modifiers_getVirtualModifierList(ob, &virtualModifierData) :
624                                      md->next) {
625     if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) {
626       continue;
627     }
628
629     if (md->type == eModifierType_Armature) {
630       ArmatureModifierData *amd = (ArmatureModifierData *)md;
631
632       if (amd->object && amd->object->pose) {
633         bPose *pose = amd->object->pose;
634         bPoseChannel *chan;
635
636         for (chan = pose->chanbase.first; chan; chan = chan->next) {
637           void **val_p;
638           if (chan->bone->flag & BONE_NO_DEFORM) {
639             continue;
640           }
641
642           val_p = BLI_ghash_lookup_p(gh, chan->name);
643           if (val_p) {
644             *val_p = POINTER_FROM_INT(1);
645           }
646         }
647       }
648     }
649   }
650
651   defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
652
653   /* add all names to a hash table */
654   for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
655     defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
656   }
657
658   BLI_assert(i == BLI_ghash_len(gh));
659
660   BLI_ghash_free(gh, NULL, NULL);
661
662   return defgroup_validmap;
663 }
664
665 /* Returns total selected vgroups,
666  * wpi.defbase_sel is assumed malloc'd, all values are set */
667 bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
668 {
669   bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
670   bDeformGroup *defgroup;
671   unsigned int i;
672   Object *armob = BKE_object_pose_armature_get(ob);
673   (*r_dg_flags_sel_tot) = 0;
674
675   if (armob) {
676     bPose *pose = armob->pose;
677     for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
678          defgroup = defgroup->next, i++) {
679       bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
680       if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
681         dg_selection[i] = true;
682         (*r_dg_flags_sel_tot) += 1;
683       }
684       else {
685         dg_selection[i] = false;
686       }
687     }
688   }
689   else {
690     memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
691   }
692
693   return dg_selection;
694 }
695
696 /**
697  * Marks mirror vgroups in output and counts them.
698  * Output and counter assumed to be already initialized.
699  * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
700  */
701 void BKE_object_defgroup_mirror_selection(struct Object *ob,
702                                           int defbase_tot,
703                                           const bool *dg_selection,
704                                           bool *dg_flags_sel,
705                                           int *r_dg_flags_sel_tot)
706 {
707   bDeformGroup *defgroup;
708   unsigned int i;
709   int i_mirr;
710
711   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
712        defgroup = defgroup->next, i++) {
713     if (dg_selection[i]) {
714       char name_flip[MAXBONENAME];
715
716       BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
717       i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
718
719       if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
720         dg_flags_sel[i_mirr] = true;
721         (*r_dg_flags_sel_tot) += 1;
722       }
723     }
724   }
725 }
726
727 /**
728  * Return the subset type of the Vertex Group Selection
729  */
730 bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
731                                                   eVGroupSelect subset_type,
732                                                   int *r_defgroup_tot,
733                                                   int *r_subset_count)
734 {
735   bool *defgroup_validmap = NULL;
736   *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
737
738   switch (subset_type) {
739     case WT_VGROUP_ACTIVE: {
740       const int def_nr_active = ob->actdef - 1;
741       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
742       memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
743       if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
744         *r_subset_count = 1;
745         defgroup_validmap[def_nr_active] = true;
746       }
747       else {
748         *r_subset_count = 0;
749       }
750       break;
751     }
752     case WT_VGROUP_BONE_SELECT: {
753       defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
754       break;
755     }
756     case WT_VGROUP_BONE_DEFORM: {
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         if (defgroup_validmap[i] == true) {
762           *r_subset_count += 1;
763         }
764       }
765       break;
766     }
767     case WT_VGROUP_BONE_DEFORM_OFF: {
768       int i;
769       defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
770       *r_subset_count = 0;
771       for (i = 0; i < *r_defgroup_tot; i++) {
772         defgroup_validmap[i] = !defgroup_validmap[i];
773         if (defgroup_validmap[i] == true) {
774           *r_subset_count += 1;
775         }
776       }
777       break;
778     }
779     case WT_VGROUP_ALL:
780     default: {
781       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
782       memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
783       *r_subset_count = *r_defgroup_tot;
784       break;
785     }
786   }
787
788   return defgroup_validmap;
789 }
790
791 /**
792  * store indices from the defgroup_validmap (faster lookups in some cases)
793  */
794 void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
795                                                const int defgroup_tot,
796                                                int *r_defgroup_subset_map)
797 {
798   int i, j = 0;
799   for (i = 0; i < defgroup_tot; i++) {
800     if (defgroup_validmap[i]) {
801       r_defgroup_subset_map[j++] = i;
802     }
803   }
804 }