Cleanup: style, use braces for 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, we can skip next per-vert update. */
351   if (!BKE_object_defgroup_clear(ob, dg, false)) {
352     /* Nothing to do. */
353   }
354   /* Else, make sure that any groups with higher indices are adjusted accordingly */
355   else if (ob->type == OB_MESH) {
356     Mesh *me = ob->data;
357     BMEditMesh *em = me->edit_mesh;
358     const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
359
360     BMIter iter;
361     BMVert *eve;
362     MDeformVert *dvert;
363
364     BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
365       dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
366
367       if (dvert) {
368         for (i = 0; i < dvert->totweight; i++) {
369           if (dvert->dw[i].def_nr > def_nr) {
370             dvert->dw[i].def_nr--;
371           }
372         }
373       }
374     }
375   }
376   else if (ob->type == OB_LATTICE) {
377     Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
378     BPoint *bp;
379     MDeformVert *dvert = lt->dvert;
380     int a, tot;
381
382     if (dvert) {
383       tot = lt->pntsu * lt->pntsv * lt->pntsw;
384       for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
385         for (i = 0; i < dvert->totweight; i++) {
386           if (dvert->dw[i].def_nr > def_nr) {
387             dvert->dw[i].def_nr--;
388           }
389         }
390       }
391     }
392   }
393
394   object_defgroup_remove_common(ob, dg, def_nr);
395 }
396
397 /**
398  * Remove given vgroup from object. Work in Object and Edit modes.
399  */
400 void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
401 {
402   if (ob->type == OB_GPENCIL) {
403     BKE_gpencil_vgroup_remove(ob, defgroup);
404   }
405   else {
406     if (BKE_object_is_in_editmode_vgroup(ob)) {
407       object_defgroup_remove_edit_mode(ob, defgroup);
408     }
409     else {
410       object_defgroup_remove_object_mode(ob, defgroup);
411     }
412
413     BKE_object_batch_cache_dirty_tag(ob);
414   }
415 }
416
417 /**
418  * Remove all vgroups from object. Work in Object and Edit modes.
419  * When only_unlocked=true, locked vertex groups are not removed.
420  */
421 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
422 {
423   bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
424   const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
425
426   if (dg) {
427     while (dg) {
428       bDeformGroup *next_dg = dg->next;
429
430       if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
431         if (edit_mode) {
432           object_defgroup_remove_edit_mode(ob, dg);
433         }
434         else {
435           object_defgroup_remove_object_mode(ob, dg);
436         }
437       }
438
439       dg = next_dg;
440     }
441   }
442   else { /* ob->defbase is empty... */
443     /* remove all dverts */
444     if (ob->type == OB_MESH) {
445       Mesh *me = ob->data;
446       CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
447       me->dvert = NULL;
448     }
449     else if (ob->type == OB_LATTICE) {
450       Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
451       if (lt->dvert) {
452         MEM_freeN(lt->dvert);
453         lt->dvert = NULL;
454       }
455     }
456     /* Fix counters/indices */
457     ob->actdef = 0;
458   }
459 }
460
461 /**
462  * Remove all vgroups from object. Work in Object and Edit modes.
463  */
464 void BKE_object_defgroup_remove_all(struct Object *ob)
465 {
466   BKE_object_defgroup_remove_all_ex(ob, false);
467 }
468
469 /**
470  * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
471  * Returns null if no remapping is required.
472  * The returned array has to be freed.
473  */
474 int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
475 {
476   /* Build src to merged mapping of vgroup indices. */
477   if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
478     *r_map_len = 0;
479     return NULL;
480   }
481
482   bDeformGroup *dg_src;
483   *r_map_len = BLI_listbase_count(&ob_src->defbase);
484   int *vgroup_index_map = MEM_malloc_arrayN(
485       *r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
486   bool is_vgroup_remap_needed = false;
487   int i;
488
489   for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
490     vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
491     is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
492   }
493
494   if (!is_vgroup_remap_needed) {
495     MEM_freeN(vgroup_index_map);
496     vgroup_index_map = NULL;
497     *r_map_len = 0;
498   }
499
500   return vgroup_index_map;
501 }
502
503 void BKE_object_defgroup_index_map_apply(MDeformVert *dvert,
504                                          int dvert_len,
505                                          const int *map,
506                                          int map_len)
507 {
508   if (map == NULL || map_len == 0) {
509     return;
510   }
511
512   MDeformVert *dv = dvert;
513   for (int i = 0; i < dvert_len; i++, dv++) {
514     int totweight = dv->totweight;
515     for (int j = 0; j < totweight; j++) {
516       int def_nr = dv->dw[j].def_nr;
517       if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
518         dv->dw[j].def_nr = map[def_nr];
519       }
520       else {
521         totweight--;
522         dv->dw[j] = dv->dw[totweight];
523         j--;
524       }
525     }
526     if (totweight != dv->totweight) {
527       if (totweight) {
528         dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
529       }
530       else {
531         MEM_SAFE_FREE(dv->dw);
532       }
533       dv->totweight = totweight;
534     }
535   }
536 }
537
538 /**
539  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
540  *
541  * \return True if the id type supports weights.
542  */
543 bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
544 {
545   if (id) {
546     switch (GS(id->name)) {
547       case ID_ME: {
548         Mesh *me = (Mesh *)id;
549         *dvert_arr = me->dvert;
550         *dvert_tot = me->totvert;
551         return true;
552       }
553       case ID_LT: {
554         Lattice *lt = object_defgroup_lattice_get(id);
555         *dvert_arr = lt->dvert;
556         *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
557         return true;
558       }
559       default:
560         break;
561     }
562   }
563
564   *dvert_arr = NULL;
565   *dvert_tot = 0;
566   return false;
567 }
568 /** \} */
569
570 /* --- functions for getting vgroup aligned maps --- */
571
572 /**
573  * gets the status of "flag" for each bDeformGroup
574  * in ob->defbase and returns an array containing them
575  */
576 bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
577 {
578   bool is_locked = false;
579   int i;
580   //int defbase_tot = BLI_listbase_count(&ob->defbase);
581   bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
582   bDeformGroup *defgroup;
583
584   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
585        defgroup = defgroup->next, i++) {
586     lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
587     is_locked |= lock_flags[i];
588   }
589   if (is_locked) {
590     return lock_flags;
591   }
592
593   MEM_freeN(lock_flags);
594   return NULL;
595 }
596
597 bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
598 {
599   bDeformGroup *dg;
600   ModifierData *md;
601   bool *defgroup_validmap;
602   GHash *gh;
603   int i, step1 = 1;
604   //int defbase_tot = BLI_listbase_count(&ob->defbase);
605   VirtualModifierData virtualModifierData;
606
607   if (BLI_listbase_is_empty(&ob->defbase)) {
608     return NULL;
609   }
610
611   gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
612
613   /* add all names to a hash table */
614   for (dg = ob->defbase.first; dg; dg = dg->next) {
615     BLI_ghash_insert(gh, dg->name, NULL);
616   }
617
618   BLI_assert(BLI_ghash_len(gh) == defbase_tot);
619
620   /* now loop through the armature modifiers and identify deform bones */
621   for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0),
622       modifiers_getVirtualModifierList(ob, &virtualModifierData) :
623                                      md->next) {
624     if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) {
625       continue;
626     }
627
628     if (md->type == eModifierType_Armature) {
629       ArmatureModifierData *amd = (ArmatureModifierData *)md;
630
631       if (amd->object && amd->object->pose) {
632         bPose *pose = amd->object->pose;
633         bPoseChannel *chan;
634
635         for (chan = pose->chanbase.first; chan; chan = chan->next) {
636           void **val_p;
637           if (chan->bone->flag & BONE_NO_DEFORM) {
638             continue;
639           }
640
641           val_p = BLI_ghash_lookup_p(gh, chan->name);
642           if (val_p) {
643             *val_p = POINTER_FROM_INT(1);
644           }
645         }
646       }
647     }
648   }
649
650   defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
651
652   /* add all names to a hash table */
653   for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
654     defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
655   }
656
657   BLI_assert(i == BLI_ghash_len(gh));
658
659   BLI_ghash_free(gh, NULL, NULL);
660
661   return defgroup_validmap;
662 }
663
664 /* Returns total selected vgroups,
665  * wpi.defbase_sel is assumed malloc'd, all values are set */
666 bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
667 {
668   bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
669   bDeformGroup *defgroup;
670   unsigned int i;
671   Object *armob = BKE_object_pose_armature_get(ob);
672   (*r_dg_flags_sel_tot) = 0;
673
674   if (armob) {
675     bPose *pose = armob->pose;
676     for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
677          defgroup = defgroup->next, i++) {
678       bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
679       if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
680         dg_selection[i] = true;
681         (*r_dg_flags_sel_tot) += 1;
682       }
683       else {
684         dg_selection[i] = false;
685       }
686     }
687   }
688   else {
689     memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
690   }
691
692   return dg_selection;
693 }
694
695 /* Marks mirror vgroups in output and counts them. Output and counter assumed to be already initialized.
696  * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
697  */
698 void BKE_object_defgroup_mirror_selection(struct Object *ob,
699                                           int defbase_tot,
700                                           const bool *dg_selection,
701                                           bool *dg_flags_sel,
702                                           int *r_dg_flags_sel_tot)
703 {
704   bDeformGroup *defgroup;
705   unsigned int i;
706   int i_mirr;
707
708   for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup;
709        defgroup = defgroup->next, i++) {
710     if (dg_selection[i]) {
711       char name_flip[MAXBONENAME];
712
713       BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
714       i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
715
716       if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
717         dg_flags_sel[i_mirr] = true;
718         (*r_dg_flags_sel_tot) += 1;
719       }
720     }
721   }
722 }
723
724 /**
725  * Return the subset type of the Vertex Group Selection
726  */
727 bool *BKE_object_defgroup_subset_from_select_type(Object *ob,
728                                                   eVGroupSelect subset_type,
729                                                   int *r_defgroup_tot,
730                                                   int *r_subset_count)
731 {
732   bool *defgroup_validmap = NULL;
733   *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
734
735   switch (subset_type) {
736     case WT_VGROUP_ACTIVE: {
737       const int def_nr_active = ob->actdef - 1;
738       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
739       memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
740       if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
741         *r_subset_count = 1;
742         defgroup_validmap[def_nr_active] = true;
743       }
744       else {
745         *r_subset_count = 0;
746       }
747       break;
748     }
749     case WT_VGROUP_BONE_SELECT: {
750       defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
751       break;
752     }
753     case WT_VGROUP_BONE_DEFORM: {
754       int i;
755       defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
756       *r_subset_count = 0;
757       for (i = 0; i < *r_defgroup_tot; i++) {
758         if (defgroup_validmap[i] == true) {
759           *r_subset_count += 1;
760         }
761       }
762       break;
763     }
764     case WT_VGROUP_BONE_DEFORM_OFF: {
765       int i;
766       defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
767       *r_subset_count = 0;
768       for (i = 0; i < *r_defgroup_tot; i++) {
769         defgroup_validmap[i] = !defgroup_validmap[i];
770         if (defgroup_validmap[i] == true) {
771           *r_subset_count += 1;
772         }
773       }
774       break;
775     }
776     case WT_VGROUP_ALL:
777     default: {
778       defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
779       memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
780       *r_subset_count = *r_defgroup_tot;
781       break;
782     }
783   }
784
785   return defgroup_validmap;
786 }
787
788 /**
789  * store indices from the defgroup_validmap (faster lookups in some cases)
790  */
791 void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap,
792                                                const int defgroup_tot,
793                                                int *r_defgroup_subset_map)
794 {
795   int i, j = 0;
796   for (i = 0; i < defgroup_tot; i++) {
797     if (defgroup_validmap[i]) {
798       r_defgroup_subset_map[j++] = i;
799     }
800   }
801 }