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