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