'Fix Deforms' op added to weight paint tools to smooth (remove/reduce) spiking caused...
[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 "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 #include "BKE_DerivedMesh.h"//Jason
64
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67
68 #include "WM_api.h"
69 #include "WM_types.h"
70
71 #include "ED_mesh.h"
72
73 #include "UI_resources.h"
74
75 #include "object_intern.h"
76
77 /************************ Exported Functions **********************/
78 static void vgroup_remap_update_users(Object *ob, int *map);
79 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
80 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
81 static void vgroup_delete_all(Object *ob);
82
83 static Lattice *vgroup_edit_lattice(Object *ob)
84 {
85         Lattice *lt= ob->data;
86         BLI_assert(ob->type==OB_LATTICE);
87         return (lt->editlatt)? lt->editlatt->latt: lt;
88 }
89
90 int ED_vgroup_object_is_edit_mode(Object *ob)
91 {
92         if(ob->type == OB_MESH)
93                 return (((Mesh*)ob->data)->edit_mesh != NULL);
94         else if(ob->type == OB_LATTICE)
95                 return (((Lattice*)ob->data)->editlatt != NULL);
96
97         return 0;
98 }
99
100 bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
101 {
102         bDeformGroup *defgroup;
103         
104         if(!ob || !ELEM(ob->type, OB_MESH, OB_LATTICE))
105                 return NULL;
106         
107         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
108
109         BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
110
111         BLI_addtail(&ob->defbase, defgroup);
112         defgroup_unique_name(defgroup, ob);
113
114         ob->actdef = BLI_countlist(&ob->defbase);
115
116         return defgroup;
117 }
118
119 bDeformGroup *ED_vgroup_add(Object *ob) 
120 {
121         return ED_vgroup_add_name(ob, "Group");
122 }
123
124 void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) 
125 {
126         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
127
128         while (dg) {
129                 if (dg == defgroup)
130                         break;
131                 dg = dg->next;
132         }
133
134         if (dg == NULL)
135                 return;
136
137         if(ED_vgroup_object_is_edit_mode(ob))
138                 vgroup_delete_edit_mode(ob, dg);
139         else
140                 vgroup_delete_object_mode(ob, dg);
141 }
142
143 int ED_vgroup_data_create(ID *id)
144 {
145         /* create deform verts */
146
147         if(GS(id->name)==ID_ME) {
148                 Mesh *me= (Mesh *)id;
149                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
150                 return TRUE;
151         }
152         else if(GS(id->name)==ID_LT) {
153                 Lattice *lt= (Lattice *)id;
154                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
155                 return TRUE;
156         }
157         else {
158                 return FALSE;
159         }
160 }
161
162 static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot)
163 {
164         *dvert_tot = 0;
165         *dvert_arr = NULL;
166
167         if(id) {
168                 switch(GS(id->name)) {
169                         case ID_ME:
170                         {
171                                 Mesh *me = (Mesh *)id;
172
173                                 if(me->edit_mesh) {
174                                         EditMesh *em = me->edit_mesh;
175                                         EditVert *eve;
176                                         int i;
177
178                                         if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
179                                                 return 0;
180                                         }
181
182                                         i= BLI_countlist(&em->verts);
183
184                                         *dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me");
185                                         *dvert_tot = i;
186
187                                         i = 0;
188                                         for (eve=em->verts.first; eve; eve=eve->next, i++) {
189                                                 (*dvert_arr)[i] = CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
190                                         }
191
192                                         return 1;
193                                 }
194                                 else if(me->dvert) {
195                                         int i;
196
197                                         *dvert_tot= me->totvert;
198                                         *dvert_arr= MEM_mallocN(sizeof(void*)*me->totvert, "vgroup parray from me");
199
200                                         for (i=0; i<me->totvert; i++) {
201                                                 (*dvert_arr)[i] = me->dvert + i;
202                                         }
203
204                                         return 1;
205                                 }
206                                 else {
207                                         return 0;
208                                 }
209                         }
210                         case ID_LT:
211                         {
212                                 int i=0;
213
214                                 Lattice *lt= (Lattice *)id;
215                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
216
217                                 if(lt->dvert) {
218                                         *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
219                                         *dvert_arr= MEM_mallocN(sizeof(void*)*(*dvert_tot), "vgroup parray from me");
220
221                                         for (i=0; i<*dvert_tot; i++) {
222                                                 (*dvert_arr)[i] = lt->dvert + i;
223                                         }
224
225                                         return 1;
226                                 }
227                                 else {
228                                         return 0;
229                                 }
230                         }
231                 }
232         }
233
234         return 0;
235 }
236
237 /* returns true if the id type supports weights */
238 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
239 {
240         if(id) {
241                 switch(GS(id->name)) {
242                         case ID_ME:
243                         {
244                                 Mesh *me = (Mesh *)id;
245                                 *dvert_arr= me->dvert;
246                                 *dvert_tot= me->totvert;
247                                 return TRUE;
248                         }
249                         case ID_LT:
250                         {
251                                 Lattice *lt= (Lattice *)id;
252                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
253                                 *dvert_arr= lt->dvert;
254                                 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
255                                 return TRUE;
256                         }
257                 }
258         }
259
260         *dvert_arr= NULL;
261         *dvert_tot= 0;
262         return FALSE;
263 }
264
265 /* matching index only */
266 int ED_vgroup_copy_array(Object *ob, Object *ob_from)
267 {
268         MDeformVert **dvert_array_from, **dvf;
269         MDeformVert **dvert_array, **dv;
270         int dvert_tot_from;
271         int dvert_tot;
272         int i;
273         int totdef_from= BLI_countlist(&ob_from->defbase);
274         int totdef= BLI_countlist(&ob->defbase);
275         short new_vgroup= FALSE;
276
277         ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from);
278         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
279
280         if((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
281                 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
282                 new_vgroup= TRUE;
283         }
284
285         if(ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) {
286                 if (dvert_array) MEM_freeN(dvert_array);
287                 if (dvert_array_from) MEM_freeN(dvert_array_from);
288
289                 if(new_vgroup == TRUE) {
290                         /* free the newly added vgroup since it wasn't compatible */
291                         vgroup_delete_all(ob);
292                 }
293                 return 0;
294         }
295
296         /* do the copy */
297         BLI_freelistN(&ob->defbase);
298         BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
299         ob->actdef= ob_from->actdef;
300
301         if(totdef_from < totdef) {
302                 /* correct vgroup indices because the number of vgroups is being reduced. */
303                 int *remap= MEM_mallocN(sizeof(int) * (totdef + 1), "ED_vgroup_copy_array");
304                 for(i=0; i<=totdef_from; i++) remap[i]= i;
305                 for(; i<=totdef; i++) remap[i]= 0; /* can't use these, so disable */
306
307                 vgroup_remap_update_users(ob, remap);
308                 MEM_freeN(remap);
309         }
310
311         dvf= dvert_array_from;
312         dv= dvert_array;
313
314         for(i=0; i<dvert_tot; i++, dvf++, dv++) {
315                 if((*dv)->dw)
316                         MEM_freeN((*dv)->dw);
317
318                 *(*dv)= *(*dvf);
319
320                 if((*dv)->dw)
321                         (*dv)->dw= MEM_dupallocN((*dv)->dw);
322         }
323
324         MEM_freeN(dvert_array);
325         MEM_freeN(dvert_array_from);
326
327         return 1;
328 }
329
330 /* for mesh in object mode
331    lattice can be in editmode */
332 static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
333 {
334         /* This routine removes the vertex from the deform
335          * group with number def_nr.
336          *
337          * This routine is meant to be fast, so it is the
338          * responsibility of the calling routine to:
339          *   a) test whether ob is non-NULL
340          *   b) test whether ob is a mesh
341          *   c) calculate def_nr
342          */
343
344         MDeformWeight *newdw;
345         MDeformVert *dvert= NULL;
346         int i, tot;
347
348         /* get the deform vertices corresponding to the
349          * vertnum
350          */
351         ED_vgroup_give_array(ob->data, &dvert, &tot);
352
353         if(dvert==NULL)
354                 return;
355         
356         dvert+= vertnum;
357
358         /* for all of the deform weights in the
359          * deform vert
360          */
361         for(i=dvert->totweight - 1 ; i>=0 ; i--){
362
363                 /* if the def_nr is the same as the one
364                  * for our weight group then remove it
365                  * from this deform vert.
366                  */
367                 if(dvert->dw[i].def_nr == def_nr) {
368                         dvert->totweight--;
369
370                         /* if there are still other deform weights
371                          * attached to this vert then remove this
372                          * deform weight, and reshuffle the others
373                          */
374                         if(dvert->totweight) {
375                                 newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), 
376                                                                          "deformWeight");
377                                 if(dvert->dw){
378                                         memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
379                                         memcpy(newdw+i, dvert->dw+i+1, 
380                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
381                                         MEM_freeN(dvert->dw);
382                                 }
383                                 dvert->dw=newdw;
384                         }
385                         /* if there are no other deform weights
386                          * left then just remove the deform weight
387                          */
388                         else {
389                                 MEM_freeN(dvert->dw);
390                                 dvert->dw = NULL;
391                                 break;
392                         }
393                 }
394         }
395
396 }
397
398 /* for Mesh in Object mode */
399 /* allows editmode for Lattice */
400 static void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode)
401 {
402         /* add the vert to the deform group with the
403          * specified number
404          */
405         MDeformVert *dv= NULL;
406         MDeformWeight *newdw;
407         int     i, tot;
408
409         /* get the vert */
410         ED_vgroup_give_array(ob->data, &dv, &tot);
411         
412         if(dv==NULL)
413                 return;
414         
415         /* check that vertnum is valid before trying to get the relevant dvert */
416         if ((vertnum < 0) || (vertnum >= tot))
417                 return;
418         else
419                 dv += vertnum;
420
421         /* Lets first check to see if this vert is
422          * already in the weight group -- if so
423          * lets update it
424          */
425         for(i=0; i<dv->totweight; i++){
426                 
427                 /* if this weight cooresponds to the
428                  * deform group, then add it using
429                  * the assign mode provided
430                  */
431                 if(dv->dw[i].def_nr == def_nr){
432                         
433                         switch(assignmode) {
434                         case WEIGHT_REPLACE:
435                                 dv->dw[i].weight=weight;
436                                 break;
437                         case WEIGHT_ADD:
438                                 dv->dw[i].weight+=weight;
439                                 if(dv->dw[i].weight >= 1.0f)
440                                         dv->dw[i].weight = 1.0f;
441                                 break;
442                         case WEIGHT_SUBTRACT:
443                                 dv->dw[i].weight-=weight;
444                                 /* if the weight is zero or less then
445                                  * remove the vert from the deform group
446                                  */
447                                 if(dv->dw[i].weight <= 0.0f)
448                                         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
449                                 break;
450                         }
451                         return;
452                 }
453         }
454
455         /* if the vert wasn't in the deform group then
456          * we must take a different form of action ...
457          */
458
459         switch(assignmode) {
460         case WEIGHT_SUBTRACT:
461                 /* if we are subtracting then we don't
462                  * need to do anything
463                  */
464                 return;
465
466         case WEIGHT_REPLACE:
467         case WEIGHT_ADD:
468                 /* if we are doing an additive assignment, then
469                  * we need to create the deform weight
470                  */
471                 newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), 
472                                                          "deformWeight");
473                 if(dv->dw){
474                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
475                         MEM_freeN(dv->dw);
476                 }
477                 dv->dw=newdw;
478
479                 dv->dw[dv->totweight].weight=weight;
480                 dv->dw[dv->totweight].def_nr=def_nr;
481
482                 dv->totweight++;
483                 break;
484         }
485 }
486
487 /* called while not in editmode */
488 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
489 {
490         /* add the vert to the deform group with the
491          * specified assign mode
492          */
493         int     def_nr;
494
495         MDeformVert *dv= NULL;
496         int tot;
497
498         /* get the deform group number, exit if
499          * it can't be found
500          */
501         def_nr = defgroup_find_index(ob, dg);
502         if(def_nr < 0) return;
503
504         /* if there's no deform verts then create some,
505          */
506         if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
507                 ED_vgroup_data_create(ob->data);
508
509         /* call another function to do the work
510          */
511         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
512 }
513
514 /* mesh object mode, lattice can be in editmode */
515 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
516 {
517         /* This routine removes the vertex from the specified
518          * deform group.
519          */
520         const int def_nr= defgroup_find_index(ob, dg);
521         if(def_nr < 0)
522                 return;
523
524         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
525 }
526
527 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
528 {
529         MDeformVert *dvert= NULL;
530         EditVert *eve;
531         Mesh *me;
532         int i;
533
534         /* get the deform vertices corresponding to the vertnum */
535         if(ob->type==OB_MESH) {
536                 me= ob->data;
537
538                 if(me->edit_mesh) {
539                         eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
540                         if(!eve) {
541                                 return 0.0f;
542                         }
543                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
544                         vertnum= 0;
545                 }
546                 else {
547                         if(vertnum >= me->totvert) {
548                                 return 0.0f;
549                         }
550                         dvert = me->dvert;
551                 }
552         }
553         else if(ob->type==OB_LATTICE) {
554                 Lattice *lt= vgroup_edit_lattice(ob);
555
556                 if(lt->dvert) {
557                         if(vertnum >= lt->pntsu*lt->pntsv*lt->pntsw) {
558                                 return 0.0f;
559                         }
560                         dvert = lt->dvert;
561                 }
562         }
563         
564         if(dvert==NULL)
565                 return -1;
566         
567         dvert += vertnum;
568         
569         for(i=dvert->totweight-1 ; i>=0 ; i--)
570                 if(dvert->dw[i].def_nr == def_nr)
571                         return dvert->dw[i].weight;
572
573         return -1;
574 }
575
576 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
577 {
578         int def_nr;
579
580         if(!ob) return -1;
581
582         def_nr = defgroup_find_index(ob, dg);
583         if(def_nr < 0) return -1;
584
585         return get_vert_def_nr(ob, def_nr, vertnum);
586 }
587
588 void ED_vgroup_select_by_name(Object *ob, const char *name)
589 {       /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */
590         ob->actdef= defgroup_name_index(ob, name) + 1;
591 }
592
593 /********************** Operator Implementations *********************/
594
595 /* only in editmode */
596 static void vgroup_select_verts(Object *ob, int select)
597 {
598         EditVert *eve;
599         MDeformVert *dvert;
600         int i;
601
602         if(ob->type == OB_MESH) {
603                 Mesh *me= ob->data;
604                 EditMesh *em = BKE_mesh_get_editmesh(me);
605
606                 for(eve=em->verts.first; eve; eve=eve->next){
607                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
608
609                         if(dvert && dvert->totweight){
610                                 for(i=0; i<dvert->totweight; i++){
611                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
612                                                 if(!eve->h) {
613                                                         if(select) eve->f |= SELECT;
614                                                         else eve->f &= ~SELECT;
615                                                 }
616                                                 break;
617                                         }
618                                 }
619                         }
620                 }
621                 /* this has to be called, because this function operates on vertices only */
622                 if(select) EM_select_flush(em); // vertices to edges/faces
623                 else EM_deselect_flush(em);
624
625                 BKE_mesh_end_editmesh(me, em);
626         }
627         else if(ob->type == OB_LATTICE) {
628                 Lattice *lt= vgroup_edit_lattice(ob);
629                 
630                 if(lt->dvert) {
631                         BPoint *bp;
632                         int a, tot;
633                         
634                         dvert= lt->dvert;
635
636                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
637                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
638                                 for(i=0; i<dvert->totweight; i++){
639                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
640                                                 if(select) bp->f1 |= SELECT;
641                                                 else bp->f1 &= ~SELECT;
642                                                 
643                                                 break;
644                                         }
645                                 }
646                         }
647                 }
648         }
649 }
650
651 static void vgroup_duplicate(Object *ob)
652 {
653         bDeformGroup *dg, *cdg;
654         char name[sizeof(dg->name)];
655         MDeformWeight *org, *cpy;
656         MDeformVert *dvert, **dvert_array=NULL;
657         int i, idg, icdg, dvert_tot=0;
658
659         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
660         if(!dg)
661                 return;
662         
663         if(!strstr(dg->name, "_copy")) {
664                 BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
665         }
666         else {
667                 BLI_snprintf(name, sizeof(name), "%s", dg->name);
668         }
669
670         cdg = defgroup_duplicate(dg);
671         strcpy(cdg->name, name);
672         defgroup_unique_name(cdg, ob);
673
674         BLI_addtail(&ob->defbase, cdg);
675
676         idg = (ob->actdef-1);
677         ob->actdef = BLI_countlist(&ob->defbase);
678         icdg = (ob->actdef-1);
679
680         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
681         
682         if(!dvert_array)
683                 return;
684
685         for(i = 0; i < dvert_tot; i++) {
686                 dvert = dvert_array[i];
687                 org = defvert_find_index(dvert, idg);
688                 if(org) {
689                         float weight = org->weight;
690                         /* defvert_verify_index re-allocs org so need to store the weight first */
691                         cpy = defvert_verify_index(dvert, icdg);
692                         cpy->weight = weight;
693                 }
694         }
695
696         MEM_freeN(dvert_array);
697 }
698
699 static void vgroup_normalize(Object *ob)
700 {
701         bDeformGroup *dg;
702         MDeformWeight *dw;
703         MDeformVert *dvert, **dvert_array=NULL;
704         int i, def_nr, dvert_tot=0;
705         // Jason
706         Mesh *me = ob->data;
707         MVert *mv = me->mvert;
708         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
709
710         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
711
712         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
713
714         if(dg) {
715                 float weight_max = 0.0f;
716
717                 def_nr= ob->actdef-1;
718
719                 for(i = 0; i < dvert_tot; i++) {
720                         // Jason
721                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
722                                 continue;
723                         }
724
725                         dvert = dvert_array[i];
726                         dw = defvert_find_index(dvert, def_nr);
727                         if(dw) {
728                                 weight_max = MAX2(dw->weight, weight_max);
729                         }
730                 }
731
732                 if(weight_max > 0.0f) {
733                         for(i = 0; i < dvert_tot; i++) {
734                                 // Jason
735                                 if(selectedVerts && !((mv+i)->flag & SELECT)) {
736                                         continue;
737                                 }
738
739                                 dvert = dvert_array[i];
740                                 dw = defvert_find_index(dvert, def_nr);
741                                 if(dw) {
742                                         dw->weight /= weight_max;
743                                         
744                                         /* incase of division errors with very low weights */
745                                         CLAMP(dw->weight, 0.0f, 1.0f);
746                                 }
747                         }
748                 }
749         }
750
751         if (dvert_array) MEM_freeN(dvert_array);
752 }
753 // Jason
754 static int tryToAddVerts(int *verts, int length, int a, int b) {
755         char containsA = FALSE;
756         char containsB = FALSE;
757         int added = 0;
758         int i;
759         for(i = 0; i < length && (!containsA || !containsB); i++) {
760                 if(verts[i] == a) {
761                         containsA = TRUE;
762                 } else if(verts[i] == b) {
763                         containsB = TRUE;
764                 } else if(verts[i] == -1) {
765                         if(!containsA) {
766                                 verts[i] = a;
767                                 containsA = TRUE;
768                                 added++;
769                         } else if(!containsB){
770                                 verts[i] = b;
771                                 containsB = TRUE;
772                                 added++;
773                         }
774                 }
775         }
776         return added;
777 }
778 //Jason
779 static int* getSurroundingVerts(Mesh *me, int vert, int *count) {
780         int length = 0;
781         int *tverts;
782         int *verts = NULL;
783         MFace *mf = me->mface;
784         int totface = me->totface;
785         int found = 0;
786         int i;
787         for(i = 0; i < totface; i++, mf++) {
788                 if(vert == mf->v1 || vert == mf->v2 || vert == mf->v3 || (mf->v4 &&vert == mf->v4)) {
789                         length+=2;
790                 }
791         }
792         if(!length) {
793                 return 0;
794         }
795         tverts = MEM_mallocN(sizeof(int)*length, "tempSurroundingVerts");
796         mf = me->mface;
797         for(i = 0; i < length; i++) {
798                 tverts[i] = -1;
799         }
800         for(i = 0; i < totface; i++, mf++) {
801                 int a=-1, b=-1;
802                 //printf("face %d verts: %d %d %d %d\n", i, mf->v1, mf->v2, mf->v3, mf->v4);
803                 if(mf->v1 == vert) {
804                         a = mf->v2;
805                         if(mf->v4) {
806                                 b = mf->v4;
807                         } else {
808                                 b = mf->v3;
809                         }
810                 } else if(mf->v2 == vert) {
811                         a = mf->v1;
812                         b = mf->v3;
813                 } else if(mf->v3 == vert) {
814                         a = mf->v2;
815                         if(mf->v4) {
816                                 b = mf->v4;
817                         } else {
818                                 b = mf->v1;
819                         }
820                 } else if (mf->v4 && mf->v4 == vert){
821                         a = mf->v1;
822                         b = mf->v3;
823                 } else {
824                         continue;
825                 }
826                 found += tryToAddVerts(tverts, length, a, b);
827         }
828         if(found) {
829                 verts = MEM_mallocN(sizeof(int)* found, "surroundingVerts");
830                 for(i = 0; i < found; i++) {
831                         verts[i] = tverts[i];
832                 }
833                 count[0] = found;
834         }
835         MEM_freeN(tverts);
836         return verts;
837 }
838 static void getSingleCoordinate(MVert **points, int count, float *coord) {
839         int i, k;
840         for(k = 0; k < 3; k++) {
841                 coord[k] = 0;
842         }
843         for(i = 0; i < count; i++) {
844                 for(k = 0; k < 3; k++) {
845                         coord[k] += points[i]->co[k];
846                 }
847         }
848         for(k = 0; k < 3; k++) {
849                 coord[k] /= count;
850         }
851 }
852 static void getNearestPointOnPlane(float *norm, float d, float *coord, float *point, float *dst) {
853         float *temp = MEM_callocN(sizeof(float)*3, "temp");
854         int i;
855         float dotprod = 0;
856         for(i = 0; i < 3; i++) {
857                 temp[i] = point[i]-coord[i];
858         }
859         for(i = 0; i < 3; i++) {
860                 dotprod += temp[i]*norm[i];
861         }
862         MEM_freeN(temp);
863         for(i = 0; i < 3; i++) {
864                 dst[i] = point[i] - dotprod*norm[i];
865         }
866 }
867 static float distance(float* a, float *b, int length) {
868         int i;
869         float sum = 0;
870         for(i = 0; i < length; i++) {
871                 sum += (b[i]-a[i])*(b[i]-a[i]);
872         }
873         return sqrt(sum);
874 }
875 static void getVerticalAndHorizontalChange(float *norm, float d, float *coord, float *start, float distToStart, float *end, float **changes, int index) {
876         // A=Q-((Q-P).N)N
877         // D = (a*x0 + b*y0 +c*z0 +d)
878         float *projA, *projB;
879         projA = MEM_callocN(sizeof(float)*3, "projectedA");
880         projB = MEM_callocN(sizeof(float)*3, "projectedB");
881         getNearestPointOnPlane(norm, d, coord, start, projA);
882         getNearestPointOnPlane(norm, d, coord, end, projB);
883         // vertical change
884         changes[index][0] = norm[0]*end[0] + norm[1]*end[1] + norm[2]*end[2] + d - distToStart;
885         //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]);
886         // horizontal change
887         changes[index][1] = distance(projA, projB, 3);
888         MEM_freeN(projA);
889         MEM_freeN(projB);
890 }
891 static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float *norm, float *coord, float d, float distToBe, float strength, float cp) {
892         DerivedMesh *dm;
893         MDeformWeight *dw;
894         MVert m;
895         MDeformVert *dvert = me->dvert+index;
896         int totweight = dvert->totweight;
897         float oldw = 0;
898         float *oldPos = MEM_callocN(sizeof(float)*3, "oldPosition");
899         float vc, hc;
900         int i, k;
901         float **changes = MEM_mallocN(sizeof(float)*totweight, "vertHorzChange");
902         int *upDown = MEM_callocN(sizeof(int)*totweight, "upDownTracker");// track if up or down moved it closer for each bone
903         int *dwIndices = MEM_callocN(sizeof(int)*totweight, "dwIndexTracker");
904         float distToStart;
905         float bestChange = 0;
906         int bestIndex = 0;
907         char wasChange;
908         char wasUp;
909         int lastIndex = -1;
910         float originalDistToBe = distToBe;
911         for(i = 0; i < totweight; i++) {
912                 changes[i] = MEM_callocN(sizeof(float)*2, "vertHorzChange_"+i);
913         }
914         do {
915                 wasChange = FALSE;
916                 dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
917                 dm->getVert(dm, index, &m);
918                 oldPos[0] = m.co[0];
919                 oldPos[1] = m.co[1];
920                 oldPos[2] = m.co[2];
921                 distToStart = norm[0]*oldPos[0] + norm[1]*oldPos[1] + norm[2]*oldPos[2] + d;
922                 //printf("dist %f \n",distToStart);
923                 //printf("mesh point %f %f %f dpoint %f %f %f \n", (me->mvert+index)->co[0], (me->mvert+index)->co[1], (me->mvert+index)->co[3], oldPos[0], oldPos[1], oldPos[2]);
924                 if(distToBe == originalDistToBe) {
925                         distToBe += distToStart - distToStart*strength;
926                 }
927                 for(i = 0; i < totweight; i++) {
928                         dwIndices[i] = i;
929                         dw = (dvert->dw+i);
930                         vc = hc = 0;
931                         if(!dw->weight) {
932                                 changes[i][0] = 0;
933                                 changes[i][1] = 0;
934                                 continue;
935                         }
936                         for(k = 0; k < 2; k++) {
937                                 if(dm) {
938                                         dm->needsFree = 1;
939                                         dm->release(dm);
940                                         dm = NULL;
941                                         ob->derivedDeform=NULL;
942                                 }
943                                 oldw = dw->weight;
944                                 if(k) {
945                                         dw->weight *= 1+cp;
946                                 } else {
947                                         dw->weight /= 1+cp;
948                                 }
949                                 if(dw->weight == oldw) {
950                                         changes[i][0] = 0;
951                                         changes[i][1] = 0;
952                                         break;
953                                 }
954                                 if(dw->weight > 1) {
955                                         dw->weight = 1;
956                                 }
957                                 dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
958                                 dm->getVert(dm, index, &m);
959                                 getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, i);
960                                 dw->weight = oldw;
961                                 if(!k) {
962                                         vc = changes[i][0];
963                                         hc = changes[i][1];
964                                 } else {
965                                         if(fabs(distToStart+vc - distToBe) < fabs(distToStart+changes[i][0] - distToBe)) {
966                                                 upDown[i] = 0;
967                                                 changes[i][0] = vc;
968                                                 changes[i][1] = hc;
969                                         } else {
970                                                 upDown[i] = 1;
971                                         }
972                                         if(fabs(distToStart+changes[i][0] - distToBe) > fabs(distToStart - distToBe)) {
973                                                 changes[i][0] = 0;
974                                                 changes[i][1] = 0;
975                                         }
976                                 }
977                         }
978                         //printf("final vc: %f\n", changes[i][0]);
979                 }
980                 // sort the changes by the vertical change
981                 for(k = 0; k < totweight; k++) {
982                         float tf;
983                         int ti;
984                         bestChange = changes[k][0];
985                         bestIndex = k;
986                         for(i = k+1; i < totweight; i++) {
987                                 vc = changes[i][0];
988
989                                 if(fabs(vc) > fabs(bestChange)) {
990                                         bestIndex = i;
991                                         bestChange = vc;
992                                 }
993                         }
994                         // switch with k
995                         if(bestIndex != k) {
996                                 ti = upDown[k];
997                                 upDown[k] = upDown[bestIndex];
998                                 upDown[bestIndex] = ti;
999
1000                                 ti = dwIndices[k];
1001                                 dwIndices[k] = dwIndices[bestIndex];
1002                                 dwIndices[bestIndex] = ti;
1003
1004                                 tf = changes[k][0];
1005                                 changes[k][0] = changes[bestIndex][0];
1006                                 changes[bestIndex][0] = tf;
1007
1008                                 tf = changes[k][1];
1009                                 changes[k][1] = changes[bestIndex][1];
1010                                 changes[bestIndex][1] = tf;
1011                         }
1012                 }
1013                 bestIndex = -1;
1014                 // find the best change with an acceptable horizontal change
1015                 for(i = 0; i < totweight; i++) {
1016                         if(fabs(changes[i][0]) > fabs(changes[i][1]*2.0f)) {
1017                                 bestIndex = i;
1018                                 break;
1019                         }
1020                 }
1021                 if(bestIndex != -1) {
1022                         //printf("changing %d\n", bestIndex);
1023                         wasChange = TRUE;
1024                         if(lastIndex != -1) {
1025                                 if(wasUp != upDown[bestIndex]) {
1026                                         wasChange = FALSE;
1027                                 }
1028                         }
1029                         lastIndex = bestIndex;
1030                         wasUp = upDown[bestIndex];
1031                         dw = (dvert->dw+dwIndices[bestIndex]);
1032                         oldw = dw->weight;
1033                         if(upDown[bestIndex]) {
1034                                 dw->weight *= 1+cp;
1035                         } else {
1036                                 dw->weight /= 1+cp;
1037                         }
1038                         if(dw->weight > 1) {
1039                                 dw->weight = 1;
1040                         }
1041                         if(oldw == dw->weight) {
1042                                 wasChange = FALSE;
1043                         }
1044                         if(dm) {
1045                                 dm->needsFree = 1;
1046                                 dm->release(dm);
1047                                 dm = NULL;
1048                                 ob->derivedDeform=NULL;
1049                         }
1050                 }
1051                 //printf("best vc=%f hc=%f \n", changes[bestIndex][0], changes[bestIndex][1]);
1052         }while(wasChange && (distToStart-distToBe)/fabs(distToStart-distToBe) == (distToStart+changes[bestIndex][0]-distToBe)/fabs(distToStart+changes[bestIndex][0]-distToBe));
1053         MEM_freeN(upDown);
1054         for(i = 0; i < totweight; i++) {
1055                 MEM_freeN(changes[i]);
1056         }
1057         MEM_freeN(changes);
1058         MEM_freeN(dwIndices);
1059         MEM_freeN(oldPos);
1060 }
1061 // Jason
1062 static void vgroup_fix(Scene *scene, Object *ob, float strength, float cp)
1063 {
1064         int i;
1065
1066         Mesh *me = ob->data;
1067         MVert *mv = me->mvert;
1068         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1069         int *verts = NULL;      
1070
1071         for(i = 0; i < me->totvert && mv; i++, mv++) {
1072                 // Jason
1073                 if(selectedVerts && (mv->flag & SELECT)) {
1074                         int *pcount = MEM_callocN(sizeof(int), "intPointer");
1075                         int count;
1076                         if((verts = getSurroundingVerts(me, i, pcount))) {
1077                                 MVert m;
1078                                 MVert **p = MEM_callocN(sizeof(MVert*)*(count = pcount[0]), "deformedPoints");
1079                                 int k;
1080
1081                                 DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
1082                                 for(k = 0; k < count; k++) {
1083                                         dm->getVert(dm, verts[k], &m);
1084                                         p[k] = &m;
1085                                         //printf("deformed coords %f %f %f\n", p[k]->co[0], p[k]->co[1], p[k]->co[2]);
1086                                 }
1087                                 
1088                                 if(count >= 3) {
1089                                         float d, dist, mag;
1090                                         float *coord = MEM_callocN(sizeof(float)*3, "deformedCoord");
1091                                         float *norm = MEM_callocN(sizeof(float)*3, "planeNorm");
1092                                         getSingleCoordinate(p, count, coord);
1093                                         dm->getVert(dm, i, &m);
1094                                         norm[0] = m.co[0]-coord[0];
1095                                         norm[1] = m.co[1]-coord[1];
1096                                         norm[2] = m.co[2]-coord[2];
1097                                         mag = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
1098                                         for(k = 0; k < 3; k++) {
1099                                                 norm[k]/=mag;
1100                                         }
1101                                         d = -norm[0]*coord[0] -norm[1]*coord[1] -norm[2]*coord[2];
1102                                         dist = (norm[0]*m.co[0] + norm[1]*m.co[1] + norm[2]*m.co[2] + d);
1103                                         //printf("status plane: (%f %f %f) %f dist: %f\n", norm[0], norm[1], norm[2], d, dist);
1104                                         moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, 0, strength, cp);
1105                                         MEM_freeN(coord);
1106                                         MEM_freeN(norm);
1107                                 }
1108
1109                                 MEM_freeN(verts);
1110                                 MEM_freeN(p);
1111                         }
1112                         MEM_freeN(pcount);
1113                 }
1114         }
1115 }
1116
1117 static void vgroup_levels(Object *ob, float offset, float gain)
1118 {
1119         bDeformGroup *dg;
1120         MDeformWeight *dw;
1121         MDeformVert *dvert, **dvert_array=NULL;
1122         int i, def_nr, dvert_tot=0;
1123         // Jason
1124         Mesh *me = ob->data;
1125         MVert *mv = me->mvert;
1126         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1127
1128         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1129         
1130         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1131         
1132         if(dg) {
1133                 def_nr= ob->actdef-1;
1134                 
1135                 for(i = 0; i < dvert_tot; i++) {
1136                         // Jason
1137                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1138                                 continue;
1139                         }
1140
1141                         dvert = dvert_array[i];
1142                         dw = defvert_find_index(dvert, def_nr);
1143                         if(dw) {
1144                                 dw->weight = gain * (dw->weight + offset);
1145                                 
1146                                 CLAMP(dw->weight, 0.0f, 1.0f);
1147                         }
1148                 }
1149         }
1150
1151         if (dvert_array) MEM_freeN(dvert_array);
1152 }
1153
1154 /* TODO - select between groups */
1155 static void vgroup_normalize_all(Object *ob, int lock_active)
1156 {
1157         MDeformWeight *dw, *dw_act;
1158         MDeformVert *dvert, **dvert_array=NULL;
1159         int i, dvert_tot=0;
1160         float tot_weight;
1161
1162         // Jason
1163         Mesh *me = ob->data;
1164         MVert *mv = me->mvert;
1165         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1166
1167         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1168
1169         if(dvert_array) {
1170                 if(lock_active) {
1171                         int def_nr= ob->actdef-1;
1172
1173                         for(i = 0; i < dvert_tot; i++) {
1174                                 float lock_iweight= 1.0f;
1175                                 int j;
1176                                 // Jason
1177                                 if(selectedVerts && !((mv+i)->flag & SELECT)) {
1178                                         continue;
1179                                 }
1180
1181                                 tot_weight= 0.0f;
1182                                 dw_act= NULL;
1183                                 dvert = dvert_array[i];
1184
1185                                 j= dvert->totweight;
1186                                 while(j--) {
1187                                         dw= dvert->dw + j;
1188
1189                                         if(dw->def_nr==def_nr) {
1190                                                 dw_act= dw;
1191                                                 lock_iweight = (1.0f - dw_act->weight);
1192                                         }
1193                                         else {
1194                                                 tot_weight += dw->weight;
1195                                         }
1196                                 }
1197
1198                                 if(tot_weight) {
1199                                         j= dvert->totweight;
1200                                         while(j--) {
1201                                                 dw= dvert->dw + j;
1202                                                 if(dw == dw_act) {
1203                                                         if (dvert->totweight==1) {
1204                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
1205                                                         }
1206                                                 } else {
1207                                                         if(dw->weight > 0.0f)
1208                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
1209                                                 }
1210
1211                                                 /* incase of division errors with very low weights */
1212                                                 CLAMP(dw->weight, 0.0f, 1.0f);
1213                                         }
1214                                 }
1215                         }
1216                 }
1217                 else {
1218                         for(i = 0; i < dvert_tot; i++) {
1219                                 int j;
1220                                 // Jason
1221                                 if(selectedVerts && !((mv+i)->flag & SELECT)) {
1222                                         continue;
1223                                 }
1224
1225                                 tot_weight= 0.0f;
1226                                 dvert = dvert_array[i];
1227
1228                                 j= dvert->totweight;
1229                                 while(j--) {
1230                                         dw= dvert->dw + j;
1231                                         tot_weight += dw->weight;
1232                                 }
1233
1234                                 if(tot_weight) {
1235                                         j= dvert->totweight;
1236                                         while(j--) {
1237                                                 dw= dvert->dw + j;
1238                                                 dw->weight /= tot_weight;
1239
1240                                                 /* incase of division errors with very low weights */
1241                                                 CLAMP(dw->weight, 0.0f, 1.0f);
1242                                         }
1243                                 }
1244                         }
1245                 }
1246         }
1247
1248         if (dvert_array) MEM_freeN(dvert_array);
1249 }
1250 /* Jason was here */
1251 static void vgroup_invert_locks(Object *ob)
1252 {
1253         bDeformGroup *dg = ob->defbase.first;
1254         while(dg) {
1255                 dg->flag = !dg->flag;
1256                 dg = dg->next;
1257         }
1258 }
1259 /* Jason was here */
1260 static void vgroup_lock_all(Object *ob)
1261 {
1262         bDeformGroup *dg = ob->defbase.first;
1263         while(dg) {
1264                 dg->flag = TRUE;
1265                 dg = dg->next;
1266         }
1267 }
1268 /* Jason was here */
1269 static void vgroup_unlock_all(Object *ob)
1270 {
1271         bDeformGroup *dg = ob->defbase.first;
1272         while(dg) {
1273                 dg->flag = FALSE;
1274                 dg = dg->next;
1275         }
1276 }
1277
1278 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
1279 {
1280         bDeformGroup *dg;
1281         MDeformWeight *dw;
1282         MDeformVert *dvert, **dvert_array=NULL;
1283         int i, def_nr, dvert_tot=0;
1284         // Jason
1285         Mesh *me = ob->data;
1286         MVert *mv = me->mvert;
1287         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1288
1289         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1290
1291         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1292
1293         if(dg) {
1294                 def_nr= ob->actdef-1;
1295
1296
1297                 for(i = 0; i < dvert_tot; i++) {
1298                         // Jason
1299                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1300                                 continue;
1301                         }
1302                         dvert = dvert_array[i];
1303
1304                         if(auto_assign) {
1305                                 dw= defvert_verify_index(dvert, def_nr);
1306                         } else {
1307                                 dw= defvert_find_index(dvert, def_nr);
1308                         }
1309
1310                         if(dw) {
1311                                 dw->weight = 1.0f-dw->weight;
1312
1313                                 if(auto_remove && dw->weight <= 0.0f) {
1314                                         /* could have a faster function for this */
1315                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
1316                                 }
1317                         }
1318                 }
1319         }
1320
1321         if (dvert_array) MEM_freeN(dvert_array);
1322 }
1323
1324 static void vgroup_blend(Object *ob)
1325 {
1326         bDeformGroup *dg;
1327         MDeformWeight *dw;
1328         MDeformVert *dvert_array=NULL, *dvert;
1329         int i, def_nr, dvert_tot=0;
1330
1331         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
1332         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1333
1334         if(em==NULL)
1335                 return;
1336
1337         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1338
1339         if(dg) {
1340                 int sel1, sel2;
1341                 int i1, i2;
1342
1343                 EditEdge *eed;
1344                 EditVert *eve;
1345                 float *vg_weights;
1346                 float *vg_users;
1347
1348                 def_nr= ob->actdef-1;
1349
1350                 i= 0;
1351                 for(eve= em->verts.first; eve; eve= eve->next)
1352                         eve->tmp.l= i++;
1353
1354                 dvert_tot= i;
1355
1356                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
1357                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
1358
1359                 for(eed= em->edges.first; eed; eed= eed->next) {
1360                         sel1= eed->v1->f & SELECT;
1361                         sel2= eed->v2->f & SELECT;
1362
1363                         if(sel1 != sel2) {
1364                                 /* i1 is always the selected one */
1365                                 if(sel1==TRUE && sel2==FALSE) {
1366                                         i1= eed->v1->tmp.l;
1367                                         i2= eed->v2->tmp.l;
1368                                         eve= eed->v2;
1369                                 }
1370                                 else {
1371                                         i2= eed->v1->tmp.l;
1372                                         i1= eed->v2->tmp.l;
1373                                         eve= eed->v1;
1374                                 }
1375
1376                                 vg_users[i1]++;
1377
1378                                 /* TODO, we may want object mode blending */
1379                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1380                                 else    dvert= dvert_array+i2;
1381
1382                                 dw= defvert_find_index(dvert, def_nr);
1383
1384                                 if(dw) {
1385                                         vg_weights[i1] += dw->weight;
1386                                 }
1387                         }
1388                 }
1389
1390                 i= 0;
1391                 for(eve= em->verts.first; eve; eve= eve->next) {
1392                         if(eve->f & SELECT && vg_users[i] > 0) {
1393                                 /* TODO, we may want object mode blending */
1394                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1395                                 else    dvert= dvert_array+i;
1396
1397                                 dw= defvert_verify_index(dvert, def_nr);
1398                                 dw->weight= vg_weights[i] / (float)vg_users[i];
1399                         }
1400
1401                         i++;
1402                 }
1403                 MEM_freeN(vg_weights);
1404                 MEM_freeN(vg_users);
1405         }
1406 }
1407
1408 static void vgroup_clean(Object *ob, float eul, int keep_single)
1409 {
1410         bDeformGroup *dg;
1411         MDeformWeight *dw;
1412         MDeformVert *dvert, **dvert_array=NULL;
1413         int i, def_nr, dvert_tot=0;
1414         // Jason
1415         Mesh *me = ob->data;
1416         MVert *mv = me->mvert;
1417         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1418
1419         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1420
1421         /* only the active group */
1422         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1423         if(dg) {
1424                 def_nr= ob->actdef-1;
1425
1426                 for(i = 0; i < dvert_tot; i++) {
1427                         // Jason
1428                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1429                                 continue;
1430                         }
1431                         dvert = dvert_array[i];
1432
1433                         dw= defvert_find_index(dvert, def_nr);
1434
1435                         if(dw) {
1436                                 if(dw->weight <= eul)
1437                                         if(keep_single==FALSE || dvert->totweight > 1)
1438                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
1439                         }
1440                 }
1441         }
1442
1443         if (dvert_array) MEM_freeN(dvert_array);
1444 }
1445
1446 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
1447 {
1448
1449         MDeformWeight *dw;
1450         MDeformVert *dvert, **dvert_array=NULL;
1451         int i, dvert_tot=0;
1452         // Jason
1453         Mesh *me = ob->data;
1454         MVert *mv = me->mvert;
1455         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1456
1457         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1458
1459         if(dvert_array) {
1460                 for(i = 0; i < dvert_tot; i++) {
1461                         int j;
1462                         // Jason
1463                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1464                                 continue;
1465                         }
1466
1467                         dvert = dvert_array[i];
1468                         j= dvert->totweight;
1469
1470                         while(j--) {
1471
1472                                 if(keep_single && dvert->totweight == 1)
1473                                         break;
1474
1475                                 dw= dvert->dw + j;
1476
1477                                 if(dw->weight <= eul)
1478                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
1479
1480                         }
1481                 }
1482         }
1483
1484         if (dvert_array) MEM_freeN(dvert_array);
1485 }
1486
1487
1488 static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
1489                             const char sel, const char sel_mirr,
1490                             const int *flip_map,
1491                             const short mirror_weights, const short flip_vgroups)
1492 {
1493         BLI_assert(sel || sel_mirr);
1494
1495         if(sel_mirr && sel) {
1496                 /* swap */
1497                 if(mirror_weights)
1498                         SWAP(MDeformVert, *dvert, *dvert_mirr);
1499                 if(flip_vgroups) {
1500                         defvert_flip(dvert, flip_map);
1501                         defvert_flip(dvert_mirr, flip_map);
1502                 }
1503         }
1504         else {
1505                 /* dvert should always be the target */
1506                 if(sel_mirr) {
1507                         SWAP(MDeformVert *, dvert, dvert_mirr);
1508                 }
1509
1510                 if(mirror_weights)
1511                         defvert_copy(dvert, dvert_mirr);
1512                 if(flip_vgroups) {
1513                         defvert_flip(dvert, flip_map);
1514                 }
1515         }
1516 }
1517
1518 void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups)
1519 {
1520 #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups)
1521
1522         EditVert *eve, *eve_mirr;
1523         MDeformVert *dvert, *dvert_mirr;
1524         short sel, sel_mirr;
1525         int     *flip_map;
1526
1527         if(mirror_weights==0 && flip_vgroups==0)
1528                 return;
1529
1530         flip_map= defgroup_flip_map(ob, 0);
1531
1532         /* only the active group */
1533         if(ob->type == OB_MESH) {
1534                 Mesh *me= ob->data;
1535                 EditMesh *em = BKE_mesh_get_editmesh(me);
1536
1537
1538                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
1539                         MEM_freeN(flip_map);
1540                         return;
1541                 }
1542
1543                 EM_cache_x_mirror_vert(ob, em);
1544
1545                 /* Go through the list of editverts and assign them */
1546                 for(eve=em->verts.first; eve; eve=eve->next){
1547                         if((eve_mirr=eve->tmp.v)) {
1548                                 sel= eve->f & SELECT;
1549                                 sel_mirr= eve_mirr->f & SELECT;
1550
1551                                 if((sel || sel_mirr) && (eve != eve_mirr)) {
1552                                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1553                                         dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
1554                                         if(dvert && dvert_mirr) {
1555                                                 VGROUP_MIRR_OP;
1556                                         }
1557                                 }
1558
1559                                 eve->tmp.v= eve_mirr->tmp.v= NULL;
1560                         }
1561                 }
1562
1563                 BKE_mesh_end_editmesh(me, em);
1564         }
1565         else if (ob->type == OB_LATTICE) {
1566                 Lattice *lt= ob->data;
1567                 int i1, i2;
1568                 int u, v, w;
1569                 int pntsu_half;
1570                 /* half but found up odd value */
1571
1572                 if(lt->editlatt) lt= lt->editlatt->latt;
1573
1574                 if(lt->pntsu == 1 || lt->dvert == NULL) {
1575                         MEM_freeN(flip_map);
1576                         return;
1577                 }
1578
1579                 /* unlike editmesh we know that by only looping over the first hald of
1580                  * the 'u' indicies it will cover all points except the middle which is
1581                  * ok in this case */
1582                 pntsu_half= lt->pntsu / 2;
1583
1584                 for(w=0; w<lt->pntsw; w++) {
1585                         for(v=0; v<lt->pntsv; v++) {
1586                                 for(u=0; u<pntsu_half; u++) {
1587                                         int u_inv= (lt->pntsu - 1) - u;
1588                                         if(u != u_inv) {
1589                                                 BPoint *bp, *bp_mirr;
1590
1591                                                 i1= LT_INDEX(lt, u, v, w);
1592                                                 i2= LT_INDEX(lt, u_inv, v, w);
1593
1594                                                 bp= &lt->def[i1];
1595                                                 bp_mirr= &lt->def[i2];
1596
1597                                                 sel= bp->f1 & SELECT;
1598                                                 sel_mirr= bp_mirr->f1 & SELECT;
1599
1600                                                 if(sel || sel_mirr) {
1601                                                         dvert= &lt->dvert[i1];
1602                                                         dvert_mirr= &lt->dvert[i2];
1603
1604                                                         VGROUP_MIRR_OP;
1605                                                 }
1606                                         }
1607                                 }
1608                         }
1609                 }
1610         }
1611
1612         MEM_freeN(flip_map);
1613
1614 #undef VGROUP_MIRR_OP
1615 }
1616
1617 static void vgroup_remap_update_users(Object *ob, int *map)
1618 {
1619         ExplodeModifierData *emd;
1620         ModifierData *md;
1621         ParticleSystem *psys;
1622         ClothModifierData *clmd;
1623         ClothSimSettings *clsim;
1624         int a;
1625
1626         /* these cases don't use names to refer to vertex groups, so when
1627          * they get deleted the numbers get out of sync, this corrects that */
1628
1629         if(ob->soft)
1630                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1631
1632         for(md=ob->modifiers.first; md; md=md->next) {
1633                 if(md->type == eModifierType_Explode) {
1634                         emd= (ExplodeModifierData*)md;
1635                         emd->vgroup= map[emd->vgroup];
1636                 }
1637                 else if(md->type == eModifierType_Cloth) {
1638                         clmd= (ClothModifierData*)md;
1639                         clsim= clmd->sim_parms;
1640
1641                         if(clsim) {
1642                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1643                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1644                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1645                         }
1646                 }
1647         }
1648
1649         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1650                 for(a=0; a<PSYS_TOT_VG; a++)
1651                         psys->vgroup[a]= map[psys->vgroup[a]];
1652         }
1653 }
1654
1655
1656 static void vgroup_delete_update_users(Object *ob, int id)
1657 {
1658         int i, tot= BLI_countlist(&ob->defbase) + 1;
1659         int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del");
1660
1661         map[id]= map[0]= 0;
1662         for(i=1; i<id; i++) map[i]=i;
1663         for(i=id+1; i<tot; i++) map[i]=i-1;
1664
1665         vgroup_remap_update_users(ob, map);
1666         MEM_freeN(map);
1667 }
1668
1669
1670 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1671 {
1672         MDeformVert *dvert_array=NULL;
1673         int i, e, dvert_tot=0;
1674         const int dg_index= BLI_findindex(&ob->defbase, dg);
1675
1676         assert(dg_index > -1);
1677         
1678         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1679
1680         if(dvert_array) {
1681                 MDeformVert *dvert;
1682                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1683                         ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */
1684                 }
1685
1686                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1687                         for(e = 0; e < dvert->totweight; e++) {
1688                                 if(dvert->dw[e].def_nr > dg_index) {
1689                                         dvert->dw[e].def_nr--;
1690                                 }
1691                         }
1692                 }
1693         }
1694
1695         vgroup_delete_update_users(ob, dg_index + 1);
1696
1697         /* Remove the group */
1698         BLI_freelinkN(&ob->defbase, dg);
1699
1700         /* Update the active deform index if necessary */
1701         if(ob->actdef > dg_index)
1702                 ob->actdef--;
1703         if(ob->actdef < 1 && ob->defbase.first)
1704                 ob->actdef= 1;
1705
1706 }
1707
1708 /* only in editmode */
1709 /* removes from active defgroup, if allverts==0 only selected vertices */
1710 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1711 {
1712         EditVert *eve;
1713         MDeformVert *dvert;
1714         MDeformWeight *newdw;
1715         bDeformGroup *eg;
1716         int     i;
1717
1718         if(ob->type == OB_MESH) {
1719                 Mesh *me= ob->data;
1720                 EditMesh *em = BKE_mesh_get_editmesh(me);
1721
1722                 for(eve=em->verts.first; eve; eve=eve->next){
1723                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1724                 
1725                         if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){
1726                                 for(i=0; i<dvert->totweight; i++){
1727                                         /* Find group */
1728                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1729                                         if(eg == dg){
1730                                                 dvert->totweight--;
1731                                                 if(dvert->totweight){
1732                                                         newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1733                                                         
1734                                                         if(dvert->dw){
1735                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1736                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1737                                                                 MEM_freeN(dvert->dw);
1738                                                         }
1739                                                         dvert->dw=newdw;
1740                                                 }
1741                                                 else{
1742                                                         MEM_freeN(dvert->dw);
1743                                                         dvert->dw=NULL;
1744                                                         break;
1745                                                 }
1746                                         }
1747                                 }
1748                         }
1749                 }
1750                 BKE_mesh_end_editmesh(me, em);
1751         }
1752         else if(ob->type == OB_LATTICE) {
1753                 Lattice *lt= vgroup_edit_lattice(ob);
1754                 
1755                 if(lt->dvert) {
1756                         BPoint *bp;
1757                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1758                                 
1759                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1760                                 if(allverts || (bp->f1 & SELECT))
1761                                         ED_vgroup_vert_remove(ob, dg, a);
1762                         }
1763                 }
1764         }
1765 }
1766
1767 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1768 {
1769         int i;
1770         const int dg_index= BLI_findindex(&ob->defbase, dg);
1771
1772         assert(dg_index > -1);
1773
1774         /* Make sure that no verts are using this group */
1775         vgroup_active_remove_verts(ob, TRUE, dg);
1776
1777         /* Make sure that any verts with higher indices are adjusted accordingly */
1778         if(ob->type==OB_MESH) {
1779                 Mesh *me= ob->data;
1780                 EditMesh *em = BKE_mesh_get_editmesh(me);
1781                 EditVert *eve;
1782                 MDeformVert *dvert;
1783                 
1784                 for(eve=em->verts.first; eve; eve=eve->next){
1785                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1786
1787                         if(dvert)
1788                                 for(i=0; i<dvert->totweight; i++)
1789                                         if(dvert->dw[i].def_nr > dg_index)
1790                                                 dvert->dw[i].def_nr--;
1791                 }
1792                 BKE_mesh_end_editmesh(me, em);
1793         }
1794         else if(ob->type==OB_LATTICE) {
1795                 Lattice *lt= vgroup_edit_lattice(ob);
1796                 BPoint *bp;
1797                 MDeformVert *dvert= lt->dvert;
1798                 int a, tot;
1799                 
1800                 if(dvert) {
1801                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1802                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1803                                 for(i=0; i<dvert->totweight; i++){
1804                                         if(dvert->dw[i].def_nr > dg_index)
1805                                                 dvert->dw[i].def_nr--;
1806                                 }
1807                         }
1808                 }
1809         }
1810
1811         vgroup_delete_update_users(ob, dg_index + 1);
1812
1813         /* Remove the group */
1814         BLI_freelinkN (&ob->defbase, dg);
1815
1816         /* Update the active deform index if necessary */
1817         if(ob->actdef > dg_index)
1818                 ob->actdef--;
1819         if(ob->actdef < 1 && ob->defbase.first)
1820                 ob->actdef= 1;
1821
1822         /* remove all dverts */
1823         if(ob->defbase.first == NULL) {
1824                 if(ob->type==OB_MESH) {
1825                         Mesh *me= ob->data;
1826                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1827                         me->dvert= NULL;
1828                 }
1829                 else if(ob->type==OB_LATTICE) {
1830                         Lattice *lt= vgroup_edit_lattice(ob);
1831                         if(lt->dvert) {
1832                                 MEM_freeN(lt->dvert);
1833                                 lt->dvert= NULL;
1834                         }
1835                 }
1836         }
1837 }
1838
1839 static int vgroup_object_in_edit_mode(Object *ob)
1840 {
1841         if(ob->type == OB_MESH)
1842                 return (((Mesh*)ob->data)->edit_mesh != NULL);
1843         else if(ob->type == OB_LATTICE)
1844                 return (((Lattice*)ob->data)->editlatt != NULL);
1845         
1846         return 0;
1847 }
1848
1849 static void vgroup_delete(Object *ob)
1850 {
1851         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
1852         if(!dg)
1853                 return;
1854
1855         if(vgroup_object_in_edit_mode(ob))
1856                 vgroup_delete_edit_mode(ob, dg);
1857         else
1858                 vgroup_delete_object_mode(ob, dg);
1859 }
1860
1861 static void vgroup_delete_all(Object *ob)
1862 {
1863         /* Remove all DVerts */
1864         if(ob->type==OB_MESH) {
1865                 Mesh *me= ob->data;
1866                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1867                 me->dvert= NULL;
1868         }
1869         else if(ob->type==OB_LATTICE) {
1870                 Lattice *lt= vgroup_edit_lattice(ob);
1871                 if(lt->dvert) {
1872                         MEM_freeN(lt->dvert);
1873                         lt->dvert= NULL;
1874                 }
1875         }
1876         
1877         /* Remove all DefGroups */
1878         BLI_freelistN(&ob->defbase);
1879         
1880         /* Fix counters/indices */
1881         ob->actdef= 0;
1882 }
1883
1884 /* only in editmode */
1885 static void vgroup_assign_verts(Object *ob, float weight)
1886 {
1887         EditVert *eve;
1888         bDeformGroup *dg, *eg;
1889         MDeformWeight *newdw;
1890         MDeformVert *dvert;
1891         int     i, done;
1892
1893         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1894         if(!dg)
1895                 return;
1896
1897         if(ob->type == OB_MESH) {
1898                 Mesh *me= ob->data;
1899                 EditMesh *em = BKE_mesh_get_editmesh(me);
1900
1901                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1902                         EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT, NULL);
1903
1904                 /* Go through the list of editverts and assign them */
1905                 for(eve=em->verts.first; eve; eve=eve->next){
1906                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1907
1908                         if(dvert && (eve->f & SELECT)){
1909                                 /* See if this vert already has a reference to this group */
1910                                 /*              If so: Change its weight */
1911                                 done=0;
1912                                 for(i=0; i<dvert->totweight; i++){
1913                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1914                                         /* Find the actual group */
1915                                         if(eg==dg){
1916                                                 dvert->dw[i].weight= weight;
1917                                                 done=1;
1918                                                 break;
1919                                         }
1920                                  }
1921                                 /*              If not: Add the group and set its weight */
1922                                 if(!done){
1923                                         newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1924                                         if(dvert->dw){
1925                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1926                                                 MEM_freeN(dvert->dw);
1927                                         }
1928                                         dvert->dw=newdw;
1929
1930                                         dvert->dw[dvert->totweight].weight= weight;
1931                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1932
1933                                         dvert->totweight++;
1934
1935                                 }
1936                         }
1937                 }
1938                 BKE_mesh_end_editmesh(me, em);
1939         }
1940         else if(ob->type == OB_LATTICE) {
1941                 Lattice *lt= vgroup_edit_lattice(ob);
1942                 BPoint *bp;
1943                 int a, tot;
1944                 
1945                 if(lt->dvert==NULL)
1946                         ED_vgroup_data_create(&lt->id);
1947                 
1948                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1949                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1950                         if(bp->f1 & SELECT)
1951                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1952                 }
1953         }
1954 }
1955
1956 /* only in editmode */
1957 /* removes from all defgroup, if allverts==0 only selected vertices */
1958 static void vgroup_remove_verts(Object *ob, int allverts)
1959 {
1960         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1961          * only operates on the active vgroup. So we iterate through all groups, by changing
1962          * active group index
1963          */
1964         bDeformGroup *dg;
1965         for(dg= ob->defbase.first; dg; dg= dg->next) {
1966                 vgroup_active_remove_verts(ob, allverts, dg);
1967         }
1968 }
1969
1970 /********************** vertex group operators *********************/
1971
1972 static int vertex_group_poll(bContext *C)
1973 {
1974         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1975         ID *data= (ob)? ob->data: NULL;
1976         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1977 }
1978
1979 static int vertex_group_poll_edit(bContext *C)
1980 {
1981         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1982         ID *data= (ob)? ob->data: NULL;
1983
1984         if(!(ob && !ob->id.lib && data && !data->lib))
1985                 return 0;
1986
1987         return vgroup_object_in_edit_mode(ob);
1988 }
1989
1990 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
1991 {
1992         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1993
1994         ED_vgroup_add(ob);
1995         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1996         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1997         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1998         
1999         return OPERATOR_FINISHED;
2000 }
2001
2002 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
2003 {
2004         /* identifiers */
2005         ot->name= "Add Vertex Group";
2006         ot->idname= "OBJECT_OT_vertex_group_add";
2007         
2008         /* api callbacks */
2009         ot->poll= vertex_group_poll;
2010         ot->exec= vertex_group_add_exec;
2011
2012         /* flags */
2013         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2014 }
2015
2016 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
2017 {
2018         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2019
2020         if(RNA_boolean_get(op->ptr, "all"))
2021                 vgroup_delete_all(ob);
2022         else
2023                 vgroup_delete(ob);
2024
2025         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2026         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2027         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2028         
2029         return OPERATOR_FINISHED;
2030 }
2031
2032 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
2033 {
2034         /* identifiers */
2035         ot->name= "Remove Vertex Group";
2036         ot->idname= "OBJECT_OT_vertex_group_remove";
2037         
2038         /* api callbacks */
2039         ot->poll= vertex_group_poll;
2040         ot->exec= vertex_group_remove_exec;
2041
2042         /* flags */
2043         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2044
2045         /* properties */
2046         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
2047 }
2048
2049 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
2050 {
2051         ToolSettings *ts= CTX_data_tool_settings(C);
2052         Object *ob= CTX_data_edit_object(C);
2053
2054         if(RNA_boolean_get(op->ptr, "new"))
2055                 ED_vgroup_add(ob);
2056
2057         vgroup_assign_verts(ob, ts->vgroup_weight);
2058         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2059         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2060         
2061         return OPERATOR_FINISHED;
2062 }
2063
2064 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
2065 {
2066         /* identifiers */
2067         ot->name= "Assign Vertex Group";
2068         ot->idname= "OBJECT_OT_vertex_group_assign";
2069         
2070         /* api callbacks */
2071         ot->poll= vertex_group_poll_edit;
2072         ot->exec= vertex_group_assign_exec;
2073
2074         /* flags */
2075         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2076
2077         /* properties */
2078         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
2079 }
2080
2081 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
2082 {
2083         Object *ob= CTX_data_edit_object(C);
2084
2085         if(RNA_boolean_get(op->ptr, "all"))
2086                 vgroup_remove_verts(ob, 0);
2087         else {
2088                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
2089
2090                 if(dg == NULL) {
2091                         return OPERATOR_CANCELLED;
2092                 }
2093
2094                 vgroup_active_remove_verts(ob, FALSE, dg);
2095         }
2096
2097         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2098         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2099
2100         return OPERATOR_FINISHED;
2101 }
2102
2103 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
2104 {
2105         /* identifiers */
2106         ot->name= "Remove from Vertex Group";
2107         ot->idname= "OBJECT_OT_vertex_group_remove_from";
2108
2109         /* api callbacks */
2110         ot->poll= vertex_group_poll_edit;
2111         ot->exec= vertex_group_remove_from_exec;
2112
2113         /* flags */
2114         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2115
2116         /* properties */
2117         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
2118 }
2119
2120 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
2121 {
2122         Object *ob= CTX_data_edit_object(C);
2123
2124         if(!ob || ob->id.lib)
2125                 return OPERATOR_CANCELLED;
2126
2127         vgroup_select_verts(ob, 1);
2128         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2129
2130         return OPERATOR_FINISHED;
2131 }
2132
2133 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
2134 {
2135         /* identifiers */
2136         ot->name= "Select Vertex Group";
2137         ot->idname= "OBJECT_OT_vertex_group_select";
2138
2139         /* api callbacks */
2140         ot->poll= vertex_group_poll_edit;
2141         ot->exec= vertex_group_select_exec;
2142
2143         /* flags */
2144         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2145 }
2146
2147 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
2148 {
2149         Object *ob= CTX_data_edit_object(C);
2150
2151         vgroup_select_verts(ob, 0);
2152         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2153
2154         return OPERATOR_FINISHED;
2155 }
2156
2157 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
2158 {
2159         /* identifiers */
2160         ot->name= "Deselect Vertex Group";
2161         ot->idname= "OBJECT_OT_vertex_group_deselect";
2162
2163         /* api callbacks */
2164         ot->poll= vertex_group_poll_edit;
2165         ot->exec= vertex_group_deselect_exec;
2166
2167         /* flags */
2168         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2169 }
2170
2171 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
2172 {
2173         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2174
2175         vgroup_duplicate(ob);
2176         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2177         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2178         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2179
2180         return OPERATOR_FINISHED;
2181 }
2182
2183 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
2184 {
2185         /* identifiers */
2186         ot->name= "Copy Vertex Group";
2187         ot->idname= "OBJECT_OT_vertex_group_copy";
2188
2189         /* api callbacks */
2190         ot->poll= vertex_group_poll;
2191         ot->exec= vertex_group_copy_exec;
2192
2193         /* flags */
2194         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2195 }
2196
2197 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
2198 {
2199         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2200         
2201         float offset= RNA_float_get(op->ptr,"offset");
2202         float gain= RNA_float_get(op->ptr,"gain");
2203         
2204         vgroup_levels(ob, offset, gain);
2205         
2206         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2207         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2208         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2209         
2210         return OPERATOR_FINISHED;
2211 }
2212
2213 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
2214 {
2215         /* identifiers */
2216         ot->name= "Vertex Group Levels";
2217         ot->idname= "OBJECT_OT_vertex_group_levels";
2218         
2219         /* api callbacks */
2220         ot->poll= vertex_group_poll;
2221         ot->exec= vertex_group_levels_exec;
2222         
2223         /* flags */
2224         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2225         
2226         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
2227         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
2228 }
2229
2230 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
2231 {
2232         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2233
2234         vgroup_normalize(ob);
2235
2236         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2237         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2238         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2239
2240         return OPERATOR_FINISHED;
2241 }
2242
2243 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
2244 {
2245         /* identifiers */
2246         ot->name= "Normalize Vertex Group";
2247         ot->idname= "OBJECT_OT_vertex_group_normalize";
2248
2249         /* api callbacks */
2250         ot->poll= vertex_group_poll;
2251         ot->exec= vertex_group_normalize_exec;
2252
2253         /* flags */
2254         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2255 }
2256
2257 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
2258 {
2259         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2260         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
2261
2262         vgroup_normalize_all(ob, lock_active);
2263
2264         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2265         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2266         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2267
2268         return OPERATOR_FINISHED;
2269 }
2270
2271 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
2272 {
2273         /* identifiers */
2274         ot->name= "Normalize All Vertex Groups";
2275         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
2276
2277         /* api callbacks */
2278         ot->poll= vertex_group_poll;
2279         ot->exec= vertex_group_normalize_all_exec;
2280
2281         /* flags */
2282         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2283
2284         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
2285 }
2286 /* Jason */
2287 static int vertex_group_fix_exec(bContext *C, wmOperator *op)
2288 {
2289         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2290         Scene *scene= CTX_data_scene(C);
2291         
2292         float strength= RNA_float_get(op->ptr,"strength");
2293         float cp= RNA_float_get(op->ptr,"cp");
2294         
2295         vgroup_fix(scene, ob, strength, cp);
2296         
2297         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2298         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2299         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2300         
2301         return OPERATOR_FINISHED;
2302 }
2303
2304 void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
2305 {
2306         /* identifiers */
2307         ot->name= "Fix Vertex Group Deform";
2308         ot->idname= "OBJECT_OT_vertex_group_fix";
2309         
2310         /* api callbacks */
2311         ot->poll= vertex_group_poll;
2312         ot->exec= vertex_group_fix_exec;
2313         
2314         /* flags */
2315         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2316         
2317         RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength", "The distance to be moved can be changed by this.", -2.0f, 2.0f);
2318         RNA_def_float(ot->srna, "cp", 1.0f, 0.05f, FLT_MAX, "Change Sensitivity", "Changes the amount weights are altered with each iteration: lower values are slower.", 0.05f, 1.f);
2319 }
2320 /* Jason was here */
2321 static int vertex_group_invert_locks_exec(bContext *C, wmOperator *op)
2322 {
2323         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2324
2325         vgroup_invert_locks(ob);
2326
2327         return OPERATOR_FINISHED;
2328 }
2329 /* Jason was here */
2330 void OBJECT_OT_vertex_group_invert_locks(wmOperatorType *ot)
2331 {
2332         /* identifiers */
2333         ot->name= "Invert All Vertex Group Locks";
2334         ot->idname= "OBJECT_OT_vertex_group_invert_locks";
2335
2336         /* api callbacks */
2337         ot->poll= vertex_group_poll;
2338         ot->exec= vertex_group_invert_locks_exec;
2339
2340         /* flags */
2341         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2342 }
2343 /* Jason was here */
2344 static int vertex_group_lock_all_exec(bContext *C, wmOperator *op)
2345 {
2346         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2347
2348         vgroup_lock_all(ob);
2349
2350         return OPERATOR_FINISHED;
2351 }
2352 /* Jason was here */
2353 void OBJECT_OT_vertex_group_lock_all(wmOperatorType *ot)
2354 {
2355         /* identifiers */
2356         ot->name= "Turn on all Vertex Group Locks";
2357         ot->idname= "OBJECT_OT_vertex_group_lock_all";
2358
2359         /* api callbacks */
2360         ot->poll= vertex_group_poll;
2361         ot->exec= vertex_group_lock_all_exec;
2362
2363         /* flags */
2364         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2365 }
2366 /* Jason was here */
2367 static int vertex_group_unlock_all_exec(bContext *C, wmOperator *op)
2368 {
2369         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2370
2371         vgroup_unlock_all(ob);
2372
2373         return OPERATOR_FINISHED;
2374 }
2375 /* Jason was here */
2376 void OBJECT_OT_vertex_group_unlock_all(wmOperatorType *ot)
2377 {
2378         /* identifiers */
2379         ot->name= "Turn off all Vertex Group Locks";
2380         ot->idname= "OBJECT_OT_vertex_group_unlock_all";
2381
2382         /* api callbacks */
2383         ot->poll= vertex_group_poll;
2384         ot->exec= vertex_group_unlock_all_exec;
2385
2386         /* flags */
2387         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2388 }
2389 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
2390 {
2391         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2392         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
2393         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
2394
2395         vgroup_invert(ob, auto_assign, auto_remove);
2396         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2397         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2398         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2399
2400         return OPERATOR_FINISHED;
2401 }
2402
2403 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
2404 {
2405         /* identifiers */
2406         ot->name= "Invert Vertex Group";
2407         ot->idname= "OBJECT_OT_vertex_group_invert";
2408
2409         /* api callbacks */
2410         ot->poll= vertex_group_poll;
2411         ot->exec= vertex_group_invert_exec;
2412
2413         /* flags */
2414         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2415
2416         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
2417         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
2418 }
2419
2420
2421 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op))
2422 {
2423         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2424
2425         vgroup_blend(ob);
2426
2427         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2428         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2429         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2430
2431         return OPERATOR_FINISHED;
2432 }
2433
2434 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
2435 {
2436         /* identifiers */
2437         ot->name= "Blend Vertex Group";
2438         ot->idname= "OBJECT_OT_vertex_group_blend";
2439         ot->description= "";
2440
2441         /* api callbacks */
2442         ot->poll= vertex_group_poll;
2443         ot->exec= vertex_group_blend_exec;
2444
2445         /* flags */
2446         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2447 }
2448
2449
2450 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
2451 {
2452         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2453
2454         float limit= RNA_float_get(op->ptr,"limit");
2455         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
2456         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
2457
2458         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
2459         else                    vgroup_clean(ob, limit, keep_single);
2460
2461         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2462         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2463         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2464
2465         return OPERATOR_FINISHED;
2466 }
2467
2468 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
2469 {
2470         /* identifiers */
2471         ot->name= "Clean Vertex Group";
2472         ot->idname= "OBJECT_OT_vertex_group_clean";
2473         ot->description= "Remove Vertex Group assignments which aren't required";
2474
2475         /* api callbacks */
2476         ot->poll= vertex_group_poll;
2477         ot->exec= vertex_group_clean_exec;
2478
2479         /* flags */
2480         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2481
2482         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
2483         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
2484         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
2485 }
2486
2487
2488 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
2489 {
2490         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2491
2492         ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
2493
2494         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2495         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2496         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2497
2498         return OPERATOR_FINISHED;
2499 }
2500
2501 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
2502 {
2503         /* identifiers */
2504         ot->name= "Mirror Vertex Group";
2505         ot->idname= "OBJECT_OT_vertex_group_mirror";
2506         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";
2507
2508         /* api callbacks */
2509         ot->poll= vertex_group_poll_edit;
2510         ot->exec= vertex_group_mirror_exec;
2511
2512         /* flags */
2513         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2514
2515         /* properties */
2516         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
2517         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names.");
2518
2519 }
2520
2521 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
2522 {
2523         Scene *scene= CTX_data_scene(C);
2524         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2525         Base *base;
2526         int retval= OPERATOR_CANCELLED;
2527
2528         for(base=scene->base.first; base; base= base->next) {
2529                 if(base->object->type==ob->type) {
2530                         if(base->object!=ob && base->object->data==ob->data) {
2531                                 BLI_freelistN(&base->object->defbase);
2532                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
2533                                 base->object->actdef= ob->actdef;
2534
2535                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
2536                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
2537                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
2538
2539                                 retval = OPERATOR_FINISHED;
2540                         }
2541                 }
2542         }
2543
2544         return retval;
2545 }
2546
2547 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
2548 {
2549         /* identifiers */
2550         ot->name= "Copy Vertex Groups to Linked";
2551         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
2552         ot->description= "Copy Vertex Groups to all users of the same Geometry data";
2553
2554         /* api callbacks */
2555         ot->poll= vertex_group_poll;
2556         ot->exec= vertex_group_copy_to_linked_exec;
2557
2558         /* flags */
2559         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2560 }
2561
2562 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
2563 {
2564         Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2565         int change= 0;
2566         int fail= 0;
2567
2568         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
2569         {
2570                 if(obact != ob) {
2571                         if(ED_vgroup_copy_array(ob, obact)) change++;
2572                         else                                fail++;
2573                 }
2574         }
2575         CTX_DATA_END;
2576
2577         if((change == 0 && fail == 0) || fail) {
2578                 BKE_reportf(op->reports, RPT_ERROR, "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indicies", change, fail);
2579         }
2580
2581         return OPERATOR_FINISHED;
2582 }
2583
2584
2585 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
2586 {
2587         /* identifiers */
2588         ot->name= "Copy Vertex Group to Selected";
2589         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected";
2590         ot->description= "Copy Vertex Groups to other selected objects with matching indices";
2591
2592         /* api callbacks */
2593         ot->poll= vertex_group_poll;
2594         ot->exec= vertex_group_copy_to_selected_exec;
2595
2596         /* flags */
2597         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2598 }
2599
2600 static EnumPropertyItem vgroup_items[]= {
2601         {0, NULL, 0, NULL, NULL}};
2602
2603 static int set_active_group_exec(bContext *C, wmOperator *op)
2604 {
2605         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2606         int nr= RNA_enum_get(op->ptr, "group");
2607
2608         ob->actdef= nr+1;
2609
2610         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2611         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2612
2613         return OPERATOR_FINISHED;
2614 }
2615
2616 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
2617 {       
2618         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2619         EnumPropertyItem tmp = {0, "", 0, "", ""};
2620         EnumPropertyItem *item= NULL;
2621         bDeformGroup *def;
2622         int a, totitem= 0;
2623         
2624         if(!ob)
2625                 return vgroup_items;
2626         
2627         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
2628                 tmp.value= a;
2629                 tmp.icon= ICON_GROUP_VERTEX;
2630                 tmp.identifier= def->name;
2631                 tmp.name= def->name;
2632                 RNA_enum_item_add(&item, &totitem, &tmp);
2633         }
2634
2635         RNA_enum_item_end(&item, &totitem);
2636         *free= 1;
2637
2638         return item;
2639 }
2640
2641 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2642 {
2643         PropertyRNA *prop;
2644
2645         /* identifiers */
2646         ot->name= "Set Active Vertex Group";
2647         ot->idname= "OBJECT_OT_vertex_group_set_active";
2648         ot->description= "Set the active vertex group";
2649
2650         /* api callbacks */
2651         ot->poll= vertex_group_poll;
2652         ot->exec= set_active_group_exec;
2653         ot->invoke= WM_menu_invoke;
2654
2655         /* flags */
2656         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2657
2658         /* properties */
2659         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
2660         RNA_def_enum_funcs(prop, vgroup_itemf);
2661         ot->prop= prop;
2662 }
2663
2664 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling
2665   with the order of vgroups then call vgroup_do_remap after*/
2666 static char *vgroup_init_remap(Object *ob)
2667 {
2668         bDeformGroup *def;
2669         int def_tot = BLI_countlist(&ob->defbase);
2670         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups");
2671         char *name;
2672
2673         name= name_array;
2674         for(def = ob->defbase.first; def; def=def->next) {
2675                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
2676                 name += MAX_VGROUP_NAME;
2677         }
2678
2679         return name_array;
2680 }
2681
2682 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
2683 {
2684         MDeformVert *dvert= NULL;
2685         bDeformGroup *def;
2686         int def_tot = BLI_countlist(&ob->defbase);
2687         int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/
2688         int *sort_map= sort_map_update + 1;
2689         char *name;
2690         int i;
2691
2692         name= name_array;
2693         for(def= ob->defbase.first, i=0; def; def=def->next, i++){
2694                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
2695                 name += MAX_VGROUP_NAME;
2696         }
2697
2698         if(ob->mode == OB_MODE_EDIT) {
2699                 if(ob->type==OB_MESH) {
2700                         EditMesh *em = BKE_mesh_get_editmesh(ob->data);
2701                         EditVert *eve;
2702
2703                         for(eve=em->verts.first; eve; eve=eve->next){
2704                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
2705                                 if(dvert && dvert->totweight){
2706                                         defvert_remap(dvert, sort_map);
2707                                 }
2708                         }
2709                 }
2710                 else {
2711                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet.");
2712                         MEM_freeN(sort_map_update);
2713                         return OPERATOR_CANCELLED;
2714                 }
2715         }
2716         else {
2717                 int dvert_tot=0;
2718
2719                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
2720
2721                 /*create as necassary*/
2722                 while(dvert && dvert_tot--) {
2723                         if(dvert->totweight)
2724                                 defvert_remap(dvert, sort_map);
2725                         dvert++;
2726                 }
2727         }
2728
2729         /* update users */
2730         for(i=0; i<def_tot; i++)
2731                 sort_map[i]++;
2732
2733         sort_map_update[0]= 0;
2734         vgroup_remap_update_users(ob, sort_map_update);
2735
2736         ob->actdef= sort_map_update[ob->actdef];
2737         
2738         MEM_freeN(sort_map_update);
2739
2740         return OPERATOR_FINISHED;
2741 }
2742
2743 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
2744 {
2745         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
2746         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
2747
2748         return BLI_natstrcmp(def_a->name, def_b->name);
2749 }
2750
2751 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
2752 {
2753         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2754         char *name_array;
2755         int ret;
2756
2757         /*init remapping*/
2758         name_array = vgroup_init_remap(ob);
2759
2760         /*sort vgroup names*/
2761         BLI_sortlist(&ob->defbase, vgroup_sort);
2762
2763         /*remap vgroup data to map to correct names*/
2764         ret = vgroup_do_remap(ob, name_array, op);
2765
2766         if (ret != OPERATOR_CANCELLED) {
2767                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2768                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2769         }
2770
2771         if (name_array) MEM_freeN(name_array);
2772
2773         return ret;
2774 }
2775
2776 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
2777 {
2778         ot->name= "Sort Vertex Groups";
2779         ot->idname= "OBJECT_OT_vertex_group_sort";
2780         ot->description= "Sorts vertex groups alphabetically";
2781
2782         /* api callbacks */
2783         ot->poll= vertex_group_poll;
2784         ot->exec= vertex_group_sort_exec;
2785
2786         /* flags */
2787         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2788 }
2789
2790 static int vgroup_move_exec(bContext *C, wmOperator *op)
2791 {
2792         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2793         bDeformGroup *def;
2794         char *name_array;
2795         int dir= RNA_enum_get(op->ptr, "direction"), ret;
2796
2797         def = BLI_findlink(&ob->defbase, ob->actdef - 1);
2798         if (!def) {
2799                 return OPERATOR_CANCELLED;
2800         }
2801
2802         name_array = vgroup_init_remap(ob);
2803
2804         if (dir == 1) { /*up*/
2805                 void *prev = def->prev;
2806
2807                 BLI_remlink(&ob->defbase, def);
2808                 BLI_insertlinkbefore(&ob->defbase, prev, def);
2809         } else { /*down*/
2810                 void *next = def->next;
2811
2812                 BLI_remlink(&ob->defbase, def);
2813                 BLI_insertlinkafter(&ob->defbase, next, def);
2814         }
2815
2816         ret = vgroup_do_remap(ob, name_array, op);
2817
2818         if (name_array) MEM_freeN(name_array);
2819
2820         if (ret != OPERATOR_CANCELLED) {
2821                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2822                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2823         }
2824
2825         return ret;
2826 }
2827
2828 void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
2829 {
2830         static EnumPropertyItem vgroup_slot_move[] = {
2831                 {1, "UP", 0, "Up", ""},
2832                 {-1, "DOWN", 0, "Down", ""},
2833                 {0, NULL, 0, NULL, NULL}
2834         };
2835
2836         /* identifiers */
2837         ot->name= "Move Vertex Group";
2838         ot->idname= "OBJECT_OT_vertex_group_move";
2839
2840         /* api callbacks */
2841         ot->poll= vertex_group_poll;
2842         ot->exec= vgroup_move_exec;
2843
2844         /* flags */
2845         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2846
2847         RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
2848 }