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 blender/blenkernel/intern/object_deform.c
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
110 /** \name Group creation
111  * \{ */
112
113 /**
114  * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all!
115  */
116 bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name)
117 {
118         bDeformGroup *defgroup;
119
120         if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
121                 return NULL;
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, "lattice deformVert");
151                 return lt->dvert;
152         }
153
154         return NULL;
155 }
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_btmesh) {
178                         BMEditMesh *em = me->edit_btmesh;
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
260 /** \name Group removal
261  * \{ */
262
263 static void object_defgroup_remove_update_users(Object *ob, const int idx)
264 {
265         int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1;
266         int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
267
268         map[idx] = map[0] = 0;
269         for (i = 1; i < idx; i++) {
270                 map[i] = i;
271         }
272         for (i = idx + 1; i < defbase_tot; i++) {
273                 map[i] = i - 1;
274         }
275
276         BKE_object_defgroup_remap_update_users(ob, map);
277         MEM_freeN(map);
278 }
279
280 static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr)
281 {
282         object_defgroup_remove_update_users(ob, def_nr + 1);
283
284         /* Remove the group */
285         BLI_freelinkN(&ob->defbase, dg);
286
287         /* Update the active deform index if necessary */
288         if (ob->actdef > def_nr)
289                 ob->actdef--;
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_btmesh;
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                 else
409                         object_defgroup_remove_object_mode(ob, defgroup);
410
411                 BKE_object_batch_cache_dirty_tag(ob);
412         }
413 }
414
415 /**
416  * Remove all vgroups from object. Work in Object and Edit modes.
417  * When only_unlocked=true, locked vertex groups are not removed.
418  */
419 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
420 {
421         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
422         const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
423
424         if (dg) {
425                 while (dg) {
426                         bDeformGroup *next_dg = dg->next;
427
428                         if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
429                                 if (edit_mode)
430                                         object_defgroup_remove_edit_mode(ob, dg);
431                                 else
432                                         object_defgroup_remove_object_mode(ob, dg);
433                         }
434
435                         dg = next_dg;
436                 }
437         }
438         else {  /* ob->defbase is empty... */
439                 /* remove all dverts */
440                 if (ob->type == OB_MESH) {
441                         Mesh *me = ob->data;
442                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
443                         me->dvert = NULL;
444                 }
445                 else if (ob->type == OB_LATTICE) {
446                         Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
447                         if (lt->dvert) {
448                                 MEM_freeN(lt->dvert);
449                                 lt->dvert = NULL;
450                         }
451                 }
452                 /* Fix counters/indices */
453                 ob->actdef = 0;
454         }
455 }
456
457 /**
458  * Remove all vgroups from object. Work in Object and Edit modes.
459  */
460 void BKE_object_defgroup_remove_all(struct Object *ob)
461 {
462         BKE_object_defgroup_remove_all_ex(ob, false);
463 }
464
465 /**
466  * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
467  * Returns null if no remapping is required.
468  * The returned array has to be freed.
469  */
470 int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
471 {
472         /* Build src to merged mapping of vgroup indices. */
473         if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
474                 *r_map_len = 0;
475                 return NULL;
476         }
477
478         bDeformGroup *dg_src;
479         *r_map_len = BLI_listbase_count(&ob_src->defbase);
480         int *vgroup_index_map = MEM_malloc_arrayN(*r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
481         bool is_vgroup_remap_needed = false;
482         int i;
483
484         for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
485                 vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
486                 is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
487         }
488
489         if (!is_vgroup_remap_needed) {
490                 MEM_freeN(vgroup_index_map);
491                 vgroup_index_map = NULL;
492                 *r_map_len = 0;
493         }
494
495         return vgroup_index_map;
496 }
497
498 void BKE_object_defgroup_index_map_apply(MDeformVert *dvert, int dvert_len, const int *map, int map_len)
499 {
500         if (map == NULL || map_len == 0) {
501                 return;
502         }
503
504         MDeformVert *dv = dvert;
505         for (int i = 0; i < dvert_len; i++, dv++) {
506                 int totweight = dv->totweight;
507                 for (int j = 0; j < totweight; j++) {
508                         int def_nr = dv->dw[j].def_nr;
509                         if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
510                                 dv->dw[j].def_nr = map[def_nr];
511                         }
512                         else {
513                                 totweight--;
514                                 dv->dw[j] = dv->dw[totweight];
515                                 j--;
516                         }
517                 }
518                 if (totweight != dv->totweight) {
519                         if (totweight) {
520                                 dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
521                         }
522                         else {
523                                 MEM_SAFE_FREE(dv->dw);
524                         }
525                         dv->totweight = totweight;
526                 }
527         }
528 }
529
530 /**
531  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
532  *
533  * \return True if the id type supports weights.
534  */
535 bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
536 {
537         if (id) {
538                 switch (GS(id->name)) {
539                         case ID_ME:
540                         {
541                                 Mesh *me = (Mesh *)id;
542                                 *dvert_arr = me->dvert;
543                                 *dvert_tot = me->totvert;
544                                 return true;
545                         }
546                         case ID_LT:
547                         {
548                                 Lattice *lt = object_defgroup_lattice_get(id);
549                                 *dvert_arr = lt->dvert;
550                                 *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
551                                 return true;
552                         }
553                         default:
554                                 break;
555                 }
556         }
557
558         *dvert_arr = NULL;
559         *dvert_tot = 0;
560         return false;
561 }
562 /** \} */
563
564 /* --- functions for getting vgroup aligned maps --- */
565
566 /**
567  * gets the status of "flag" for each bDeformGroup
568  * in ob->defbase and returns an array containing them
569  */
570 bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot)
571 {
572         bool is_locked = false;
573         int i;
574         //int defbase_tot = BLI_listbase_count(&ob->defbase);
575         bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags");
576         bDeformGroup *defgroup;
577
578         for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
579                 lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
580                 is_locked |= lock_flags[i];
581         }
582         if (is_locked) {
583                 return lock_flags;
584         }
585
586         MEM_freeN(lock_flags);
587         return NULL;
588 }
589
590 bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
591 {
592         bDeformGroup *dg;
593         ModifierData *md;
594         bool *defgroup_validmap;
595         GHash *gh;
596         int i, step1 = 1;
597         //int defbase_tot = BLI_listbase_count(&ob->defbase);
598         VirtualModifierData virtualModifierData;
599
600         if (BLI_listbase_is_empty(&ob->defbase)) {
601                 return NULL;
602         }
603
604         gh = BLI_ghash_str_new_ex(__func__, defbase_tot);
605
606         /* add all names to a hash table */
607         for (dg = ob->defbase.first; dg; dg = dg->next) {
608                 BLI_ghash_insert(gh, dg->name, NULL);
609         }
610
611         BLI_assert(BLI_ghash_len(gh) == defbase_tot);
612
613         /* now loop through the armature modifiers and identify deform bones */
614         for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
615                 if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
616                         continue;
617
618                 if (md->type == eModifierType_Armature) {
619                         ArmatureModifierData *amd = (ArmatureModifierData *) md;
620
621                         if (amd->object && amd->object->pose) {
622                                 bPose *pose = amd->object->pose;
623                                 bPoseChannel *chan;
624
625                                 for (chan = pose->chanbase.first; chan; chan = chan->next) {
626                                         void **val_p;
627                                         if (chan->bone->flag & BONE_NO_DEFORM)
628                                                 continue;
629
630                                         val_p = BLI_ghash_lookup_p(gh, chan->name);
631                                         if (val_p) {
632                                                 *val_p = POINTER_FROM_INT(1);
633                                         }
634                                 }
635                         }
636                 }
637         }
638
639         defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map");
640
641         /* add all names to a hash table */
642         for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
643                 defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
644         }
645
646         BLI_assert(i == BLI_ghash_len(gh));
647
648         BLI_ghash_free(gh, NULL, NULL);
649
650         return defgroup_validmap;
651 }
652
653 /* Returns total selected vgroups,
654  * wpi.defbase_sel is assumed malloc'd, all values are set */
655 bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
656 {
657         bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__);
658         bDeformGroup *defgroup;
659         unsigned int i;
660         Object *armob = BKE_object_pose_armature_get(ob);
661         (*r_dg_flags_sel_tot) = 0;
662
663         if (armob) {
664                 bPose *pose = armob->pose;
665                 for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
666                         bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name);
667                         if (pchan && (pchan->bone->flag & BONE_SELECTED)) {
668                                 dg_selection[i] = true;
669                                 (*r_dg_flags_sel_tot) += 1;
670                         }
671                         else {
672                                 dg_selection[i] = false;
673                         }
674                 }
675         }
676         else {
677                 memset(dg_selection, false, sizeof(*dg_selection) * defbase_tot);
678         }
679
680         return dg_selection;
681 }
682
683 /* Marks mirror vgroups in output and counts them. Output and counter assumed to be already initialized.
684  * Designed to be usable after BKE_object_defgroup_selected_get to extend selection to mirror.
685  */
686 void BKE_object_defgroup_mirror_selection(
687         struct Object *ob, int defbase_tot, const bool *dg_selection,
688         bool *dg_flags_sel, int *r_dg_flags_sel_tot)
689 {
690         bDeformGroup *defgroup;
691         unsigned int i;
692         int i_mirr;
693
694         for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
695                 if (dg_selection[i]) {
696                         char name_flip[MAXBONENAME];
697
698                         BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
699                         i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
700
701                         if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
702                                 dg_flags_sel[i_mirr] = true;
703                                 (*r_dg_flags_sel_tot) += 1;
704                         }
705                 }
706         }
707 }
708
709 /**
710  * Return the subset type of the Vertex Group Selection
711  */
712 bool *BKE_object_defgroup_subset_from_select_type(
713         Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
714 {
715         bool *defgroup_validmap = NULL;
716         *r_defgroup_tot = BLI_listbase_count(&ob->defbase);
717
718         switch (subset_type) {
719                 case WT_VGROUP_ACTIVE:
720                 {
721                         const int def_nr_active = ob->actdef - 1;
722                         defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
723                         memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap));
724                         if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) {
725                                 *r_subset_count = 1;
726                                 defgroup_validmap[def_nr_active] = true;
727                         }
728                         else {
729                                 *r_subset_count = 0;
730                         }
731                         break;
732                 }
733                 case WT_VGROUP_BONE_SELECT:
734                 {
735                         defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count);
736                         break;
737                 }
738                 case WT_VGROUP_BONE_DEFORM:
739                 {
740                         int i;
741                         defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
742                         *r_subset_count = 0;
743                         for (i = 0; i < *r_defgroup_tot; i++) {
744                                 if (defgroup_validmap[i] == true) {
745                                         *r_subset_count += 1;
746                                 }
747                         }
748                         break;
749                 }
750                 case WT_VGROUP_BONE_DEFORM_OFF:
751                 {
752                         int i;
753                         defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot);
754                         *r_subset_count = 0;
755                         for (i = 0; i < *r_defgroup_tot; i++) {
756                                 defgroup_validmap[i] = !defgroup_validmap[i];
757                                 if (defgroup_validmap[i] == true) {
758                                         *r_subset_count += 1;
759                                 }
760                         }
761                         break;
762                 }
763                 case WT_VGROUP_ALL:
764                 default:
765                 {
766                         defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__);
767                         memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap));
768                         *r_subset_count = *r_defgroup_tot;
769                         break;
770                 }
771         }
772
773         return defgroup_validmap;
774 }
775
776 /**
777  * store indices from the defgroup_validmap (faster lookups in some cases)
778  */
779 void BKE_object_defgroup_subset_to_index_array(
780         const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
781 {
782         int i, j = 0;
783         for (i = 0; i < defgroup_tot; i++) {
784                 if (defgroup_validmap[i]) {
785                         r_defgroup_subset_map[j++] = i;
786                 }
787         }
788 }