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