Merge branch 'blender2.7'
[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 \ingroup bke
18  */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "MEM_guardedalloc.h"
24
25 #include "BLT_translation.h"
26
27 #include "BLI_utildefines.h"
28 #include "BLI_ghash.h"
29 #include "BLI_listbase.h"
30 #include "BLI_string_utils.h"
31
32 #include "DNA_armature_types.h"
33 #include "DNA_cloth_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_lattice_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_object_force_types.h"
41 #include "DNA_particle_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BKE_action.h"
45 #include "BKE_deform.h"
46 #include "BKE_editmesh.h"
47 #include "BKE_object_deform.h"  /* own include */
48 #include "BKE_object.h"
49 #include "BKE_mesh.h"
50 #include "BKE_modifier.h"
51 #include "BKE_gpencil.h"
52
53 /** \name Misc helpers
54  * \{ */
55
56 static Lattice *object_defgroup_lattice_get(ID *id)
57 {
58         Lattice *lt = (Lattice *)id;
59         BLI_assert(GS(id->name) == ID_LT);
60         return (lt->editlatt) ? lt->editlatt->latt : lt;
61 }
62
63 /**
64  * Update users of vgroups from this object, according to given map.
65  *
66  * Use it when you remove or reorder vgroups in the object.
67  *
68  * \param map: an array mapping old indices to new indices.
69  */
70 void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
71 {
72         ModifierData *md;
73         ParticleSystem *psys;
74         int a;
75
76         /* these cases don't use names to refer to vertex groups, so when
77          * they get removed the numbers get out of sync, this corrects that */
78
79         if (ob->soft) {
80                 ob->soft->vertgroup = map[ob->soft->vertgroup];
81         }
82
83         for (md = ob->modifiers.first; md; md = md->next) {
84                 if (md->type == eModifierType_Explode) {
85                         ExplodeModifierData *emd = (ExplodeModifierData *)md;
86                         emd->vgroup = map[emd->vgroup];
87                 }
88                 else if (md->type == eModifierType_Cloth) {
89                         ClothModifierData *clmd = (ClothModifierData *)md;
90                         ClothSimSettings *clsim = clmd->sim_parms;
91
92                         if (clsim) {
93                                 clsim->vgroup_mass = map[clsim->vgroup_mass];
94                                 clsim->vgroup_bend = map[clsim->vgroup_bend];
95                                 clsim->vgroup_struct = map[clsim->vgroup_struct];
96                         }
97                 }
98         }
99
100         for (psys = ob->particlesystem.first; psys; psys = psys->next) {
101                 for (a = 0; a < PSYS_TOT_VG; a++) {
102                         psys->vgroup[a] = map[psys->vgroup[a]];
103                 }
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, "lattice deformVert");
150                 return lt->dvert;
151         }
152
153         return NULL;
154 }
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
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         /* remove all dverts */
291         if (BLI_listbase_is_empty(&ob->defbase)) {
292                 if (ob->type == OB_MESH) {
293                         Mesh *me = ob->data;
294                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
295                         me->dvert = NULL;
296                 }
297                 else if (ob->type == OB_LATTICE) {
298                         Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
299                         if (lt->dvert) {
300                                 MEM_freeN(lt->dvert);
301                                 lt->dvert = NULL;
302                         }
303                 }
304         }
305         else if (ob->actdef < 1) {  /* Keep a valid active index if we still have some vgroups. */
306                 ob->actdef = 1;
307         }
308 }
309
310 static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg)
311 {
312         MDeformVert *dvert_array = NULL;
313         int dvert_tot = 0;
314         const int def_nr = BLI_findindex(&ob->defbase, dg);
315
316         BLI_assert(def_nr != -1);
317
318         BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot);
319
320         if (dvert_array) {
321                 int i, j;
322                 MDeformVert *dv;
323                 for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) {
324                         MDeformWeight *dw;
325
326                         dw = defvert_find_index(dv, def_nr);
327                         defvert_remove_group(dv, dw); /* dw can be NULL */
328
329                         /* inline, make into a function if anything else needs to do this */
330                         for (j = 0; j < dv->totweight; j++) {
331                                 if (dv->dw[j].def_nr > def_nr) {
332                                         dv->dw[j].def_nr--;
333                                 }
334                         }
335                         /* done */
336                 }
337         }
338
339         object_defgroup_remove_common(ob, dg, def_nr);
340 }
341
342 static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg)
343 {
344         int i;
345         const int def_nr = BLI_findindex(&ob->defbase, dg);
346
347         BLI_assert(def_nr != -1);
348
349         /* Make sure that no verts are using this group - if none were removed, we can skip next per-vert update. */
350         if (!BKE_object_defgroup_clear(ob, dg, false)) {
351                 /* Nothing to do. */
352         }
353         /* Else, make sure that any groups with higher indices are adjusted accordingly */
354         else if (ob->type == OB_MESH) {
355                 Mesh *me = ob->data;
356                 BMEditMesh *em = me->edit_mesh;
357                 const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
358
359                 BMIter iter;
360                 BMVert *eve;
361                 MDeformVert *dvert;
362
363                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
364                         dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
365
366                         if (dvert) {
367                                 for (i = 0; i < dvert->totweight; i++) {
368                                         if (dvert->dw[i].def_nr > def_nr) {
369                                                 dvert->dw[i].def_nr--;
370                                         }
371                                 }
372                         }
373                 }
374         }
375         else if (ob->type == OB_LATTICE) {
376                 Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt;
377                 BPoint *bp;
378                 MDeformVert *dvert = lt->dvert;
379                 int a, tot;
380
381                 if (dvert) {
382                         tot = lt->pntsu * lt->pntsv * lt->pntsw;
383                         for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) {
384                                 for (i = 0; i < dvert->totweight; i++) {
385                                         if (dvert->dw[i].def_nr > def_nr) {
386                                                 dvert->dw[i].def_nr--;
387                                         }
388                                 }
389                         }
390                 }
391         }
392
393         object_defgroup_remove_common(ob, dg, def_nr);
394 }
395
396 /**
397  * Remove given vgroup from object. Work in Object and Edit modes.
398  */
399 void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
400 {
401         if (ob->type == OB_GPENCIL) {
402                 BKE_gpencil_vgroup_remove(ob, defgroup);
403         }
404         else {
405                 if (BKE_object_is_in_editmode_vgroup(ob))
406                         object_defgroup_remove_edit_mode(ob, defgroup);
407                 else
408                         object_defgroup_remove_object_mode(ob, defgroup);
409
410                 BKE_object_batch_cache_dirty_tag(ob);
411         }
412 }
413
414 /**
415  * Remove all vgroups from object. Work in Object and Edit modes.
416  * When only_unlocked=true, locked vertex groups are not removed.
417  */
418 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
419 {
420         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
421         const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
422
423         if (dg) {
424                 while (dg) {
425                         bDeformGroup *next_dg = dg->next;
426
427                         if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
428                                 if (edit_mode)
429                                         object_defgroup_remove_edit_mode(ob, dg);
430                                 else
431                                         object_defgroup_remove_object_mode(ob, dg);
432                         }
433
434                         dg = next_dg;
435                 }
436         }
437         else {  /* ob->defbase is empty... */
438                 /* remove all dverts */
439                 if (ob->type == OB_MESH) {
440                         Mesh *me = ob->data;
441                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
442                         me->dvert = NULL;
443                 }
444                 else if (ob->type == OB_LATTICE) {
445                         Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
446                         if (lt->dvert) {
447                                 MEM_freeN(lt->dvert);
448                                 lt->dvert = NULL;
449                         }
450                 }
451                 /* Fix counters/indices */
452                 ob->actdef = 0;
453         }
454 }
455
456 /**
457  * Remove all vgroups from object. Work in Object and Edit modes.
458  */
459 void BKE_object_defgroup_remove_all(struct Object *ob)
460 {
461         BKE_object_defgroup_remove_all_ex(ob, false);
462 }
463
464 /**
465  * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
466  * Returns null if no remapping is required.
467  * The returned array has to be freed.
468  */
469 int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
470 {
471         /* Build src to merged mapping of vgroup indices. */
472         if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
473                 *r_map_len = 0;
474                 return NULL;
475         }
476
477         bDeformGroup *dg_src;
478         *r_map_len = BLI_listbase_count(&ob_src->defbase);
479         int *vgroup_index_map = MEM_malloc_arrayN(*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, int dvert_len, const int *map, int map_len)
498 {
499         if (map == NULL || map_len == 0) {
500                 return;
501         }
502
503         MDeformVert *dv = dvert;
504         for (int i = 0; i < dvert_len; i++, dv++) {
505                 int totweight = dv->totweight;
506                 for (int j = 0; j < totweight; j++) {
507                         int def_nr = dv->dw[j].def_nr;
508                         if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
509                                 dv->dw[j].def_nr = map[def_nr];
510                         }
511                         else {
512                                 totweight--;
513                                 dv->dw[j] = dv->dw[totweight];
514                                 j--;
515                         }
516                 }
517                 if (totweight != dv->totweight) {
518                         if (totweight) {
519                                 dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
520                         }
521                         else {
522                                 MEM_SAFE_FREE(dv->dw);
523                         }
524                         dv->totweight = totweight;
525                 }
526         }
527 }
528
529 /**
530  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
531  *
532  * \return True if the id type supports weights.
533  */
534 bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
535 {
536         if (id) {
537                 switch (GS(id->name)) {
538                         case ID_ME:
539                         {
540                                 Mesh *me = (Mesh *)id;
541                                 *dvert_arr = me->dvert;
542                                 *dvert_tot = me->totvert;
543                                 return true;
544                         }
545                         case ID_LT:
546                         {
547                                 Lattice *lt = object_defgroup_lattice_get(id);
548                                 *dvert_arr = lt->dvert;
549                                 *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
550                                 return true;
551                         }
552                         default:
553                                 break;
554                 }
555         }
556
557         *dvert_arr = NULL;
558         *dvert_tot = 0;
559         return false;
560 }
561 /** \} */
562
563 /* --- functions for getting vgroup aligned maps --- */
564
565 /**
566  * gets the status of "flag" for each bDeformGroup
567  * in ob->defbase and returns an array containing them
568  */
569 bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
570 {
571         bool is_locked = false;
572         int i;
573         //int defbase_tot = BLI_listbase_count(&ob->defbase);
574         bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
575         bDeformGroup *defgroup;
576
577         for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
578                 lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
579                 is_locked |= lock_flags[i];
580         }
581         if (is_locked) {
582                 return lock_flags;
583         }
584
585         MEM_freeN(lock_flags);
586         return NULL;
587 }
588
589 bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
590 {
591         bDeformGroup *dg;
592         ModifierData *md;
593         bool *defgroup_validmap;
594         GHash *gh;
595         int i, step1 = 1;
596         //int defbase_tot = BLI_listbase_count(&ob->defbase);
597         VirtualModifierData virtualModifierData;
598
599         if (BLI_listbase_is_empty(&ob->defbase)) {
600                 return NULL;
601         }
602
603         gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
604
605         /* add all names to a hash table */
606         for (dg = ob->defbase.first; dg; dg = dg->next) {
607                 BLI_ghash_insert(gh, dg->name, NULL);
608         }
609
610         BLI_assert(BLI_ghash_len(gh) == defbase_tot);
611
612         /* now loop through the armature modifiers and identify deform bones */
613         for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
614                 if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
615                         continue;
616
617                 if (md->type == eModifierType_Armature) {
618                         ArmatureModifierData *amd = (ArmatureModifierData *) md;
619
620                         if (amd->object && amd->object->pose) {
621                                 bPose *pose = amd->object->pose;
622                                 bPoseChannel *chan;
623
624                                 for (chan = pose->chanbase.first; chan; chan = chan->next) {
625                                         void **val_p;
626                                         if (chan->bone->flag & BONE_NO_DEFORM)
627                                                 continue;
628
629                                         val_p = BLI_ghash_lookup_p(gh, chan->name);
630                                         if (val_p) {
631                                                 *val_p = POINTER_FROM_INT(1);
632                                         }
633                                 }
634                         }
635                 }
636         }
637
638         defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
639
640         /* add all names to a hash table */
641         for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
642                 defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
643         }
644
645         BLI_assert(i == BLI_ghash_len(gh));
646
647         BLI_ghash_free(gh, NULL, NULL);
648
649         return defgroup_validmap;
650 }
651
652 /* Returns total selected vgroups,
653  * wpi.defbase_sel is assumed malloc'd, all values are set */
654 bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
655 {
656         bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
657         bDeformGroup *defgroup;
658         unsigned int i;
659         Object *armob = BKE_object_pose_armature_get(ob);
660         (*r_dg_flags_sel_tot) = 0;
661
662         if (armob) {
663                 bPose *pose = armob->pose;
664                 for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
665                         bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
666                         if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
667                                 dg_selection[i] = true;
668                                 (*r_dg_flags_sel_tot) += 1;
669                         }
670                         else {
671                                 dg_selection[i] = false;
672                         }
673                 }
674         }
675         else {
676                 memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
677         }
678
679         return dg_selection;
680 }
681
682 /* Marks mirror vgroups in output and counts them. Output and counter assumed to be already initialized.
683  * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
684  */
685 void BKE_object_defgroup_mirror_selection(
686         struct Object *ob, int defbase_tot, const bool *dg_selection,
687         bool *dg_flags_sel, int *r_dg_flags_sel_tot)
688 {
689         bDeformGroup *defgroup;
690         unsigned int i;
691         int i_mirr;
692
693         for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
694                 if (dg_selection[i]) {
695                         char name_flip[MAXBONENAME];
696
697                         BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
698                         i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
699
700                         if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
701                                 dg_flags_sel[i_mirr] = true;
702                                 (*r_dg_flags_sel_tot) += 1;
703                         }
704                 }
705         }
706 }
707
708 /**
709  * Return the subset type of the Vertex Group Selection
710  */
711 bool *BKE_object_defgroup_subset_from_select_type(
712         Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
713 {
714         bool *defgroup_validmap = NULL;
715         *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
716
717         switch (subset_type) {
718                 case WT_VGROUP_ACTIVE:
719                 {
720                         const int def_nr_active = ob->actdef - 1;
721                         defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
722                         memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
723                         if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
724                                 *r_subset_count = 1;
725                                 defgroup_validmap[def_nr_active] = true;
726                         }
727                         else {
728                                 *r_subset_count = 0;
729                         }
730                         break;
731                 }
732                 case WT_VGROUP_BONE_SELECT:
733                 {
734                         defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
735                         break;
736                 }
737                 case WT_VGROUP_BONE_DEFORM:
738                 {
739                         int i;
740                         defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
741                         *r_subset_count = 0;
742                         for (i = 0; i < *r_defgroup_tot; i++) {
743                                 if (defgroup_validmap[i] == true) {
744                                         *r_subset_count += 1;
745                                 }
746                         }
747                         break;
748                 }
749                 case WT_VGROUP_BONE_DEFORM_OFF:
750                 {
751                         int i;
752                         defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
753                         *r_subset_count = 0;
754                         for (i = 0; i < *r_defgroup_tot; i++) {
755                                 defgroup_validmap[i] = !defgroup_validmap[i];
756                                 if (defgroup_validmap[i] == true) {
757                                         *r_subset_count += 1;
758                                 }
759                         }
760                         break;
761                 }
762                 case WT_VGROUP_ALL:
763                 default:
764                 {
765                         defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
766                         memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
767                         *r_subset_count = *r_defgroup_tot;
768                         break;
769                 }
770         }
771
772         return defgroup_validmap;
773 }
774
775 /**
776  * store indices from the defgroup_validmap (faster lookups in some cases)
777  */
778 void BKE_object_defgroup_subset_to_index_array(
779         const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
780 {
781         int i, j = 0;
782         for (i = 0; i < defgroup_tot; i++) {
783                 if (defgroup_validmap[i]) {
784                         r_defgroup_subset_map[j++] = i;
785                 }
786         }
787 }