b50c526ef3d03b31d2ca0fcde171eb5af87f951e
[blender.git] / source / blender / editors / object / object_vgroup.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/editors/object/object_vgroup.c
31  *  \ingroup edobj
32  */
33
34
35 #include <string.h>
36 #include <stddef.h>
37 #include <math.h>
38 #include <assert.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_cloth_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_lattice_types.h"
45 #include "DNA_meshdata_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_modifier_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_object_force.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_particle_types.h"
52
53 #include "BLI_blenlib.h"
54 #include "BLI_cellalloc.h"
55 #include "BLI_utildefines.h"
56
57 #include "BKE_context.h"
58 #include "BKE_customdata.h"
59 #include "BKE_deform.h"
60 #include "BKE_depsgraph.h"
61 #include "BKE_global.h"
62 #include "BKE_mesh.h"
63 #include "BKE_tessmesh.h"
64 #include "BKE_report.h"
65
66 #include "RNA_access.h"
67 #include "RNA_define.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71
72 #include "ED_mesh.h"
73
74 #include "UI_resources.h"
75
76 #include "object_intern.h"
77
78 /************************ Exported Functions **********************/
79 static void vgroup_remap_update_users(Object *ob, int *map);
80 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
81 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
82
83 static Lattice *vgroup_edit_lattice(Object *ob)
84 {
85         Lattice *lt= ob->data;
86         BLI_assert(ob->type==OB_LATTICE);
87         return (lt->editlatt)? lt->editlatt->latt: lt;
88 }
89
90 int ED_vgroup_object_is_edit_mode(Object *ob)
91 {
92         if(ob->type == OB_MESH)
93                 return (((Mesh*)ob->data)->edit_btmesh != NULL);
94         else if(ob->type == OB_LATTICE)
95                 return (((Lattice*)ob->data)->editlatt != NULL);
96
97         return 0;
98 }
99
100 bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
101 {
102         bDeformGroup *defgroup;
103         
104         if(!ob || !ELEM(ob->type, OB_MESH, OB_LATTICE))
105                 return NULL;
106         
107         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
108
109         BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
110
111         BLI_addtail(&ob->defbase, defgroup);
112         defgroup_unique_name(defgroup, ob);
113
114         ob->actdef = BLI_countlist(&ob->defbase);
115
116         return defgroup;
117 }
118
119 bDeformGroup *ED_vgroup_add(Object *ob) 
120 {
121         return ED_vgroup_add_name(ob, "Group");
122 }
123
124 void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) 
125 {
126         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
127
128         while (dg) {
129                 if (dg == defgroup)
130                         break;
131                 dg = dg->next;
132         }
133
134         if (dg == NULL)
135                 return;
136
137         if(ED_vgroup_object_is_edit_mode(ob))
138                 vgroup_delete_edit_mode(ob, dg);
139         else
140                 vgroup_delete_object_mode(ob, dg);
141 }
142
143 void ED_vgroup_data_create(ID *id)
144 {
145         /* create deform verts */
146
147         if(GS(id->name)==ID_ME) {
148                 Mesh *me= (Mesh *)id;
149                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
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         }
155 }
156
157 static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot)
158 {
159         if(id) {
160                 switch(GS(id->name)) {
161                         case ID_ME:
162                         {
163                                 Mesh *me = (Mesh *)id;
164
165                                 if(me->edit_btmesh) {
166                                         BMEditMesh *em = me->edit_btmesh;
167                                         BMIter iter;
168                                         BMVert *eve;
169                                         int i;
170
171                                         if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) {
172                                                 *dvert_tot = 0;
173                                                 *dvert_arr = NULL;
174                                                 return 0;
175                                         }
176
177                                         i = em->bm->totvert;
178
179                                         *dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me");
180                                         *dvert_tot = i;
181
182                                         i = 0;
183                                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
184                                                 (*dvert_arr)[i] = CustomData_em_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
185                                                 i++;
186                                         }
187
188                                         return 1;
189                                 }
190                                 else if(me->dvert) {
191                                         int i;
192
193                                         *dvert_tot= me->totvert;
194                                         *dvert_arr= MEM_mallocN(sizeof(void*)*me->totvert, "vgroup parray from me");
195
196                                         for (i=0; i<me->totvert; i++) {
197                                                 (*dvert_arr)[i] = me->dvert + i;
198                                         }
199
200                                         return 1;
201                                 }
202                                 else
203                                         return 0;
204                         }
205                         case ID_LT:
206                         {
207                                 int i=0;
208
209                                 Lattice *lt= (Lattice *)id;
210                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
211
212                                 if(lt->dvert) {
213                                         *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
214                                         *dvert_arr= MEM_mallocN(sizeof(void*)*(*dvert_tot), "vgroup parray from me");
215
216                                         for (i=0; i<*dvert_tot; i++) {
217                                                 (*dvert_arr)[i] = lt->dvert + i;
218                                         }
219
220                                         return 1;
221                                 }
222                                 else {
223                                         return 0;
224                                 }
225                         }
226                 }
227         }
228
229         *dvert_arr= NULL;
230         *dvert_tot= 0;
231         return 0;
232 }
233
234 /* returns true if the id type supports weights */
235 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
236 {
237         if(id) {
238                 switch(GS(id->name)) {
239                         case ID_ME:
240                         {
241                                 Mesh *me = (Mesh *)id;
242                                 *dvert_arr= me->dvert;
243                                 *dvert_tot= me->totvert;
244                                 return TRUE;
245                         }
246                         case ID_LT:
247                         {
248                                 Lattice *lt= (Lattice *)id;
249                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
250                                 *dvert_arr= lt->dvert;
251                                 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
252                                 return TRUE;
253                         }
254                 }
255         }
256
257         *dvert_arr= NULL;
258         *dvert_tot= 0;
259         return FALSE;
260 }
261
262 /* matching index only */
263 int ED_vgroup_copy_array(Object *ob, Object *ob_from)
264 {
265         MDeformVert **dvert_array_from, **dvf;
266         MDeformVert **dvert_array, **dv;
267         int dvert_tot_from;
268         int dvert_tot;
269         int i;
270         int totdef_from= BLI_countlist(&ob_from->defbase);
271         int totdef= BLI_countlist(&ob->defbase);
272
273         ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from);
274         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
275
276         if(ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) {
277                 if (dvert_array) MEM_freeN(dvert_array);
278                 if (dvert_array_from) MEM_freeN(dvert_array_from);
279                 return 0;
280         }
281
282         /* do the copy */
283         BLI_freelistN(&ob->defbase);
284         BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
285         ob->actdef= ob_from->actdef;
286
287         if(totdef_from < totdef) {
288                 /* correct vgroup indices because the number of vgroups is being reduced. */
289                 int *remap= MEM_mallocN(sizeof(int) * (totdef + 1), "ED_vgroup_copy_array");
290                 for(i=0; i<=totdef_from; i++) remap[i]= i;
291                 for(; i<=totdef; i++) remap[i]= 0; /* can't use these, so disable */
292
293                 vgroup_remap_update_users(ob, remap);
294                 MEM_freeN(remap);
295         }
296
297         dvf= dvert_array_from;
298         dv= dvert_array;
299
300         for(i=0; i<dvert_tot; i++, dvf++, dv++) {
301                 if((*dv)->dw)
302                         BLI_cellalloc_free((*dv)->dw);
303
304                 *(*dv)= *(*dvf);
305
306                 if((*dv)->dw)
307                         (*dv)->dw= BLI_cellalloc_dupalloc((*dv)->dw);
308         }
309
310         MEM_freeN(dvert_array);
311         MEM_freeN(dvert_array_from);
312
313         return 1;
314 }
315
316 /* for mesh in object mode
317    lattice can be in editmode */
318 static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
319 {
320         /* This routine removes the vertex from the deform
321          * group with number def_nr.
322          *
323          * This routine is meant to be fast, so it is the
324          * responsibility of the calling routine to:
325          *   a) test whether ob is non-NULL
326          *   b) test whether ob is a mesh
327          *   c) calculate def_nr
328          */
329
330         MDeformWeight *newdw;
331         MDeformVert *dvert= NULL;
332         int i, tot;
333
334         /* get the deform vertices corresponding to the
335          * vertnum
336          */
337         ED_vgroup_give_array(ob->data, &dvert, &tot);
338
339         if(dvert==NULL)
340                 return;
341         
342         dvert+= vertnum;
343
344         /* for all of the deform weights in the
345          * deform vert
346          */
347         for(i=dvert->totweight - 1 ; i>=0 ; i--){
348
349                 /* if the def_nr is the same as the one
350                  * for our weight group then remove it
351                  * from this deform vert.
352                  */
353                 if(dvert->dw[i].def_nr == def_nr) {
354                         dvert->totweight--;
355
356                         /* if there are still other deform weights
357                          * attached to this vert then remove this
358                          * deform weight, and reshuffle the others
359                          */
360                         if(dvert->totweight) {
361                                 newdw = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight), 
362                                                                          "deformWeight");
363                                 if(dvert->dw){
364                                         memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
365                                         memcpy(newdw+i, dvert->dw+i+1, 
366                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
367                                         BLI_cellalloc_free(dvert->dw);
368                                 }
369                                 dvert->dw=newdw;
370                         }
371                         /* if there are no other deform weights
372                          * left then just remove the deform weight
373                          */
374                         else {
375                                 BLI_cellalloc_free(dvert->dw);
376                                 dvert->dw = NULL;
377                                 break;
378                         }
379                 }
380         }
381
382 }
383
384 /* for Mesh in Object mode */
385 /* allows editmode for Lattice */
386 static void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode)
387 {
388         /* add the vert to the deform group with the
389          * specified number
390          */
391         MDeformVert *dv= NULL;
392         MDeformWeight *newdw;
393         int     i, tot;
394
395         /* get the vert */
396         ED_vgroup_give_array(ob->data, &dv, &tot);
397         
398         if(dv==NULL)
399                 return;
400         
401         /* check that vertnum is valid before trying to get the relevant dvert */
402         if ((vertnum < 0) || (vertnum >= tot))
403                 return;
404         else
405                 dv += vertnum;
406
407         /* Lets first check to see if this vert is
408          * already in the weight group -- if so
409          * lets update it
410          */
411         for(i=0; i<dv->totweight; i++){
412                 
413                 /* if this weight cooresponds to the
414                  * deform group, then add it using
415                  * the assign mode provided
416                  */
417                 if(dv->dw[i].def_nr == def_nr){
418                         
419                         switch(assignmode) {
420                         case WEIGHT_REPLACE:
421                                 dv->dw[i].weight=weight;
422                                 break;
423                         case WEIGHT_ADD:
424                                 dv->dw[i].weight+=weight;
425                                 if(dv->dw[i].weight >= 1.0f)
426                                         dv->dw[i].weight = 1.0f;
427                                 break;
428                         case WEIGHT_SUBTRACT:
429                                 dv->dw[i].weight-=weight;
430                                 /* if the weight is zero or less then
431                                  * remove the vert from the deform group
432                                  */
433                                 if(dv->dw[i].weight <= 0.0f)
434                                         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
435                                 break;
436                         }
437                         return;
438                 }
439         }
440
441         /* if the vert wasn't in the deform group then
442          * we must take a different form of action ...
443          */
444
445         switch(assignmode) {
446         case WEIGHT_SUBTRACT:
447                 /* if we are subtracting then we don't
448                  * need to do anything
449                  */
450                 return;
451
452         case WEIGHT_REPLACE:
453         case WEIGHT_ADD:
454                 /* if we are doing an additive assignment, then
455                  * we need to create the deform weight
456                  */
457                 newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), 
458                                                          "deformWeight");
459                 if(dv->dw){
460                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
461                         BLI_cellalloc_free(dv->dw);
462                 }
463                 dv->dw=newdw;
464
465                 dv->dw[dv->totweight].weight=weight;
466                 dv->dw[dv->totweight].def_nr=def_nr;
467
468                 dv->totweight++;
469                 break;
470         }
471 }
472
473 /* called while not in editmode */
474 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
475 {
476         /* add the vert to the deform group with the
477          * specified assign mode
478          */
479         int     def_nr;
480
481         MDeformVert *dv= NULL;
482         int tot;
483
484         /* get the deform group number, exit if
485          * it can't be found
486          */
487         def_nr = defgroup_find_index(ob, dg);
488         if(def_nr < 0) return;
489
490         /* if there's no deform verts then create some,
491          */
492         if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
493                 ED_vgroup_data_create(ob->data);
494
495         /* call another function to do the work
496          */
497         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
498 }
499
500 /* mesh object mode, lattice can be in editmode */
501 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
502 {
503         /* This routine removes the vertex from the specified
504          * deform group.
505          */
506         const int def_nr= defgroup_find_index(ob, dg);
507         if(def_nr < 0)
508                 return;
509
510         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
511 }
512
513 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
514 {
515         MDeformVert *dvert= NULL;
516         BMVert *eve;
517         Mesh *me;
518         int i;
519
520         /* get the deform vertices corresponding to the vertnum */
521         if(ob->type==OB_MESH) {
522                 me= ob->data;
523
524                 if(me->edit_btmesh) {
525                         eve= BMIter_AtIndex(me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL, vertnum);
526                         if(!eve) {
527                                 return 0.0f;
528                         }
529                         dvert= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT);
530                         vertnum= 0;
531                 }
532                 else {
533                         if(vertnum >= me->totvert) {
534                                 return 0.0f;
535                         }
536                         dvert = me->dvert;
537                 }
538         }
539         else if(ob->type==OB_LATTICE) {
540                 Lattice *lt= vgroup_edit_lattice(ob);
541
542                 if(lt->dvert) {
543                         if(vertnum >= lt->pntsu*lt->pntsv*lt->pntsw) {
544                                 return 0.0f;
545                         }
546                         dvert = lt->dvert;
547                 }
548         }
549         
550         if(dvert==NULL)
551                 return -1;
552         
553         dvert += vertnum;
554         
555         for(i=dvert->totweight-1 ; i>=0 ; i--)
556                 if(dvert->dw[i].def_nr == def_nr)
557                         return dvert->dw[i].weight;
558
559         return -1;
560 }
561
562 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
563 {
564         int def_nr;
565
566         if(!ob) return -1;
567
568         def_nr = defgroup_find_index(ob, dg);
569         if(def_nr < 0) return -1;
570
571         return get_vert_def_nr(ob, def_nr, vertnum);
572 }
573
574 void ED_vgroup_select_by_name(Object *ob, const char *name)
575 {       /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */
576         ob->actdef= defgroup_name_index(ob, name) + 1;
577 }
578
579 /********************** Operator Implementations *********************/
580
581 /* only in editmode */
582 static void vgroup_select_verts(Object *ob, int select)
583 {
584         BMVert *eve;
585         MDeformVert *dvert;
586         int i;
587
588         if(ob->type == OB_MESH) {
589                 Mesh *me= ob->data;
590                 BMEditMesh *em = me->edit_btmesh;
591                 BMIter iter;
592
593                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
594                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
595
596                         if(dvert && dvert->totweight){
597                                 for(i=0; i<dvert->totweight; i++){
598                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
599                                                 if (!BM_TestHFlag(eve, BM_HIDDEN)) {
600                                                         BM_Select(em->bm, eve, select);
601                                                         break;
602                                                 }
603                                         }
604                                 }
605                         }
606                 }
607                 /* this has to be called, because this function operates on vertices only */
608                 if(select) EDBM_selectmode_flush(em);   // vertices to edges/faces
609                 else EDBM_deselect_flush(em);
610         }
611         else if(ob->type == OB_LATTICE) {
612                 Lattice *lt= vgroup_edit_lattice(ob);
613                 
614                 if(lt->dvert) {
615                         BPoint *bp;
616                         int a, tot;
617                         
618                         dvert= lt->dvert;
619
620                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
621                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
622                                 for(i=0; i<dvert->totweight; i++){
623                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
624                                                 if(select) bp->f1 |= SELECT;
625                                                 else bp->f1 &= ~SELECT;
626                                                 
627                                                 break;
628                                         }
629                                 }
630                         }
631                 }
632         }
633 }
634
635 static void vgroup_duplicate(Object *ob)
636 {
637         bDeformGroup *dg, *cdg;
638         char name[sizeof(dg->name)];
639         MDeformWeight *org, *cpy;
640         MDeformVert *dvert, **dvert_array=NULL;
641         int i, idg, icdg, dvert_tot=0;
642
643         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
644         if(!dg)
645                 return;
646         
647         if(!strstr(dg->name, "_copy")) {
648                 BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
649         }
650         else {
651                 BLI_snprintf(name, sizeof(name), "%s", dg->name);
652         }
653
654         cdg = defgroup_duplicate(dg);
655         strcpy(cdg->name, name);
656         defgroup_unique_name(cdg, ob);
657
658         BLI_addtail(&ob->defbase, cdg);
659
660         idg = (ob->actdef-1);
661         ob->actdef = BLI_countlist(&ob->defbase);
662         icdg = (ob->actdef-1);
663
664         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
665         
666         if(!dvert_array)
667                 return;
668
669         for(i = 0; i < dvert_tot; i++) {
670                 dvert = dvert_array[i];
671                 org = defvert_find_index(dvert, idg);
672                 if(org) {
673                         float weight = org->weight;
674                         /* defvert_verify_index re-allocs org so need to store the weight first */
675                         cpy = defvert_verify_index(dvert, icdg);
676                         cpy->weight = weight;
677                 }
678         }
679
680         MEM_freeN(dvert_array);
681 }
682
683 static void vgroup_normalize(Object *ob)
684 {
685         bDeformGroup *dg;
686         MDeformWeight *dw;
687         MDeformVert *dvert, **dvert_array=NULL;
688         int i, def_nr, dvert_tot=0;
689
690         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
691
692         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
693
694         if(dg) {
695                 float weight_max = 0.0f;
696
697                 def_nr= ob->actdef-1;
698
699                 for(i = 0; i < dvert_tot; i++) {
700                         dvert = dvert_array[i];
701                         dw = defvert_find_index(dvert, def_nr);
702                         if(dw) {
703                                 weight_max = MAX2(dw->weight, weight_max);
704                         }
705                 }
706
707                 if(weight_max > 0.0f) {
708                         for(i = 0; i < dvert_tot; i++) {
709                                 dvert = dvert_array[i];
710                                 dw = defvert_find_index(dvert, def_nr);
711                                 if(dw) {
712                                         dw->weight /= weight_max;
713                                         
714                                         /* incase of division errors with very low weights */
715                                         CLAMP(dw->weight, 0.0f, 1.0f);
716                                 }
717                         }
718                 }
719         }
720
721         if (dvert_array) MEM_freeN(dvert_array);
722 }
723
724 static void vgroup_levels(Object *ob, float offset, float gain)
725 {
726         bDeformGroup *dg;
727         MDeformWeight *dw;
728         MDeformVert *dvert, **dvert_array=NULL;
729         int i, def_nr, dvert_tot=0;
730         
731         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
732         
733         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
734         
735         if(dg) {
736                 def_nr= ob->actdef-1;
737                 
738                 for(i = 0; i < dvert_tot; i++) {
739                         dvert = dvert_array[i];
740                         dw = defvert_find_index(dvert, def_nr);
741                         if(dw) {
742                                 dw->weight = gain * (dw->weight + offset);
743                                 
744                                 CLAMP(dw->weight, 0.0f, 1.0f);
745                         }
746                 }
747         }
748
749         if (dvert_array) MEM_freeN(dvert_array);
750 }
751
752 /* TODO - select between groups */
753 static void vgroup_normalize_all(Object *ob, int lock_active)
754 {
755         MDeformWeight *dw, *dw_act;
756         MDeformVert *dvert, **dvert_array=NULL;
757         int i, dvert_tot=0;
758         float tot_weight;
759
760         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
761
762         if(dvert_array) {
763                 if(lock_active) {
764                         int def_nr= ob->actdef-1;
765
766                         for(i = 0; i < dvert_tot; i++) {
767                                 float lock_iweight= 1.0f;
768                                 int j;
769
770                                 tot_weight= 0.0f;
771                                 dw_act= NULL;
772                                 dvert = dvert_array[i];
773
774                                 j= dvert->totweight;
775                                 while(j--) {
776                                         dw= dvert->dw + j;
777
778                                         if(dw->def_nr==def_nr) {
779                                                 dw_act= dw;
780                                                 lock_iweight = (1.0f - dw_act->weight);
781                                         }
782                                         else {
783                                                 tot_weight += dw->weight;
784                                         }
785                                 }
786
787                                 if(tot_weight) {
788                                         j= dvert->totweight;
789                                         while(j--) {
790                                                 dw= dvert->dw + j;
791                                                 if(dw == dw_act) {
792                                                         if (dvert->totweight==1) {
793                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
794                                                         }
795                                                 } else {
796                                                         if(dw->weight > 0.0f)
797                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
798                                                 }
799
800                                                 /* incase of division errors with very low weights */
801                                                 CLAMP(dw->weight, 0.0f, 1.0f);
802                                         }
803                                 }
804                         }
805                 }
806                 else {
807                         for(i = 0; i < dvert_tot; i++) {
808                                 int j;
809                                 tot_weight= 0.0f;
810                                 dvert = dvert_array[i];
811
812                                 j= dvert->totweight;
813                                 while(j--) {
814                                         dw= dvert->dw + j;
815                                         tot_weight += dw->weight;
816                                 }
817
818                                 if(tot_weight) {
819                                         j= dvert->totweight;
820                                         while(j--) {
821                                                 dw= dvert->dw + j;
822                                                 dw->weight /= tot_weight;
823
824                                                 /* incase of division errors with very low weights */
825                                                 CLAMP(dw->weight, 0.0f, 1.0f);
826                                         }
827                                 }
828                         }
829                 }
830         }
831
832         if (dvert_array) MEM_freeN(dvert_array);
833 }
834
835
836 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
837 {
838         bDeformGroup *dg;
839         MDeformWeight *dw;
840         MDeformVert *dvert, **dvert_array=NULL;
841         int i, def_nr, dvert_tot=0;
842
843         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
844
845         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
846
847         if(dg) {
848                 def_nr= ob->actdef-1;
849
850
851                 for(i = 0; i < dvert_tot; i++) {
852                         dvert = dvert_array[i];
853
854                         if(auto_assign) {
855                                 dw= defvert_verify_index(dvert, def_nr);
856                         } else {
857                                 dw= defvert_find_index(dvert, def_nr);
858                         }
859
860                         if(dw) {
861                                 dw->weight = 1.0f-dw->weight;
862
863                                 if(auto_remove && dw->weight <= 0.0f) {
864                                         /* could have a faster function for this */
865                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
866                                 }
867                         }
868                 }
869         }
870
871         if (dvert_array) MEM_freeN(dvert_array);
872 }
873
874 static void vgroup_blend(Object *ob)
875 {
876         BMEditMesh *em= ((Mesh *)ob->data)->edit_btmesh;
877         bDeformGroup *dg;
878         MDeformWeight *dw;
879         MDeformVert *dvert_array=NULL, *dvert;
880         int i, def_nr, dvert_tot=0;
881
882         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
883
884         if(em==NULL)
885                 return;
886
887         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
888
889         if(dg) {
890                 BMEdge *eed;
891                 BMVert *eve;
892                 BMIter iter;
893                 float *vg_weights;
894                 float *vg_users;
895                 int sel1, sel2;
896                 int i1, i2;
897
898                 def_nr= ob->actdef-1;
899
900                 i= 0;
901                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
902                         BM_SetIndex(eve, i);
903                         i++;
904                 }
905                 dvert_tot= i;
906
907                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
908                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
909
910                 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
911                         sel1= BM_TestHFlag(eed->v1, BM_SELECT);
912                         sel2= BM_TestHFlag(eed->v2, BM_SELECT);
913
914                         if(sel1 != sel2) {
915                                 /* i1 is always the selected one */
916                                 if(sel1==TRUE && sel2==FALSE) {
917                                         i1= BM_GetIndex(eed->v1);
918                                         i2= BM_GetIndex(eed->v2);
919                                         eve= eed->v2;
920                                 }
921                                 else {
922                                         i2= BM_GetIndex(eed->v1);
923                                         i1= BM_GetIndex(eed->v2);
924                                         eve= eed->v1;
925                                 }
926
927                                 vg_users[i1]++;
928
929                                 /* TODO, we may want object mode blending */
930                                 if(em)  dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
931                                 else    dvert= dvert_array+i2;
932
933                                 dw= defvert_find_index(dvert, def_nr);
934
935                                 if(dw) {
936                                         vg_weights[i1] += dw->weight;
937                                 }
938                         }
939                 }
940
941                 i= 0;
942                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
943                         if(BM_TestHFlag(eve, BM_SELECT) && vg_users[i] > 0) {
944                                 /* TODO, we may want object mode blending */
945                                 if(em)  dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
946                                 else    dvert= dvert_array+i;
947
948                                 dw= defvert_verify_index(dvert, def_nr);
949                                 dw->weight= vg_weights[i] / (float)vg_users[i];
950                         }
951
952                         i++;
953                 }
954                 MEM_freeN(vg_weights);
955                 MEM_freeN(vg_users);
956         }
957 }
958
959 static void vgroup_clean(Object *ob, float eul, int keep_single)
960 {
961         bDeformGroup *dg;
962         MDeformWeight *dw;
963         MDeformVert *dvert, **dvert_array=NULL;
964         int i, def_nr, dvert_tot=0;
965
966         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
967
968         /* only the active group */
969         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
970         if(dg) {
971                 def_nr= ob->actdef-1;
972
973                 for(i = 0; i < dvert_tot; i++) {
974                         dvert = dvert_array[i];
975
976                         dw= defvert_find_index(dvert, def_nr);
977
978                         if(dw) {
979                                 if(dw->weight <= eul)
980                                         if(keep_single==FALSE || dvert->totweight > 1)
981                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
982                         }
983                 }
984         }
985
986         if (dvert_array) MEM_freeN(dvert_array);
987 }
988
989 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
990 {
991
992         MDeformWeight *dw;
993         MDeformVert *dvert, **dvert_array=NULL;
994         int i, dvert_tot=0;
995
996         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
997
998         if(dvert_array) {
999                 for(i = 0; i < dvert_tot; i++) {
1000                         int j;
1001                         dvert = dvert_array[i];
1002                         j= dvert->totweight;
1003
1004                         while(j--) {
1005
1006                                 if(keep_single && dvert->totweight == 1)
1007                                         break;
1008
1009                                 dw= dvert->dw + j;
1010
1011                                 if(dw->weight <= eul)
1012                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
1013
1014                         }
1015                 }
1016         }
1017
1018         if (dvert_array) MEM_freeN(dvert_array);
1019 }
1020
1021 void ED_vgroup_mirror(Object *ob, int mirror_weights, int flip_vgroups)
1022 {
1023         BMVert *eve, *eve_mirr;
1024         MDeformVert *dvert, *dvert_mirr;
1025         int     *flip_map;
1026
1027         if(mirror_weights==0 && flip_vgroups==0)
1028                 return;
1029
1030         /* only the active group */
1031         if(ob->type == OB_MESH) {
1032                 Mesh *me= ob->data;
1033                 BMEditMesh *em = me->edit_btmesh;
1034                 BMIter iter;
1035 #if 0 //BMESH_TODO
1036                 EM_cache_x_mirror_vert(ob, em);
1037
1038                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1039                         return;
1040
1041                 flip_map= defgroup_flip_map(ob, 0);
1042
1043                 /* Go through the list of editverts and assign them */
1044                 for(eve=em->verts.first; eve; eve=eve->next){
1045                         if((eve_mirr=eve->tmp.v)) {
1046                                 if((eve_mirr->f & SELECT || eve->f & SELECT) && (eve != eve_mirr)) {
1047                                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1048                                         dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
1049                                         if(dvert && dvert_mirr) {
1050                                                 if(eve_mirr->f & SELECT && eve->f & SELECT) {
1051                                                         /* swap */
1052                                                         if(mirror_weights)
1053                                                                 SWAP(MDeformVert, *dvert, *dvert_mirr);
1054                                                         if(flip_vgroups) {
1055                                                                 defvert_flip(dvert, flip_map);
1056                                                                 defvert_flip(dvert_mirr, flip_map);
1057                                                         }
1058                                                 }
1059                                                 else {
1060                                                         /* dvert should always be the target */
1061                                                         if(eve_mirr->f & SELECT) {
1062                                                                 SWAP(MDeformVert *, dvert, dvert_mirr);
1063                                                         }
1064
1065                                                         if(mirror_weights)
1066                                                                 defvert_copy(dvert, dvert_mirr);
1067                                                         if(flip_vgroups) {
1068                                                                 defvert_flip(dvert, flip_map);
1069                                                         }
1070                                                 }
1071                                         }
1072                                 }
1073
1074                                 eve->tmp.v= eve_mirr->tmp.v= NULL;
1075                         }
1076                 }
1077
1078                 MEM_freeN(flip_map);
1079
1080                 BKE_mesh_end_editmesh(me, em);
1081 #endif
1082         }
1083 }
1084
1085 static void vgroup_remap_update_users(Object *ob, int *map)
1086 {
1087         ExplodeModifierData *emd;
1088         ModifierData *md;
1089         ParticleSystem *psys;
1090         ClothModifierData *clmd;
1091         ClothSimSettings *clsim;
1092         int a;
1093
1094         /* these cases don't use names to refer to vertex groups, so when
1095          * they get deleted the numbers get out of sync, this corrects that */
1096
1097         if(ob->soft)
1098                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1099
1100         for(md=ob->modifiers.first; md; md=md->next) {
1101                 if(md->type == eModifierType_Explode) {
1102                         emd= (ExplodeModifierData*)md;
1103                         emd->vgroup= map[emd->vgroup];
1104                 }
1105                 else if(md->type == eModifierType_Cloth) {
1106                         clmd= (ClothModifierData*)md;
1107                         clsim= clmd->sim_parms;
1108
1109                         if(clsim) {
1110                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1111                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1112                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1113                         }
1114                 }
1115         }
1116
1117         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1118                 for(a=0; a<PSYS_TOT_VG; a++)
1119                         psys->vgroup[a]= map[psys->vgroup[a]];
1120         }
1121 }
1122
1123
1124 static void vgroup_delete_update_users(Object *ob, int id)
1125 {
1126         int i, tot= BLI_countlist(&ob->defbase) + 1;
1127         int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del");
1128
1129         map[id]= map[0]= 0;
1130         for(i=1; i<id; i++) map[i]=i;
1131         for(i=id+1; i<tot; i++) map[i]=i-1;
1132
1133         vgroup_remap_update_users(ob, map);
1134         MEM_freeN(map);
1135 }
1136
1137
1138 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1139 {
1140         MDeformVert *dvert_array=NULL;
1141         int i, e, dvert_tot=0;
1142         const int dg_index= BLI_findindex(&ob->defbase, dg);
1143
1144         assert(dg_index > -1);
1145         
1146         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1147
1148         if(dvert_array) {
1149                 MDeformVert *dvert;
1150                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1151                         ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */
1152                 }
1153
1154                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1155                         for(e = 0; e < dvert->totweight; e++) {
1156                                 if(dvert->dw[e].def_nr > dg_index) {
1157                                         dvert->dw[e].def_nr--;
1158                                 }
1159                         }
1160                 }
1161         }
1162
1163         vgroup_delete_update_users(ob, dg_index + 1);
1164
1165         /* Remove the group */
1166         BLI_freelinkN(&ob->defbase, dg);
1167
1168         /* Update the active deform index if necessary */
1169         if(ob->actdef > dg_index)
1170                 ob->actdef--;
1171         if(ob->actdef < 1 && ob->defbase.first)
1172                 ob->actdef= 1;
1173
1174 }
1175
1176 /* only in editmode */
1177 /* removes from active defgroup, if allverts==0 only selected vertices */
1178 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1179 {
1180         BMVert *eve;
1181         MDeformVert *dvert;
1182         MDeformWeight *newdw;
1183         bDeformGroup *eg;
1184         int     i;
1185
1186         if(ob->type == OB_MESH) {
1187                 Mesh *me= ob->data;
1188                 BMEditMesh *em = me->edit_btmesh;
1189                 BMIter iter;
1190
1191                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1192                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1193                 
1194                         if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){
1195                                 for(i=0; i<dvert->totweight; i++){
1196                                         /* Find group */
1197                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1198                                         if(eg == dg){
1199                                                 dvert->totweight--;
1200                                                 if (dvert->totweight){
1201                                                         newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1202                                                         
1203                                                         if(dvert->dw){
1204                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1205                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1206                                                                 BLI_cellalloc_free(dvert->dw);
1207                                                         }
1208                                                         dvert->dw=newdw;
1209                                                 }
1210                                                 else{
1211                                                         BLI_cellalloc_free (dvert->dw);
1212                                                         dvert->dw=NULL;
1213                                                         break;
1214                                                 }
1215                                         }
1216                                 }
1217                         }
1218                 }
1219         }
1220         else if(ob->type == OB_LATTICE) {
1221                 Lattice *lt= vgroup_edit_lattice(ob);
1222                 
1223                 if(lt->dvert) {
1224                         BPoint *bp;
1225                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1226                                 
1227                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1228                                 if(allverts || (bp->f1 & SELECT))
1229                                         ED_vgroup_vert_remove(ob, dg, a);
1230                         }
1231                 }
1232         }
1233 }
1234
1235 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1236 {
1237         int i;
1238         const int dg_index= BLI_findindex(&ob->defbase, dg);
1239
1240         assert(dg_index > -1);
1241
1242         /* Make sure that no verts are using this group */
1243         vgroup_active_remove_verts(ob, TRUE, dg);
1244
1245         /* Make sure that any verts with higher indices are adjusted accordingly */
1246         if(ob->type==OB_MESH) {
1247                 Mesh *me= ob->data;
1248                 BMEditMesh *em = me->edit_btmesh;
1249                 BMIter iter;
1250                 BMVert *eve;
1251                 MDeformVert *dvert;
1252                 
1253                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1254                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1255
1256                         if(dvert)
1257                                 for(i=0; i<dvert->totweight; i++)
1258                                         if(dvert->dw[i].def_nr > dg_index)
1259                                                 dvert->dw[i].def_nr--;
1260                 }
1261         }
1262         else if(ob->type==OB_LATTICE) {
1263                 Lattice *lt= vgroup_edit_lattice(ob);
1264                 BPoint *bp;
1265                 MDeformVert *dvert= lt->dvert;
1266                 int a, tot;
1267                 
1268                 if(dvert) {
1269                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1270                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1271                                 for(i=0; i<dvert->totweight; i++){
1272                                         if(dvert->dw[i].def_nr > dg_index)
1273                                                 dvert->dw[i].def_nr--;
1274                                 }
1275                         }
1276                 }
1277         }
1278
1279         vgroup_delete_update_users(ob, dg_index + 1);
1280
1281         /* Remove the group */
1282         BLI_freelinkN (&ob->defbase, dg);
1283
1284         /* Update the active deform index if necessary */
1285         if(ob->actdef > dg_index)
1286                 ob->actdef--;
1287         if(ob->actdef < 1 && ob->defbase.first)
1288                 ob->actdef= 1;
1289
1290         /* remove all dverts */
1291         if(ob->defbase.first == NULL) {
1292                 if(ob->type==OB_MESH) {
1293                         Mesh *me= ob->data;
1294                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1295                         me->dvert= NULL;
1296                 }
1297                 else if(ob->type==OB_LATTICE) {
1298                         Lattice *lt= vgroup_edit_lattice(ob);
1299                         if(lt->dvert) {
1300                                 BLI_cellalloc_free(lt->dvert);
1301                                 lt->dvert= NULL;
1302                         }
1303                 }
1304         }
1305 }
1306
1307 static int vgroup_object_in_edit_mode(Object *ob)
1308 {
1309         if(ob->type == OB_MESH)
1310                 return (((Mesh*)ob->data)->edit_btmesh != NULL);
1311         else if(ob->type == OB_LATTICE)
1312                 return (((Lattice*)ob->data)->editlatt != NULL);
1313         
1314         return 0;
1315 }
1316
1317 static void vgroup_delete(Object *ob)
1318 {
1319         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
1320         if(!dg)
1321                 return;
1322
1323         if(vgroup_object_in_edit_mode(ob))
1324                 vgroup_delete_edit_mode(ob, dg);
1325         else
1326                 vgroup_delete_object_mode(ob, dg);
1327 }
1328
1329 static void vgroup_delete_all(Object *ob)
1330 {
1331         /* Remove all DVerts */
1332         if(ob->type==OB_MESH) {
1333                 Mesh *me= ob->data;
1334                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1335                 me->dvert= NULL;
1336         }
1337         else if(ob->type==OB_LATTICE) {
1338                 Lattice *lt= vgroup_edit_lattice(ob);
1339                 if(lt->dvert) {
1340                         BLI_cellalloc_free(lt->dvert);
1341                         lt->dvert= NULL;
1342                 }
1343         }
1344         
1345         /* Remove all DefGroups */
1346         BLI_freelistN(&ob->defbase);
1347         
1348         /* Fix counters/indices */
1349         ob->actdef= 0;
1350 }
1351
1352 /* only in editmode */
1353 static void vgroup_assign_verts(Object *ob, float weight)
1354 {
1355         BMVert *eve;
1356         bDeformGroup *dg, *eg;
1357         MDeformWeight *newdw;
1358         MDeformVert *dvert;
1359         int     i, done;
1360
1361         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1362         if(!dg)
1363                 return;
1364
1365         if(ob->type == OB_MESH) {
1366                 Mesh *me= ob->data;
1367                 BMEditMesh *em = me->edit_btmesh;
1368                 BMIter iter;
1369
1370                 if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
1371                         BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
1372
1373                 /* Go through the list of editverts and assign them */
1374                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1375                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1376
1377                         if(dvert && BM_TestHFlag(eve, BM_SELECT)) {
1378                                 /* See if this vert already has a reference to this group */
1379                                 /*              If so: Change its weight */
1380                                 done=0;
1381                                 for(i=0; i<dvert->totweight; i++){
1382                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1383                                         /* Find the actual group */
1384                                         if(eg==dg){
1385                                                 dvert->dw[i].weight= weight;
1386                                                 done=1;
1387                                                 break;
1388                                         }
1389                                  }
1390                                 /*              If not: Add the group and set its weight */
1391                                 if(!done){
1392                                         newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1393                                         if(dvert->dw){
1394                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1395                                                 BLI_cellalloc_free(dvert->dw);
1396                                         }
1397                                         dvert->dw=newdw;
1398
1399                                         dvert->dw[dvert->totweight].weight= weight;
1400                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1401
1402                                         dvert->totweight++;
1403
1404                                 }
1405                         }
1406                 }
1407         }
1408         else if(ob->type == OB_LATTICE) {
1409                 Lattice *lt= vgroup_edit_lattice(ob);
1410                 BPoint *bp;
1411                 int a, tot;
1412                 
1413                 if(lt->dvert==NULL)
1414                         ED_vgroup_data_create(&lt->id);
1415                 
1416                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1417                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1418                         if(bp->f1 & SELECT)
1419                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1420                 }
1421         }
1422 }
1423
1424 /* only in editmode */
1425 /* removes from all defgroup, if allverts==0 only selected vertices */
1426 static void vgroup_remove_verts(Object *ob, int allverts)
1427 {
1428         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1429          * only operates on the active vgroup. So we iterate through all groups, by changing
1430          * active group index
1431          */
1432         bDeformGroup *dg;
1433         for(dg= ob->defbase.first; dg; dg= dg->next) {
1434                 vgroup_active_remove_verts(ob, allverts, dg);
1435         }
1436 }
1437
1438 /********************** vertex group operators *********************/
1439
1440 static int vertex_group_poll(bContext *C)
1441 {
1442         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1443         ID *data= (ob)? ob->data: NULL;
1444         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1445 }
1446
1447 static int vertex_group_poll_edit(bContext *C)
1448 {
1449         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1450         ID *data= (ob)? ob->data: NULL;
1451
1452         if(!(ob && !ob->id.lib && data && !data->lib))
1453                 return 0;
1454
1455         return vgroup_object_in_edit_mode(ob);
1456 }
1457
1458 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
1459 {
1460         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1461
1462         ED_vgroup_add(ob);
1463         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1464         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1465         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1466         
1467         return OPERATOR_FINISHED;
1468 }
1469
1470 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
1471 {
1472         /* identifiers */
1473         ot->name= "Add Vertex Group";
1474         ot->idname= "OBJECT_OT_vertex_group_add";
1475         
1476         /* api callbacks */
1477         ot->poll= vertex_group_poll;
1478         ot->exec= vertex_group_add_exec;
1479
1480         /* flags */
1481         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1482 }
1483
1484 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1485 {
1486         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1487
1488         if(RNA_boolean_get(op->ptr, "all"))
1489                 vgroup_delete_all(ob);
1490         else
1491                 vgroup_delete(ob);
1492
1493         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1494         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1495         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1496         
1497         return OPERATOR_FINISHED;
1498 }
1499
1500 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1501 {
1502         /* identifiers */
1503         ot->name= "Remove Vertex Group";
1504         ot->idname= "OBJECT_OT_vertex_group_remove";
1505         
1506         /* api callbacks */
1507         ot->poll= vertex_group_poll;
1508         ot->exec= vertex_group_remove_exec;
1509
1510         /* flags */
1511         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1512
1513         /* properties */
1514         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1515 }
1516
1517 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1518 {
1519         ToolSettings *ts= CTX_data_tool_settings(C);
1520         Object *ob= CTX_data_edit_object(C);
1521
1522         if(RNA_boolean_get(op->ptr, "new"))
1523                 ED_vgroup_add(ob);
1524
1525         vgroup_assign_verts(ob, ts->vgroup_weight);
1526         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1527         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1528         
1529         return OPERATOR_FINISHED;
1530 }
1531
1532 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1533 {
1534         /* identifiers */
1535         ot->name= "Assign Vertex Group";
1536         ot->idname= "OBJECT_OT_vertex_group_assign";
1537         
1538         /* api callbacks */
1539         ot->poll= vertex_group_poll_edit;
1540         ot->exec= vertex_group_assign_exec;
1541
1542         /* flags */
1543         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1544
1545         /* properties */
1546         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1547 }
1548
1549 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1550 {
1551         Object *ob= CTX_data_edit_object(C);
1552
1553         if(RNA_boolean_get(op->ptr, "all"))
1554                 vgroup_remove_verts(ob, 0);
1555         else {
1556                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
1557
1558                 if(dg == NULL) {
1559                         return OPERATOR_CANCELLED;
1560                 }
1561
1562                 vgroup_active_remove_verts(ob, FALSE, dg);
1563         }
1564
1565         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1566         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1567
1568         return OPERATOR_FINISHED;
1569 }
1570
1571 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1572 {
1573         /* identifiers */
1574         ot->name= "Remove from Vertex Group";
1575         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1576
1577         /* api callbacks */
1578         ot->poll= vertex_group_poll_edit;
1579         ot->exec= vertex_group_remove_from_exec;
1580
1581         /* flags */
1582         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1583
1584         /* properties */
1585         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1586 }
1587
1588 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
1589 {
1590         Object *ob= CTX_data_edit_object(C);
1591
1592         if(!ob || ob->id.lib)
1593                 return OPERATOR_CANCELLED;
1594
1595         vgroup_select_verts(ob, 1);
1596         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1597
1598         return OPERATOR_FINISHED;
1599 }
1600
1601 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1602 {
1603         /* identifiers */
1604         ot->name= "Select Vertex Group";
1605         ot->idname= "OBJECT_OT_vertex_group_select";
1606
1607         /* api callbacks */
1608         ot->poll= vertex_group_poll_edit;
1609         ot->exec= vertex_group_select_exec;
1610
1611         /* flags */
1612         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1613 }
1614
1615 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
1616 {
1617         Object *ob= CTX_data_edit_object(C);
1618
1619         vgroup_select_verts(ob, 0);
1620         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1621
1622         return OPERATOR_FINISHED;
1623 }
1624
1625 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1626 {
1627         /* identifiers */
1628         ot->name= "Deselect Vertex Group";
1629         ot->idname= "OBJECT_OT_vertex_group_deselect";
1630
1631         /* api callbacks */
1632         ot->poll= vertex_group_poll_edit;
1633         ot->exec= vertex_group_deselect_exec;
1634
1635         /* flags */
1636         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1637 }
1638
1639 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
1640 {
1641         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1642
1643         vgroup_duplicate(ob);
1644         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1645         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1646         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1647
1648         return OPERATOR_FINISHED;
1649 }
1650
1651 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1652 {
1653         /* identifiers */
1654         ot->name= "Copy Vertex Group";
1655         ot->idname= "OBJECT_OT_vertex_group_copy";
1656
1657         /* api callbacks */
1658         ot->poll= vertex_group_poll;
1659         ot->exec= vertex_group_copy_exec;
1660
1661         /* flags */
1662         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1663 }
1664
1665 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
1666 {
1667         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1668         
1669         float offset= RNA_float_get(op->ptr,"offset");
1670         float gain= RNA_float_get(op->ptr,"gain");
1671         
1672         vgroup_levels(ob, offset, gain);
1673         
1674         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1675         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1676         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1677         
1678         return OPERATOR_FINISHED;
1679 }
1680
1681 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
1682 {
1683         /* identifiers */
1684         ot->name= "Vertex Group Levels";
1685         ot->idname= "OBJECT_OT_vertex_group_levels";
1686         
1687         /* api callbacks */
1688         ot->poll= vertex_group_poll;
1689         ot->exec= vertex_group_levels_exec;
1690         
1691         /* flags */
1692         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1693         
1694         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
1695         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
1696 }
1697
1698 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
1699 {
1700         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1701
1702         vgroup_normalize(ob);
1703
1704         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1705         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1706         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1707
1708         return OPERATOR_FINISHED;
1709 }
1710
1711 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
1712 {
1713         /* identifiers */
1714         ot->name= "Normalize Vertex Group";
1715         ot->idname= "OBJECT_OT_vertex_group_normalize";
1716
1717         /* api callbacks */
1718         ot->poll= vertex_group_poll;
1719         ot->exec= vertex_group_normalize_exec;
1720
1721         /* flags */
1722         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1723 }
1724
1725 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
1726 {
1727         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1728         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
1729
1730         vgroup_normalize_all(ob, lock_active);
1731
1732         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1733         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1734         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1735
1736         return OPERATOR_FINISHED;
1737 }
1738
1739 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
1740 {
1741         /* identifiers */
1742         ot->name= "Normalize All Vertex Groups";
1743         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
1744
1745         /* api callbacks */
1746         ot->poll= vertex_group_poll;
1747         ot->exec= vertex_group_normalize_all_exec;
1748
1749         /* flags */
1750         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1751
1752         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
1753 }
1754
1755 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
1756 {
1757         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1758         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
1759         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
1760
1761         vgroup_invert(ob, auto_assign, auto_remove);
1762         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1763         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1764         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1765
1766         return OPERATOR_FINISHED;
1767 }
1768
1769 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
1770 {
1771         /* identifiers */
1772         ot->name= "Invert Vertex Group";
1773         ot->idname= "OBJECT_OT_vertex_group_invert";
1774
1775         /* api callbacks */
1776         ot->poll= vertex_group_poll;
1777         ot->exec= vertex_group_invert_exec;
1778
1779         /* flags */
1780         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1781
1782         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
1783         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
1784 }
1785
1786
1787 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op))
1788 {
1789         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1790
1791         vgroup_blend(ob);
1792
1793         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1794         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1795         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1796
1797         return OPERATOR_FINISHED;
1798 }
1799
1800 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
1801 {
1802         /* identifiers */
1803         ot->name= "Blend Vertex Group";
1804         ot->idname= "OBJECT_OT_vertex_group_blend";
1805         ot->description= "";
1806
1807         /* api callbacks */
1808         ot->poll= vertex_group_poll;
1809         ot->exec= vertex_group_blend_exec;
1810
1811         /* flags */
1812         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1813 }
1814
1815
1816 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
1817 {
1818         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1819
1820         float limit= RNA_float_get(op->ptr,"limit");
1821         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
1822         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
1823
1824         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
1825         else                    vgroup_clean(ob, limit, keep_single);
1826
1827         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1828         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1829         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1830
1831         return OPERATOR_FINISHED;
1832 }
1833
1834 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
1835 {
1836         /* identifiers */
1837         ot->name= "Clean Vertex Group";
1838         ot->idname= "OBJECT_OT_vertex_group_clean";
1839         ot->description= "Remove Vertex Group assignments which aren't required";
1840
1841         /* api callbacks */
1842         ot->poll= vertex_group_poll;
1843         ot->exec= vertex_group_clean_exec;
1844
1845         /* flags */
1846         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1847
1848         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
1849         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
1850         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
1851 }
1852
1853
1854 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
1855 {
1856         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1857
1858         ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
1859
1860         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1861         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1862         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1863
1864         return OPERATOR_FINISHED;
1865 }
1866
1867 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
1868 {
1869         /* identifiers */
1870         ot->name= "Mirror Vertex Group";
1871         ot->idname= "OBJECT_OT_vertex_group_mirror";
1872         ot->description= "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, flipping when both sides are selected otherwise copy from unselected";
1873
1874         /* api callbacks */
1875         ot->poll= vertex_group_poll_edit;
1876         ot->exec= vertex_group_mirror_exec;
1877
1878         /* flags */
1879         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1880
1881         /* properties */
1882         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
1883         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names.");
1884
1885 }
1886
1887 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
1888 {
1889         Scene *scene= CTX_data_scene(C);
1890         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1891         Base *base;
1892         int retval= OPERATOR_CANCELLED;
1893
1894         for(base=scene->base.first; base; base= base->next) {
1895                 if(base->object->type==ob->type) {
1896                         if(base->object!=ob && base->object->data==ob->data) {
1897                                 BLI_freelistN(&base->object->defbase);
1898                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1899                                 base->object->actdef= ob->actdef;
1900
1901                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
1902                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1903                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1904
1905                                 retval = OPERATOR_FINISHED;
1906                         }
1907                 }
1908         }
1909
1910         return retval;
1911 }
1912
1913 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1914 {
1915         /* identifiers */
1916         ot->name= "Copy Vertex Groups to Linked";
1917         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1918         ot->description= "Copy Vertex Groups to all users of the same Geometry data";
1919
1920         /* api callbacks */
1921         ot->poll= vertex_group_poll;
1922         ot->exec= vertex_group_copy_to_linked_exec;
1923
1924         /* flags */
1925         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1926 }
1927
1928 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *UNUSED(op))
1929 {
1930         Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1931
1932         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
1933         {
1934                 if(obact != ob)
1935                         ED_vgroup_copy_array(ob, obact);
1936         }
1937         CTX_DATA_END;
1938
1939         return OPERATOR_FINISHED;
1940 }
1941
1942
1943 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
1944 {
1945         /* identifiers */
1946         ot->name= "Copy Vertex Group to Selected";
1947         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected";
1948         ot->description= "Copy Vertex Groups to other selected objects with matching indices";
1949
1950         /* api callbacks */
1951         ot->poll= vertex_group_poll;
1952         ot->exec= vertex_group_copy_to_selected_exec;
1953
1954         /* flags */
1955         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1956 }
1957
1958 static EnumPropertyItem vgroup_items[]= {
1959         {0, NULL, 0, NULL, NULL}};
1960
1961 static int set_active_group_exec(bContext *C, wmOperator *op)
1962 {
1963         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1964         int nr= RNA_enum_get(op->ptr, "group");
1965
1966         ob->actdef= nr+1;
1967
1968         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1969         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
1970
1971         return OPERATOR_FINISHED;
1972 }
1973
1974 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), int *free)
1975 {       
1976         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1977         EnumPropertyItem tmp = {0, "", 0, "", ""};
1978         EnumPropertyItem *item= NULL;
1979         bDeformGroup *def;
1980         int a, totitem= 0;
1981         
1982         if(!ob)
1983                 return vgroup_items;
1984         
1985         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
1986                 tmp.value= a;
1987                 tmp.icon= ICON_GROUP_VERTEX;
1988                 tmp.identifier= def->name;
1989                 tmp.name= def->name;
1990                 RNA_enum_item_add(&item, &totitem, &tmp);
1991         }
1992
1993         RNA_enum_item_end(&item, &totitem);
1994         *free= 1;
1995
1996         return item;
1997 }
1998
1999 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2000 {
2001         PropertyRNA *prop;
2002
2003         /* identifiers */
2004         ot->name= "Set Active Vertex Group";
2005         ot->idname= "OBJECT_OT_vertex_group_set_active";
2006         ot->description= "Set the active vertex group";
2007
2008         /* api callbacks */
2009         ot->poll= vertex_group_poll;
2010         ot->exec= set_active_group_exec;
2011         ot->invoke= WM_menu_invoke;
2012
2013         /* flags */
2014         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2015
2016         /* properties */
2017         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
2018         RNA_def_enum_funcs(prop, vgroup_itemf);
2019         ot->prop= prop;
2020 }
2021
2022 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling
2023   with the order of vgroups then call vgroup_do_remap after*/
2024 static char *vgroup_init_remap(Object *ob)
2025 {
2026         bDeformGroup *def;
2027         int def_tot = BLI_countlist(&ob->defbase);
2028         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups");
2029         char *name;
2030
2031         name= name_array;
2032         for(def = ob->defbase.first; def; def=def->next) {
2033                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
2034                 name += MAX_VGROUP_NAME;
2035         }
2036
2037         return name_array;
2038 }
2039
2040 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
2041 {
2042         MDeformVert *dvert= NULL;
2043         bDeformGroup *def;
2044         int def_tot = BLI_countlist(&ob->defbase);
2045         int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/
2046         int *sort_map= sort_map_update + 1;
2047         char *name;
2048         int i;
2049
2050         name= name_array;
2051         for(def= ob->defbase.first, i=0; def; def=def->next, i++){
2052                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
2053                 name += MAX_VGROUP_NAME;
2054         }
2055
2056         if(ob->mode == OB_MODE_EDIT) {
2057                 if(ob->type==OB_MESH) {
2058                         BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
2059                         BMIter iter;
2060                         BMVert *eve;
2061
2062                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2063                                 dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
2064                                 if(dvert && dvert->totweight){
2065                                         defvert_remap(dvert, sort_map);
2066                                 }
2067                         }
2068                 }
2069                 else {
2070                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet.");
2071                         MEM_freeN(sort_map_update);
2072                         return OPERATOR_CANCELLED;
2073                 }
2074         }
2075         else {
2076                 int dvert_tot=0;
2077
2078                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
2079
2080                 /*create as necassary*/
2081                 while(dvert && dvert_tot--) {
2082                         if(dvert->totweight)
2083                                 defvert_remap(dvert, sort_map);
2084                         dvert++;
2085                 }
2086         }
2087
2088         /* update users */
2089         for(i=0; i<def_tot; i++)
2090                 sort_map[i]++;
2091
2092         sort_map_update[0]= 0;
2093         vgroup_remap_update_users(ob, sort_map_update);
2094
2095         ob->actdef= sort_map_update[ob->actdef];
2096         
2097         MEM_freeN(sort_map_update);
2098
2099         return OPERATOR_FINISHED;
2100 }
2101
2102 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
2103 {
2104         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
2105         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
2106
2107         return BLI_natstrcmp(def_a->name, def_b->name);
2108 }
2109
2110 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
2111 {
2112         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2113         char *name_array;
2114         int ret;
2115
2116         /*init remapping*/
2117         name_array = vgroup_init_remap(ob);
2118
2119         /*sort vgroup names*/
2120         BLI_sortlist(&ob->defbase, vgroup_sort);
2121
2122         /*remap vgroup data to map to correct names*/
2123         ret = vgroup_do_remap(ob, name_array, op);
2124
2125         if (ret != OPERATOR_CANCELLED) {
2126                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2127                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2128         }
2129
2130         if (name_array) MEM_freeN(name_array);
2131
2132         return ret;
2133 }
2134
2135 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
2136 {
2137         ot->name= "Sort Vertex Groups";
2138         ot->idname= "OBJECT_OT_vertex_group_sort";
2139         ot->description= "Sorts vertex groups alphabetically";
2140
2141         /* api callbacks */
2142         ot->poll= vertex_group_poll;
2143         ot->exec= vertex_group_sort_exec;
2144
2145         /* flags */
2146         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2147 }
2148
2149 static int vgroup_move_exec(bContext *C, wmOperator *op)
2150 {
2151         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2152         bDeformGroup *def;
2153         char *name_array;
2154         int dir= RNA_enum_get(op->ptr, "direction"), ret;
2155
2156         def = BLI_findlink(&ob->defbase, ob->actdef - 1);
2157         if (!def) {
2158                 return OPERATOR_CANCELLED;
2159         }
2160
2161         name_array = vgroup_init_remap(ob);
2162
2163         if (dir == 1) { /*up*/
2164                 void *prev = def->prev;
2165
2166                 BLI_remlink(&ob->defbase, def);
2167                 BLI_insertlinkbefore(&ob->defbase, prev, def);
2168         } else { /*down*/
2169                 void *next = def->next;
2170
2171                 BLI_remlink(&ob->defbase, def);
2172                 BLI_insertlinkafter(&ob->defbase, next, def);
2173         }
2174
2175         ret = vgroup_do_remap(ob, name_array, op);
2176
2177         if (name_array) MEM_freeN(name_array);
2178
2179         if (ret != OPERATOR_CANCELLED) {
2180                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2181                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2182         }
2183
2184         return ret;
2185 }
2186
2187 void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
2188 {
2189         static EnumPropertyItem vgroup_slot_move[] = {
2190                 {1, "UP", 0, "Up", ""},
2191                 {-1, "DOWN", 0, "Down", ""},
2192                 {0, NULL, 0, NULL, NULL}
2193         };
2194
2195         /* identifiers */
2196         ot->name= "Move Vertex Group";
2197         ot->idname= "OBJECT_OT_vertex_group_move";
2198
2199         /* api callbacks */
2200         ot->poll= vertex_group_poll;
2201         ot->exec= vgroup_move_exec;
2202
2203         /* flags */
2204         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2205
2206         RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
2207 }