remove unused vars
[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 1 //BMESH_TODO
1036                 (void)eve;
1037                 (void)eve_mirr;
1038                 (void)dvert;
1039                 (void)dvert_mirr;
1040                 (void)flip_map;
1041                 (void)iter;
1042                 (void)em;
1043 #else
1044                 EM_cache_x_mirror_vert(ob, em);
1045
1046                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1047                         return;
1048
1049                 flip_map= defgroup_flip_map(ob, 0);
1050
1051                 /* Go through the list of editverts and assign them */
1052                 for(eve=em->verts.first; eve; eve=eve->next){
1053                         if((eve_mirr=eve->tmp.v)) {
1054                                 if((eve_mirr->f & SELECT || eve->f & SELECT) && (eve != eve_mirr)) {
1055                                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1056                                         dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
1057                                         if(dvert && dvert_mirr) {
1058                                                 if(eve_mirr->f & SELECT && eve->f & SELECT) {
1059                                                         /* swap */
1060                                                         if(mirror_weights)
1061                                                                 SWAP(MDeformVert, *dvert, *dvert_mirr);
1062                                                         if(flip_vgroups) {
1063                                                                 defvert_flip(dvert, flip_map);
1064                                                                 defvert_flip(dvert_mirr, flip_map);
1065                                                         }
1066                                                 }
1067                                                 else {
1068                                                         /* dvert should always be the target */
1069                                                         if(eve_mirr->f & SELECT) {
1070                                                                 SWAP(MDeformVert *, dvert, dvert_mirr);
1071                                                         }
1072
1073                                                         if(mirror_weights)
1074                                                                 defvert_copy(dvert, dvert_mirr);
1075                                                         if(flip_vgroups) {
1076                                                                 defvert_flip(dvert, flip_map);
1077                                                         }
1078                                                 }
1079                                         }
1080                                 }
1081
1082                                 eve->tmp.v= eve_mirr->tmp.v= NULL;
1083                         }
1084                 }
1085
1086                 MEM_freeN(flip_map);
1087
1088                 BKE_mesh_end_editmesh(me, em);
1089 #endif
1090         }
1091 }
1092
1093 static void vgroup_remap_update_users(Object *ob, int *map)
1094 {
1095         ExplodeModifierData *emd;
1096         ModifierData *md;
1097         ParticleSystem *psys;
1098         ClothModifierData *clmd;
1099         ClothSimSettings *clsim;
1100         int a;
1101
1102         /* these cases don't use names to refer to vertex groups, so when
1103          * they get deleted the numbers get out of sync, this corrects that */
1104
1105         if(ob->soft)
1106                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1107
1108         for(md=ob->modifiers.first; md; md=md->next) {
1109                 if(md->type == eModifierType_Explode) {
1110                         emd= (ExplodeModifierData*)md;
1111                         emd->vgroup= map[emd->vgroup];
1112                 }
1113                 else if(md->type == eModifierType_Cloth) {
1114                         clmd= (ClothModifierData*)md;
1115                         clsim= clmd->sim_parms;
1116
1117                         if(clsim) {
1118                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1119                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1120                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1121                         }
1122                 }
1123         }
1124
1125         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1126                 for(a=0; a<PSYS_TOT_VG; a++)
1127                         psys->vgroup[a]= map[psys->vgroup[a]];
1128         }
1129 }
1130
1131
1132 static void vgroup_delete_update_users(Object *ob, int id)
1133 {
1134         int i, tot= BLI_countlist(&ob->defbase) + 1;
1135         int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del");
1136
1137         map[id]= map[0]= 0;
1138         for(i=1; i<id; i++) map[i]=i;
1139         for(i=id+1; i<tot; i++) map[i]=i-1;
1140
1141         vgroup_remap_update_users(ob, map);
1142         MEM_freeN(map);
1143 }
1144
1145
1146 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1147 {
1148         MDeformVert *dvert_array=NULL;
1149         int i, e, dvert_tot=0;
1150         const int dg_index= BLI_findindex(&ob->defbase, dg);
1151
1152         assert(dg_index > -1);
1153         
1154         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1155
1156         if(dvert_array) {
1157                 MDeformVert *dvert;
1158                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1159                         ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */
1160                 }
1161
1162                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1163                         for(e = 0; e < dvert->totweight; e++) {
1164                                 if(dvert->dw[e].def_nr > dg_index) {
1165                                         dvert->dw[e].def_nr--;
1166                                 }
1167                         }
1168                 }
1169         }
1170
1171         vgroup_delete_update_users(ob, dg_index + 1);
1172
1173         /* Remove the group */
1174         BLI_freelinkN(&ob->defbase, dg);
1175
1176         /* Update the active deform index if necessary */
1177         if(ob->actdef > dg_index)
1178                 ob->actdef--;
1179         if(ob->actdef < 1 && ob->defbase.first)
1180                 ob->actdef= 1;
1181
1182 }
1183
1184 /* only in editmode */
1185 /* removes from active defgroup, if allverts==0 only selected vertices */
1186 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1187 {
1188         BMVert *eve;
1189         MDeformVert *dvert;
1190         MDeformWeight *newdw;
1191         bDeformGroup *eg;
1192         int     i;
1193
1194         if(ob->type == OB_MESH) {
1195                 Mesh *me= ob->data;
1196                 BMEditMesh *em = me->edit_btmesh;
1197                 BMIter iter;
1198
1199                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1200                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1201                 
1202                         if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){
1203                                 for(i=0; i<dvert->totweight; i++){
1204                                         /* Find group */
1205                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1206                                         if(eg == dg){
1207                                                 dvert->totweight--;
1208                                                 if (dvert->totweight){
1209                                                         newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1210                                                         
1211                                                         if(dvert->dw){
1212                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1213                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1214                                                                 BLI_cellalloc_free(dvert->dw);
1215                                                         }
1216                                                         dvert->dw=newdw;
1217                                                 }
1218                                                 else{
1219                                                         BLI_cellalloc_free (dvert->dw);
1220                                                         dvert->dw=NULL;
1221                                                         break;
1222                                                 }
1223                                         }
1224                                 }
1225                         }
1226                 }
1227         }
1228         else if(ob->type == OB_LATTICE) {
1229                 Lattice *lt= vgroup_edit_lattice(ob);
1230                 
1231                 if(lt->dvert) {
1232                         BPoint *bp;
1233                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1234                                 
1235                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1236                                 if(allverts || (bp->f1 & SELECT))
1237                                         ED_vgroup_vert_remove(ob, dg, a);
1238                         }
1239                 }
1240         }
1241 }
1242
1243 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1244 {
1245         int i;
1246         const int dg_index= BLI_findindex(&ob->defbase, dg);
1247
1248         assert(dg_index > -1);
1249
1250         /* Make sure that no verts are using this group */
1251         vgroup_active_remove_verts(ob, TRUE, dg);
1252
1253         /* Make sure that any verts with higher indices are adjusted accordingly */
1254         if(ob->type==OB_MESH) {
1255                 Mesh *me= ob->data;
1256                 BMEditMesh *em = me->edit_btmesh;
1257                 BMIter iter;
1258                 BMVert *eve;
1259                 MDeformVert *dvert;
1260                 
1261                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1262                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1263
1264                         if(dvert)
1265                                 for(i=0; i<dvert->totweight; i++)
1266                                         if(dvert->dw[i].def_nr > dg_index)
1267                                                 dvert->dw[i].def_nr--;
1268                 }
1269         }
1270         else if(ob->type==OB_LATTICE) {
1271                 Lattice *lt= vgroup_edit_lattice(ob);
1272                 BPoint *bp;
1273                 MDeformVert *dvert= lt->dvert;
1274                 int a, tot;
1275                 
1276                 if(dvert) {
1277                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1278                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1279                                 for(i=0; i<dvert->totweight; i++){
1280                                         if(dvert->dw[i].def_nr > dg_index)
1281                                                 dvert->dw[i].def_nr--;
1282                                 }
1283                         }
1284                 }
1285         }
1286
1287         vgroup_delete_update_users(ob, dg_index + 1);
1288
1289         /* Remove the group */
1290         BLI_freelinkN (&ob->defbase, dg);
1291
1292         /* Update the active deform index if necessary */
1293         if(ob->actdef > dg_index)
1294                 ob->actdef--;
1295         if(ob->actdef < 1 && ob->defbase.first)
1296                 ob->actdef= 1;
1297
1298         /* remove all dverts */
1299         if(ob->defbase.first == NULL) {
1300                 if(ob->type==OB_MESH) {
1301                         Mesh *me= ob->data;
1302                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1303                         me->dvert= NULL;
1304                 }
1305                 else if(ob->type==OB_LATTICE) {
1306                         Lattice *lt= vgroup_edit_lattice(ob);
1307                         if(lt->dvert) {
1308                                 BLI_cellalloc_free(lt->dvert);
1309                                 lt->dvert= NULL;
1310                         }
1311                 }
1312         }
1313 }
1314
1315 static int vgroup_object_in_edit_mode(Object *ob)
1316 {
1317         if(ob->type == OB_MESH)
1318                 return (((Mesh*)ob->data)->edit_btmesh != NULL);
1319         else if(ob->type == OB_LATTICE)
1320                 return (((Lattice*)ob->data)->editlatt != NULL);
1321         
1322         return 0;
1323 }
1324
1325 static void vgroup_delete(Object *ob)
1326 {
1327         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
1328         if(!dg)
1329                 return;
1330
1331         if(vgroup_object_in_edit_mode(ob))
1332                 vgroup_delete_edit_mode(ob, dg);
1333         else
1334                 vgroup_delete_object_mode(ob, dg);
1335 }
1336
1337 static void vgroup_delete_all(Object *ob)
1338 {
1339         /* Remove all DVerts */
1340         if(ob->type==OB_MESH) {
1341                 Mesh *me= ob->data;
1342                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1343                 me->dvert= NULL;
1344         }
1345         else if(ob->type==OB_LATTICE) {
1346                 Lattice *lt= vgroup_edit_lattice(ob);
1347                 if(lt->dvert) {
1348                         BLI_cellalloc_free(lt->dvert);
1349                         lt->dvert= NULL;
1350                 }
1351         }
1352         
1353         /* Remove all DefGroups */
1354         BLI_freelistN(&ob->defbase);
1355         
1356         /* Fix counters/indices */
1357         ob->actdef= 0;
1358 }
1359
1360 /* only in editmode */
1361 static void vgroup_assign_verts(Object *ob, float weight)
1362 {
1363         BMVert *eve;
1364         bDeformGroup *dg, *eg;
1365         MDeformWeight *newdw;
1366         MDeformVert *dvert;
1367         int     i, done;
1368
1369         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1370         if(!dg)
1371                 return;
1372
1373         if(ob->type == OB_MESH) {
1374                 Mesh *me= ob->data;
1375                 BMEditMesh *em = me->edit_btmesh;
1376                 BMIter iter;
1377
1378                 if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
1379                         BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
1380
1381                 /* Go through the list of editverts and assign them */
1382                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1383                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1384
1385                         if(dvert && BM_TestHFlag(eve, BM_SELECT)) {
1386                                 /* See if this vert already has a reference to this group */
1387                                 /*              If so: Change its weight */
1388                                 done=0;
1389                                 for(i=0; i<dvert->totweight; i++){
1390                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1391                                         /* Find the actual group */
1392                                         if(eg==dg){
1393                                                 dvert->dw[i].weight= weight;
1394                                                 done=1;
1395                                                 break;
1396                                         }
1397                                  }
1398                                 /*              If not: Add the group and set its weight */
1399                                 if(!done){
1400                                         newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1401                                         if(dvert->dw){
1402                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1403                                                 BLI_cellalloc_free(dvert->dw);
1404                                         }
1405                                         dvert->dw=newdw;
1406
1407                                         dvert->dw[dvert->totweight].weight= weight;
1408                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1409
1410                                         dvert->totweight++;
1411
1412                                 }
1413                         }
1414                 }
1415         }
1416         else if(ob->type == OB_LATTICE) {
1417                 Lattice *lt= vgroup_edit_lattice(ob);
1418                 BPoint *bp;
1419                 int a, tot;
1420                 
1421                 if(lt->dvert==NULL)
1422                         ED_vgroup_data_create(&lt->id);
1423                 
1424                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1425                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1426                         if(bp->f1 & SELECT)
1427                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1428                 }
1429         }
1430 }
1431
1432 /* only in editmode */
1433 /* removes from all defgroup, if allverts==0 only selected vertices */
1434 static void vgroup_remove_verts(Object *ob, int allverts)
1435 {
1436         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1437          * only operates on the active vgroup. So we iterate through all groups, by changing
1438          * active group index
1439          */
1440         bDeformGroup *dg;
1441         for(dg= ob->defbase.first; dg; dg= dg->next) {
1442                 vgroup_active_remove_verts(ob, allverts, dg);
1443         }
1444 }
1445
1446 /********************** vertex group operators *********************/
1447
1448 static int vertex_group_poll(bContext *C)
1449 {
1450         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1451         ID *data= (ob)? ob->data: NULL;
1452         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1453 }
1454
1455 static int vertex_group_poll_edit(bContext *C)
1456 {
1457         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1458         ID *data= (ob)? ob->data: NULL;
1459
1460         if(!(ob && !ob->id.lib && data && !data->lib))
1461                 return 0;
1462
1463         return vgroup_object_in_edit_mode(ob);
1464 }
1465
1466 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
1467 {
1468         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1469
1470         ED_vgroup_add(ob);
1471         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1472         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1473         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1474         
1475         return OPERATOR_FINISHED;
1476 }
1477
1478 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
1479 {
1480         /* identifiers */
1481         ot->name= "Add Vertex Group";
1482         ot->idname= "OBJECT_OT_vertex_group_add";
1483         
1484         /* api callbacks */
1485         ot->poll= vertex_group_poll;
1486         ot->exec= vertex_group_add_exec;
1487
1488         /* flags */
1489         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1490 }
1491
1492 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1493 {
1494         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1495
1496         if(RNA_boolean_get(op->ptr, "all"))
1497                 vgroup_delete_all(ob);
1498         else
1499                 vgroup_delete(ob);
1500
1501         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1502         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1503         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1504         
1505         return OPERATOR_FINISHED;
1506 }
1507
1508 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1509 {
1510         /* identifiers */
1511         ot->name= "Remove Vertex Group";
1512         ot->idname= "OBJECT_OT_vertex_group_remove";
1513         
1514         /* api callbacks */
1515         ot->poll= vertex_group_poll;
1516         ot->exec= vertex_group_remove_exec;
1517
1518         /* flags */
1519         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1520
1521         /* properties */
1522         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1523 }
1524
1525 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1526 {
1527         ToolSettings *ts= CTX_data_tool_settings(C);
1528         Object *ob= CTX_data_edit_object(C);
1529
1530         if(RNA_boolean_get(op->ptr, "new"))
1531                 ED_vgroup_add(ob);
1532
1533         vgroup_assign_verts(ob, ts->vgroup_weight);
1534         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1535         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1536         
1537         return OPERATOR_FINISHED;
1538 }
1539
1540 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1541 {
1542         /* identifiers */
1543         ot->name= "Assign Vertex Group";
1544         ot->idname= "OBJECT_OT_vertex_group_assign";
1545         
1546         /* api callbacks */
1547         ot->poll= vertex_group_poll_edit;
1548         ot->exec= vertex_group_assign_exec;
1549
1550         /* flags */
1551         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1552
1553         /* properties */
1554         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1555 }
1556
1557 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1558 {
1559         Object *ob= CTX_data_edit_object(C);
1560
1561         if(RNA_boolean_get(op->ptr, "all"))
1562                 vgroup_remove_verts(ob, 0);
1563         else {
1564                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
1565
1566                 if(dg == NULL) {
1567                         return OPERATOR_CANCELLED;
1568                 }
1569
1570                 vgroup_active_remove_verts(ob, FALSE, dg);
1571         }
1572
1573         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1574         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1575
1576         return OPERATOR_FINISHED;
1577 }
1578
1579 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1580 {
1581         /* identifiers */
1582         ot->name= "Remove from Vertex Group";
1583         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1584
1585         /* api callbacks */
1586         ot->poll= vertex_group_poll_edit;
1587         ot->exec= vertex_group_remove_from_exec;
1588
1589         /* flags */
1590         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1591
1592         /* properties */
1593         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1594 }
1595
1596 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
1597 {
1598         Object *ob= CTX_data_edit_object(C);
1599
1600         if(!ob || ob->id.lib)
1601                 return OPERATOR_CANCELLED;
1602
1603         vgroup_select_verts(ob, 1);
1604         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1605
1606         return OPERATOR_FINISHED;
1607 }
1608
1609 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1610 {
1611         /* identifiers */
1612         ot->name= "Select Vertex Group";
1613         ot->idname= "OBJECT_OT_vertex_group_select";
1614
1615         /* api callbacks */
1616         ot->poll= vertex_group_poll_edit;
1617         ot->exec= vertex_group_select_exec;
1618
1619         /* flags */
1620         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1621 }
1622
1623 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
1624 {
1625         Object *ob= CTX_data_edit_object(C);
1626
1627         vgroup_select_verts(ob, 0);
1628         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1629
1630         return OPERATOR_FINISHED;
1631 }
1632
1633 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1634 {
1635         /* identifiers */
1636         ot->name= "Deselect Vertex Group";
1637         ot->idname= "OBJECT_OT_vertex_group_deselect";
1638
1639         /* api callbacks */
1640         ot->poll= vertex_group_poll_edit;
1641         ot->exec= vertex_group_deselect_exec;
1642
1643         /* flags */
1644         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1645 }
1646
1647 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
1648 {
1649         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1650
1651         vgroup_duplicate(ob);
1652         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1653         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1654         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1655
1656         return OPERATOR_FINISHED;
1657 }
1658
1659 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1660 {
1661         /* identifiers */
1662         ot->name= "Copy Vertex Group";
1663         ot->idname= "OBJECT_OT_vertex_group_copy";
1664
1665         /* api callbacks */
1666         ot->poll= vertex_group_poll;
1667         ot->exec= vertex_group_copy_exec;
1668
1669         /* flags */
1670         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1671 }
1672
1673 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
1674 {
1675         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1676         
1677         float offset= RNA_float_get(op->ptr,"offset");
1678         float gain= RNA_float_get(op->ptr,"gain");
1679         
1680         vgroup_levels(ob, offset, gain);
1681         
1682         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1683         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1684         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1685         
1686         return OPERATOR_FINISHED;
1687 }
1688
1689 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
1690 {
1691         /* identifiers */
1692         ot->name= "Vertex Group Levels";
1693         ot->idname= "OBJECT_OT_vertex_group_levels";
1694         
1695         /* api callbacks */
1696         ot->poll= vertex_group_poll;
1697         ot->exec= vertex_group_levels_exec;
1698         
1699         /* flags */
1700         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1701         
1702         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
1703         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
1704 }
1705
1706 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
1707 {
1708         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1709
1710         vgroup_normalize(ob);
1711
1712         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1713         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1714         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1715
1716         return OPERATOR_FINISHED;
1717 }
1718
1719 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
1720 {
1721         /* identifiers */
1722         ot->name= "Normalize Vertex Group";
1723         ot->idname= "OBJECT_OT_vertex_group_normalize";
1724
1725         /* api callbacks */
1726         ot->poll= vertex_group_poll;
1727         ot->exec= vertex_group_normalize_exec;
1728
1729         /* flags */
1730         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1731 }
1732
1733 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
1734 {
1735         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1736         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
1737
1738         vgroup_normalize_all(ob, lock_active);
1739
1740         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1741         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1742         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1743
1744         return OPERATOR_FINISHED;
1745 }
1746
1747 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
1748 {
1749         /* identifiers */
1750         ot->name= "Normalize All Vertex Groups";
1751         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
1752
1753         /* api callbacks */
1754         ot->poll= vertex_group_poll;
1755         ot->exec= vertex_group_normalize_all_exec;
1756
1757         /* flags */
1758         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1759
1760         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
1761 }
1762
1763 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
1764 {
1765         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1766         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
1767         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
1768
1769         vgroup_invert(ob, auto_assign, auto_remove);
1770         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1771         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1772         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1773
1774         return OPERATOR_FINISHED;
1775 }
1776
1777 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
1778 {
1779         /* identifiers */
1780         ot->name= "Invert Vertex Group";
1781         ot->idname= "OBJECT_OT_vertex_group_invert";
1782
1783         /* api callbacks */
1784         ot->poll= vertex_group_poll;
1785         ot->exec= vertex_group_invert_exec;
1786
1787         /* flags */
1788         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1789
1790         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
1791         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
1792 }
1793
1794
1795 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op))
1796 {
1797         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1798
1799         vgroup_blend(ob);
1800
1801         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1802         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1803         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1804
1805         return OPERATOR_FINISHED;
1806 }
1807
1808 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
1809 {
1810         /* identifiers */
1811         ot->name= "Blend Vertex Group";
1812         ot->idname= "OBJECT_OT_vertex_group_blend";
1813         ot->description= "";
1814
1815         /* api callbacks */
1816         ot->poll= vertex_group_poll;
1817         ot->exec= vertex_group_blend_exec;
1818
1819         /* flags */
1820         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1821 }
1822
1823
1824 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
1825 {
1826         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1827
1828         float limit= RNA_float_get(op->ptr,"limit");
1829         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
1830         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
1831
1832         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
1833         else                    vgroup_clean(ob, limit, keep_single);
1834
1835         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1836         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1837         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1838
1839         return OPERATOR_FINISHED;
1840 }
1841
1842 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
1843 {
1844         /* identifiers */
1845         ot->name= "Clean Vertex Group";
1846         ot->idname= "OBJECT_OT_vertex_group_clean";
1847         ot->description= "Remove Vertex Group assignments which aren't required";
1848
1849         /* api callbacks */
1850         ot->poll= vertex_group_poll;
1851         ot->exec= vertex_group_clean_exec;
1852
1853         /* flags */
1854         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1855
1856         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
1857         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
1858         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
1859 }
1860
1861
1862 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
1863 {
1864         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1865
1866         ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
1867
1868         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1869         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1870         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1871
1872         return OPERATOR_FINISHED;
1873 }
1874
1875 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
1876 {
1877         /* identifiers */
1878         ot->name= "Mirror Vertex Group";
1879         ot->idname= "OBJECT_OT_vertex_group_mirror";
1880         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";
1881
1882         /* api callbacks */
1883         ot->poll= vertex_group_poll_edit;
1884         ot->exec= vertex_group_mirror_exec;
1885
1886         /* flags */
1887         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1888
1889         /* properties */
1890         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
1891         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names.");
1892
1893 }
1894
1895 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
1896 {
1897         Scene *scene= CTX_data_scene(C);
1898         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1899         Base *base;
1900         int retval= OPERATOR_CANCELLED;
1901
1902         for(base=scene->base.first; base; base= base->next) {
1903                 if(base->object->type==ob->type) {
1904                         if(base->object!=ob && base->object->data==ob->data) {
1905                                 BLI_freelistN(&base->object->defbase);
1906                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1907                                 base->object->actdef= ob->actdef;
1908
1909                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
1910                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1911                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1912
1913                                 retval = OPERATOR_FINISHED;
1914                         }
1915                 }
1916         }
1917
1918         return retval;
1919 }
1920
1921 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1922 {
1923         /* identifiers */
1924         ot->name= "Copy Vertex Groups to Linked";
1925         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1926         ot->description= "Copy Vertex Groups to all users of the same Geometry data";
1927
1928         /* api callbacks */
1929         ot->poll= vertex_group_poll;
1930         ot->exec= vertex_group_copy_to_linked_exec;
1931
1932         /* flags */
1933         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1934 }
1935
1936 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *UNUSED(op))
1937 {
1938         Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1939
1940         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
1941         {
1942                 if(obact != ob)
1943                         ED_vgroup_copy_array(ob, obact);
1944         }
1945         CTX_DATA_END;
1946
1947         return OPERATOR_FINISHED;
1948 }
1949
1950
1951 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
1952 {
1953         /* identifiers */
1954         ot->name= "Copy Vertex Group to Selected";
1955         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected";
1956         ot->description= "Copy Vertex Groups to other selected objects with matching indices";
1957
1958         /* api callbacks */
1959         ot->poll= vertex_group_poll;
1960         ot->exec= vertex_group_copy_to_selected_exec;
1961
1962         /* flags */
1963         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1964 }
1965
1966 static EnumPropertyItem vgroup_items[]= {
1967         {0, NULL, 0, NULL, NULL}};
1968
1969 static int set_active_group_exec(bContext *C, wmOperator *op)
1970 {
1971         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1972         int nr= RNA_enum_get(op->ptr, "group");
1973
1974         ob->actdef= nr+1;
1975
1976         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1977         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
1978
1979         return OPERATOR_FINISHED;
1980 }
1981
1982 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), int *free)
1983 {       
1984         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1985         EnumPropertyItem tmp = {0, "", 0, "", ""};
1986         EnumPropertyItem *item= NULL;
1987         bDeformGroup *def;
1988         int a, totitem= 0;
1989         
1990         if(!ob)
1991                 return vgroup_items;
1992         
1993         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
1994                 tmp.value= a;
1995                 tmp.icon= ICON_GROUP_VERTEX;
1996                 tmp.identifier= def->name;
1997                 tmp.name= def->name;
1998                 RNA_enum_item_add(&item, &totitem, &tmp);
1999         }
2000
2001         RNA_enum_item_end(&item, &totitem);
2002         *free= 1;
2003
2004         return item;
2005 }
2006
2007 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2008 {
2009         PropertyRNA *prop;
2010
2011         /* identifiers */
2012         ot->name= "Set Active Vertex Group";
2013         ot->idname= "OBJECT_OT_vertex_group_set_active";
2014         ot->description= "Set the active vertex group";
2015
2016         /* api callbacks */
2017         ot->poll= vertex_group_poll;
2018         ot->exec= set_active_group_exec;
2019         ot->invoke= WM_menu_invoke;
2020
2021         /* flags */
2022         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2023
2024         /* properties */
2025         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
2026         RNA_def_enum_funcs(prop, vgroup_itemf);
2027         ot->prop= prop;
2028 }
2029
2030 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling
2031   with the order of vgroups then call vgroup_do_remap after*/
2032 static char *vgroup_init_remap(Object *ob)
2033 {
2034         bDeformGroup *def;
2035         int def_tot = BLI_countlist(&ob->defbase);
2036         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups");
2037         char *name;
2038
2039         name= name_array;
2040         for(def = ob->defbase.first; def; def=def->next) {
2041                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
2042                 name += MAX_VGROUP_NAME;
2043         }
2044
2045         return name_array;
2046 }
2047
2048 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
2049 {
2050         MDeformVert *dvert= NULL;
2051         bDeformGroup *def;
2052         int def_tot = BLI_countlist(&ob->defbase);
2053         int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/
2054         int *sort_map= sort_map_update + 1;
2055         char *name;
2056         int i;
2057
2058         name= name_array;
2059         for(def= ob->defbase.first, i=0; def; def=def->next, i++){
2060                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
2061                 name += MAX_VGROUP_NAME;
2062         }
2063
2064         if(ob->mode == OB_MODE_EDIT) {
2065                 if(ob->type==OB_MESH) {
2066                         BMEditMesh *em = ((Mesh*)ob->data)->edit_btmesh;
2067                         BMIter iter;
2068                         BMVert *eve;
2069
2070                         BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
2071                                 dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
2072                                 if(dvert && dvert->totweight){
2073                                         defvert_remap(dvert, sort_map);
2074                                 }
2075                         }
2076                 }
2077                 else {
2078                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet.");
2079                         MEM_freeN(sort_map_update);
2080                         return OPERATOR_CANCELLED;
2081                 }
2082         }
2083         else {
2084                 int dvert_tot=0;
2085
2086                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
2087
2088                 /*create as necassary*/
2089                 while(dvert && dvert_tot--) {
2090                         if(dvert->totweight)
2091                                 defvert_remap(dvert, sort_map);
2092                         dvert++;
2093                 }
2094         }
2095
2096         /* update users */
2097         for(i=0; i<def_tot; i++)
2098                 sort_map[i]++;
2099
2100         sort_map_update[0]= 0;
2101         vgroup_remap_update_users(ob, sort_map_update);
2102
2103         ob->actdef= sort_map_update[ob->actdef];
2104         
2105         MEM_freeN(sort_map_update);
2106
2107         return OPERATOR_FINISHED;
2108 }
2109
2110 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
2111 {
2112         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
2113         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
2114
2115         return BLI_natstrcmp(def_a->name, def_b->name);
2116 }
2117
2118 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
2119 {
2120         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2121         char *name_array;
2122         int ret;
2123
2124         /*init remapping*/
2125         name_array = vgroup_init_remap(ob);
2126
2127         /*sort vgroup names*/
2128         BLI_sortlist(&ob->defbase, vgroup_sort);
2129
2130         /*remap vgroup data to map to correct names*/
2131         ret = vgroup_do_remap(ob, name_array, op);
2132
2133         if (ret != OPERATOR_CANCELLED) {
2134                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2135                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2136         }
2137
2138         if (name_array) MEM_freeN(name_array);
2139
2140         return ret;
2141 }
2142
2143 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
2144 {
2145         ot->name= "Sort Vertex Groups";
2146         ot->idname= "OBJECT_OT_vertex_group_sort";
2147         ot->description= "Sorts vertex groups alphabetically";
2148
2149         /* api callbacks */
2150         ot->poll= vertex_group_poll;
2151         ot->exec= vertex_group_sort_exec;
2152
2153         /* flags */
2154         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2155 }
2156
2157 static int vgroup_move_exec(bContext *C, wmOperator *op)
2158 {
2159         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2160         bDeformGroup *def;
2161         char *name_array;
2162         int dir= RNA_enum_get(op->ptr, "direction"), ret;
2163
2164         def = BLI_findlink(&ob->defbase, ob->actdef - 1);
2165         if (!def) {
2166                 return OPERATOR_CANCELLED;
2167         }
2168
2169         name_array = vgroup_init_remap(ob);
2170
2171         if (dir == 1) { /*up*/
2172                 void *prev = def->prev;
2173
2174                 BLI_remlink(&ob->defbase, def);
2175                 BLI_insertlinkbefore(&ob->defbase, prev, def);
2176         } else { /*down*/
2177                 void *next = def->next;
2178
2179                 BLI_remlink(&ob->defbase, def);
2180                 BLI_insertlinkafter(&ob->defbase, next, def);
2181         }
2182
2183         ret = vgroup_do_remap(ob, name_array, op);
2184
2185         if (name_array) MEM_freeN(name_array);
2186
2187         if (ret != OPERATOR_CANCELLED) {
2188                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2189                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2190         }
2191
2192         return ret;
2193 }
2194
2195 void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
2196 {
2197         static EnumPropertyItem vgroup_slot_move[] = {
2198                 {1, "UP", 0, "Up", ""},
2199                 {-1, "DOWN", 0, "Down", ""},
2200                 {0, NULL, 0, NULL, NULL}
2201         };
2202
2203         /* identifiers */
2204         ot->name= "Move Vertex Group";
2205         ot->idname= "OBJECT_OT_vertex_group_move";
2206
2207         /* api callbacks */
2208         ot->poll= vertex_group_poll;
2209         ot->exec= vgroup_move_exec;
2210
2211         /* flags */
2212         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2213
2214         RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
2215 }