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