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