Merged 39182-39257
[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, float *dists, 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 and horizontal refer to the plane's y and xz respectively)
884         // vertical distance
885         dists[index] = norm[0]*end[0] + norm[1]*end[1] + norm[2]*end[2] + d;
886         // vertical change
887         changes[index][0] = dists[index] - distToStart;
888         //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]);
889         // horizontal change
890         changes[index][1] = distance(projA, projB, 3);
891         
892         MEM_freeN(projA);
893         MEM_freeN(projB);
894 }
895 // Jason
896 static int dm_deform_clear(DerivedMesh *dm, Object *ob) {
897         dm->needsFree = 1;
898         dm->release(dm);
899         ob->derivedDeform=NULL;
900         // dm = NULL;
901         return NULL;
902 }
903 // Jason
904 static DerivedMesh* dm_deform_recalc(Scene *scene, Object *ob) {
905         return mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
906 }
907 // Jason
908 static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float *norm, float *coord, float d, float distToBe, float strength, float cp) {
909         DerivedMesh *dm;
910         MDeformWeight *dw;
911         MVert m;
912         MDeformVert *dvert = me->dvert+index;
913         int totweight = dvert->totweight;
914         float oldw = 0;
915         float *oldPos = MEM_callocN(sizeof(float)*3, "oldPosition");
916         float vc, hc, dist;
917         int i, k;
918         float **changes = MEM_mallocN(sizeof(float *)*totweight, "vertHorzChange");
919         float *dists = MEM_mallocN(sizeof(float)*totweight, "distance");
920         int *upDown = MEM_callocN(sizeof(int)*totweight, "upDownTracker");// track if up or down moved it closer for each bone
921         int *dwIndices = MEM_callocN(sizeof(int)*totweight, "dwIndexTracker");
922         float distToStart;
923         int bestIndex = 0;
924         char wasChange;
925         char wasUp;
926         int lastIndex = -1;
927         float originalDistToBe = distToBe;
928         for(i = 0; i < totweight; i++) {
929                 changes[i] = MEM_callocN(sizeof(float)*2, "vertHorzChange_"+i);
930         }
931         do {
932                 wasChange = FALSE;
933                 dm = dm_deform_recalc(scene, ob);
934                 dm->getVert(dm, index, &m);
935                 oldPos[0] = m.co[0];
936                 oldPos[1] = m.co[1];
937                 oldPos[2] = m.co[2];
938                 distToStart = norm[0]*oldPos[0] + norm[1]*oldPos[1] + norm[2]*oldPos[2] + d;
939                 //printf("dist %f \n",distToStart);
940                 //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]);
941                 if(distToBe == originalDistToBe) {
942                         distToBe += distToStart - distToStart*strength;
943                 }
944                 for(i = 0; i < totweight; i++) {
945                         dwIndices[i] = i;
946                         dw = (dvert->dw+i);
947                         vc = hc = 0;
948                         if(!dw->weight) {
949                                 changes[i][0] = 0;
950                                 changes[i][1] = 0;
951                                 dists[i] = distToStart;
952                                 continue;
953                         }
954                         for(k = 0; k < 2; k++) {
955                                 if(dm) {
956                                         dm = dm_deform_clear(dm, ob);
957                                 }
958                                 oldw = dw->weight;
959                                 if(k) {
960                                         dw->weight *= 1+cp;
961                                 } else {
962                                         dw->weight /= 1+cp;
963                                 }
964                                 if(dw->weight == oldw) {
965                                         changes[i][0] = 0;
966                                         changes[i][1] = 0;
967                                         dists[i] = distToStart;
968                                         break;
969                                 }
970                                 if(dw->weight > 1) {
971                                         dw->weight = 1;
972                                 }
973                                 dm = dm_deform_recalc(scene, ob);
974                                 dm->getVert(dm, index, &m);
975                                 getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
976                                 dw->weight = oldw;
977                                 if(!k) {
978                                         vc = changes[i][0];
979                                         hc = changes[i][1];
980                                         dist = dists[i];
981                                 } else {
982                                         if(fabs(dist - distToBe) < fabs(dists[i] - distToBe)) {
983                                                 upDown[i] = 0;
984                                                 changes[i][0] = vc;
985                                                 changes[i][1] = hc;
986                                                 dists[i] = dist;
987                                         } else {
988                                                 upDown[i] = 1;
989                                         }
990                                         if(fabs(dists[i] - distToBe) > fabs(distToStart - distToBe)) {
991                                                 changes[i][0] = 0;
992                                                 changes[i][1] = 0;
993                                                 dists[i] = distToStart;
994                                         }
995                                 }
996                         }
997                         //printf("final vc: %f\n", changes[i][0]);
998                 }
999                 // sort the changes by the vertical change
1000                 for(k = 0; k < totweight; k++) {
1001                         float tf;
1002                         int ti;
1003                         bestIndex = k;
1004                         for(i = k+1; i < totweight; i++) {
1005                                 dist = dists[i];
1006
1007                                 if(fabs(dist) > fabs(dists[i])) {
1008                                         bestIndex = i;
1009                                 }
1010                         }
1011                         // switch with k
1012                         if(bestIndex != k) {
1013                                 ti = upDown[k];
1014                                 upDown[k] = upDown[bestIndex];
1015                                 upDown[bestIndex] = ti;
1016
1017                                 ti = dwIndices[k];
1018                                 dwIndices[k] = dwIndices[bestIndex];
1019                                 dwIndices[bestIndex] = ti;
1020
1021                                 tf = changes[k][0];
1022                                 changes[k][0] = changes[bestIndex][0];
1023                                 changes[bestIndex][0] = tf;
1024
1025                                 tf = changes[k][1];
1026                                 changes[k][1] = changes[bestIndex][1];
1027                                 changes[bestIndex][1] = tf;
1028
1029                                 tf = dists[k];
1030                                 dists[k] = dists[bestIndex];
1031                                 dists[bestIndex] = tf;
1032                         }
1033                 }
1034                 bestIndex = -1;
1035                 // find the best change with an acceptable horizontal change
1036                 for(i = 0; i < totweight; i++) {
1037                         if(fabs(changes[i][0]) > fabs(changes[i][1]*2.0f)) {
1038                                 bestIndex = i;
1039                                 break;
1040                         }
1041                 }
1042                 if(bestIndex != -1) {
1043                         //printf("changing %d\n", bestIndex);
1044                         wasChange = TRUE;
1045                         if(lastIndex != -1) {
1046                                 if(wasUp != upDown[bestIndex]) {
1047                                         wasChange = FALSE;
1048                                 }
1049                         }
1050                         lastIndex = bestIndex;
1051                         wasUp = upDown[bestIndex];
1052                         dw = (dvert->dw+dwIndices[bestIndex]);
1053                         oldw = dw->weight;
1054                         if(upDown[bestIndex]) {
1055                                 dw->weight *= 1+cp;
1056                         } else {
1057                                 dw->weight /= 1+cp;
1058                         }
1059                         if(dw->weight > 1) {
1060                                 dw->weight = 1;
1061                         }
1062                         if(oldw == dw->weight) {
1063                                 wasChange = FALSE;
1064                         }
1065                         if(dm) {
1066                                 dm = dm_deform_clear(dm, ob);
1067                         }
1068                 }
1069                 //printf("best vc=%f hc=%f \n", changes[bestIndex][0], changes[bestIndex][1]);
1070         }while(wasChange && (distToStart-distToBe)/fabs(distToStart-distToBe) == (dists[bestIndex]-distToBe)/fabs(dists[bestIndex]-distToBe));
1071         MEM_freeN(upDown);
1072         for(i = 0; i < totweight; i++) {
1073                 MEM_freeN(changes[i]);
1074         }
1075         MEM_freeN(changes);
1076         MEM_freeN(dists);
1077         MEM_freeN(dwIndices);
1078         MEM_freeN(oldPos);
1079 }
1080 // Jason
1081 static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, float cp)
1082 {
1083         int i;
1084
1085         Mesh *me = ob->data;
1086         MVert *mv = me->mvert;
1087         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1088         int *verts = NULL;
1089         int *pcount = MEM_callocN(sizeof(int), "intPointer");
1090         for(i = 0; i < me->totvert && mv; i++, mv++) {
1091                 // Jason
1092                 if(selectedVerts && (mv->flag & SELECT)) {
1093                         
1094                         int count;
1095                         if((verts = getSurroundingVerts(me, i, pcount))) {
1096                                 MVert m;
1097                                 MVert **p = MEM_callocN(sizeof(MVert*)*(count = pcount[0]), "deformedPoints");
1098                                 int k;
1099
1100                                 DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
1101                                 for(k = 0; k < count; k++) {
1102                                         dm->getVert(dm, verts[k], &m);
1103                                         p[k] = &m;
1104                                         //printf("deformed coords %f %f %f\n", p[k]->co[0], p[k]->co[1], p[k]->co[2]);
1105                                 }
1106                                 
1107                                 if(count >= 3) {
1108                                         float d, dist, mag;
1109                                         float *coord = MEM_callocN(sizeof(float)*3, "deformedCoord");
1110                                         float *norm = MEM_callocN(sizeof(float)*3, "planeNorm");
1111                                         getSingleCoordinate(p, count, coord);
1112                                         dm->getVert(dm, i, &m);
1113                                         norm[0] = m.co[0]-coord[0];
1114                                         norm[1] = m.co[1]-coord[1];
1115                                         norm[2] = m.co[2]-coord[2];
1116                                         mag = sqrt(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
1117                                         for(k = 0; k < 3; k++) {
1118                                                 norm[k]/=mag;
1119                                         }
1120                                         d = -norm[0]*coord[0] -norm[1]*coord[1] -norm[2]*coord[2];
1121                                         dist = (norm[0]*m.co[0] + norm[1]*m.co[1] + norm[2]*m.co[2] + d);
1122                                         //printf("status plane: (%f %f %f) %f dist: %f\n", norm[0], norm[1], norm[2], d, dist);
1123                                         moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
1124                                         MEM_freeN(coord);
1125                                         MEM_freeN(norm);
1126                                 }
1127
1128                                 MEM_freeN(verts);
1129                                 MEM_freeN(p);
1130                         }
1131                 }
1132         }
1133         MEM_freeN(pcount);
1134 }
1135
1136 static void vgroup_levels(Object *ob, float offset, float gain)
1137 {
1138         bDeformGroup *dg;
1139         MDeformWeight *dw;
1140         MDeformVert *dvert, **dvert_array=NULL;
1141         int i, def_nr, dvert_tot=0;
1142         // Jason
1143         Mesh *me = ob->data;
1144         MVert *mv = me->mvert;
1145         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1146
1147         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1148         
1149         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1150         
1151         if(dg) {
1152                 def_nr= ob->actdef-1;
1153                 
1154                 for(i = 0; i < dvert_tot; i++) {
1155                         // Jason
1156                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1157                                 continue;
1158                         }
1159
1160                         dvert = dvert_array[i];
1161                         dw = defvert_find_index(dvert, def_nr);
1162                         if(dw) {
1163                                 dw->weight = gain * (dw->weight + offset);
1164                                 
1165                                 CLAMP(dw->weight, 0.0f, 1.0f);
1166                         }
1167                 }
1168         }
1169
1170         if (dvert_array) MEM_freeN(dvert_array);
1171 }
1172
1173 /* TODO - select between groups */
1174 static void vgroup_normalize_all(Object *ob, int lock_active)
1175 {
1176         MDeformWeight *dw, *dw_act;
1177         MDeformVert *dvert, **dvert_array=NULL;
1178         int i, dvert_tot=0;
1179         float tot_weight;
1180
1181         // Jason
1182         Mesh *me = ob->data;
1183         MVert *mv = me->mvert;
1184         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1185
1186         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1187
1188         if(dvert_array) {
1189                 if(lock_active) {
1190                         int def_nr= ob->actdef-1;
1191
1192                         for(i = 0; i < dvert_tot; i++) {
1193                                 float lock_iweight= 1.0f;
1194                                 int j;
1195                                 // Jason
1196                                 if(selectedVerts && !((mv+i)->flag & SELECT)) {
1197                                         continue;
1198                                 }
1199
1200                                 tot_weight= 0.0f;
1201                                 dw_act= NULL;
1202                                 dvert = dvert_array[i];
1203
1204                                 j= dvert->totweight;
1205                                 while(j--) {
1206                                         dw= dvert->dw + j;
1207
1208                                         if(dw->def_nr==def_nr) {
1209                                                 dw_act= dw;
1210                                                 lock_iweight = (1.0f - dw_act->weight);
1211                                         }
1212                                         else {
1213                                                 tot_weight += dw->weight;
1214                                         }
1215                                 }
1216
1217                                 if(tot_weight) {
1218                                         j= dvert->totweight;
1219                                         while(j--) {
1220                                                 dw= dvert->dw + j;
1221                                                 if(dw == dw_act) {
1222                                                         if (dvert->totweight==1) {
1223                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
1224                                                         }
1225                                                 } else {
1226                                                         if(dw->weight > 0.0f)
1227                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
1228                                                 }
1229
1230                                                 /* incase of division errors with very low weights */
1231                                                 CLAMP(dw->weight, 0.0f, 1.0f);
1232                                         }
1233                                 }
1234                         }
1235                 }
1236                 else {
1237                         for(i = 0; i < dvert_tot; i++) {
1238                                 int j;
1239                                 // Jason
1240                                 if(selectedVerts && !((mv+i)->flag & SELECT)) {
1241                                         continue;
1242                                 }
1243
1244                                 tot_weight= 0.0f;
1245                                 dvert = dvert_array[i];
1246
1247                                 j= dvert->totweight;
1248                                 while(j--) {
1249                                         dw= dvert->dw + j;
1250                                         tot_weight += dw->weight;
1251                                 }
1252
1253                                 if(tot_weight) {
1254                                         j= dvert->totweight;
1255                                         while(j--) {
1256                                                 dw= dvert->dw + j;
1257                                                 dw->weight /= tot_weight;
1258
1259                                                 /* incase of division errors with very low weights */
1260                                                 CLAMP(dw->weight, 0.0f, 1.0f);
1261                                         }
1262                                 }
1263                         }
1264                 }
1265         }
1266
1267         if (dvert_array) MEM_freeN(dvert_array);
1268 }
1269 /* Jason was here */
1270 static void vgroup_invert_locks(Object *ob)
1271 {
1272         bDeformGroup *dg = ob->defbase.first;
1273         while(dg) {
1274                 dg->flag = !dg->flag;
1275                 dg = dg->next;
1276         }
1277 }
1278 /* Jason was here */
1279 static void vgroup_lock_all(Object *ob)
1280 {
1281         bDeformGroup *dg = ob->defbase.first;
1282         while(dg) {
1283                 dg->flag = TRUE;
1284                 dg = dg->next;
1285         }
1286 }
1287 /* Jason was here */
1288 static void vgroup_unlock_all(Object *ob)
1289 {
1290         bDeformGroup *dg = ob->defbase.first;
1291         while(dg) {
1292                 dg->flag = FALSE;
1293                 dg = dg->next;
1294         }
1295 }
1296
1297 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
1298 {
1299         bDeformGroup *dg;
1300         MDeformWeight *dw;
1301         MDeformVert *dvert, **dvert_array=NULL;
1302         int i, def_nr, dvert_tot=0;
1303         // Jason
1304         Mesh *me = ob->data;
1305         MVert *mv = me->mvert;
1306         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1307
1308         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1309
1310         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1311
1312         if(dg) {
1313                 def_nr= ob->actdef-1;
1314
1315
1316                 for(i = 0; i < dvert_tot; i++) {
1317                         // Jason
1318                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1319                                 continue;
1320                         }
1321                         dvert = dvert_array[i];
1322
1323                         if(auto_assign) {
1324                                 dw= defvert_verify_index(dvert, def_nr);
1325                         } else {
1326                                 dw= defvert_find_index(dvert, def_nr);
1327                         }
1328
1329                         if(dw) {
1330                                 dw->weight = 1.0f-dw->weight;
1331
1332                                 if(auto_remove && dw->weight <= 0.0f) {
1333                                         /* could have a faster function for this */
1334                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
1335                                 }
1336                         }
1337                 }
1338         }
1339
1340         if (dvert_array) MEM_freeN(dvert_array);
1341 }
1342
1343 static void vgroup_blend(Object *ob)
1344 {
1345         bDeformGroup *dg;
1346         MDeformWeight *dw;
1347         MDeformVert *dvert_array=NULL, *dvert;
1348         int i, def_nr, dvert_tot=0;
1349
1350         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
1351         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1352
1353         if(em==NULL)
1354                 return;
1355
1356         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1357
1358         if(dg) {
1359                 int sel1, sel2;
1360                 int i1, i2;
1361
1362                 EditEdge *eed;
1363                 EditVert *eve;
1364                 float *vg_weights;
1365                 float *vg_users;
1366
1367                 def_nr= ob->actdef-1;
1368
1369                 i= 0;
1370                 for(eve= em->verts.first; eve; eve= eve->next)
1371                         eve->tmp.l= i++;
1372
1373                 dvert_tot= i;
1374
1375                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
1376                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
1377
1378                 for(eed= em->edges.first; eed; eed= eed->next) {
1379                         sel1= eed->v1->f & SELECT;
1380                         sel2= eed->v2->f & SELECT;
1381
1382                         if(sel1 != sel2) {
1383                                 /* i1 is always the selected one */
1384                                 if(sel1==TRUE && sel2==FALSE) {
1385                                         i1= eed->v1->tmp.l;
1386                                         i2= eed->v2->tmp.l;
1387                                         eve= eed->v2;
1388                                 }
1389                                 else {
1390                                         i2= eed->v1->tmp.l;
1391                                         i1= eed->v2->tmp.l;
1392                                         eve= eed->v1;
1393                                 }
1394
1395                                 vg_users[i1]++;
1396
1397                                 /* TODO, we may want object mode blending */
1398                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1399                                 else    dvert= dvert_array+i2;
1400
1401                                 dw= defvert_find_index(dvert, def_nr);
1402
1403                                 if(dw) {
1404                                         vg_weights[i1] += dw->weight;
1405                                 }
1406                         }
1407                 }
1408
1409                 i= 0;
1410                 for(eve= em->verts.first; eve; eve= eve->next) {
1411                         if(eve->f & SELECT && vg_users[i] > 0) {
1412                                 /* TODO, we may want object mode blending */
1413                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1414                                 else    dvert= dvert_array+i;
1415
1416                                 dw= defvert_verify_index(dvert, def_nr);
1417                                 dw->weight= vg_weights[i] / (float)vg_users[i];
1418                         }
1419
1420                         i++;
1421                 }
1422                 MEM_freeN(vg_weights);
1423                 MEM_freeN(vg_users);
1424         }
1425 }
1426
1427 static void vgroup_clean(Object *ob, float eul, int keep_single)
1428 {
1429         bDeformGroup *dg;
1430         MDeformWeight *dw;
1431         MDeformVert *dvert, **dvert_array=NULL;
1432         int i, def_nr, dvert_tot=0;
1433         // Jason
1434         Mesh *me = ob->data;
1435         MVert *mv = me->mvert;
1436         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1437
1438         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1439
1440         /* only the active group */
1441         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
1442         if(dg) {
1443                 def_nr= ob->actdef-1;
1444
1445                 for(i = 0; i < dvert_tot; i++) {
1446                         // Jason
1447                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1448                                 continue;
1449                         }
1450                         dvert = dvert_array[i];
1451
1452                         dw= defvert_find_index(dvert, def_nr);
1453
1454                         if(dw) {
1455                                 if(dw->weight <= eul)
1456                                         if(keep_single==FALSE || dvert->totweight > 1)
1457                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
1458                         }
1459                 }
1460         }
1461
1462         if (dvert_array) MEM_freeN(dvert_array);
1463 }
1464
1465 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
1466 {
1467
1468         MDeformWeight *dw;
1469         MDeformVert *dvert, **dvert_array=NULL;
1470         int i, dvert_tot=0;
1471         // Jason
1472         Mesh *me = ob->data;
1473         MVert *mv = me->mvert;
1474         int selectedVerts = me->editflag & ME_EDIT_VERT_SEL;
1475
1476         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1477
1478         if(dvert_array) {
1479                 for(i = 0; i < dvert_tot; i++) {
1480                         int j;
1481                         // Jason
1482                         if(selectedVerts && !((mv+i)->flag & SELECT)) {
1483                                 continue;
1484                         }
1485
1486                         dvert = dvert_array[i];
1487                         j= dvert->totweight;
1488
1489                         while(j--) {
1490
1491                                 if(keep_single && dvert->totweight == 1)
1492                                         break;
1493
1494                                 dw= dvert->dw + j;
1495
1496                                 if(dw->weight <= eul)
1497                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
1498
1499                         }
1500                 }
1501         }
1502
1503         if (dvert_array) MEM_freeN(dvert_array);
1504 }
1505
1506
1507 static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
1508                             const char sel, const char sel_mirr,
1509                             const int *flip_map,
1510                             const short mirror_weights, const short flip_vgroups)
1511 {
1512         BLI_assert(sel || sel_mirr);
1513
1514         if(sel_mirr && sel) {
1515                 /* swap */
1516                 if(mirror_weights)
1517                         SWAP(MDeformVert, *dvert, *dvert_mirr);
1518                 if(flip_vgroups) {
1519                         defvert_flip(dvert, flip_map);
1520                         defvert_flip(dvert_mirr, flip_map);
1521                 }
1522         }
1523         else {
1524                 /* dvert should always be the target */
1525                 if(sel_mirr) {
1526                         SWAP(MDeformVert *, dvert, dvert_mirr);
1527                 }
1528
1529                 if(mirror_weights)
1530                         defvert_copy(dvert, dvert_mirr);
1531                 if(flip_vgroups) {
1532                         defvert_flip(dvert, flip_map);
1533                 }
1534         }
1535 }
1536
1537 void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups)
1538 {
1539 #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups)
1540
1541         EditVert *eve, *eve_mirr;
1542         MDeformVert *dvert, *dvert_mirr;
1543         short sel, sel_mirr;
1544         int     *flip_map;
1545
1546         if(mirror_weights==0 && flip_vgroups==0)
1547                 return;
1548
1549         flip_map= defgroup_flip_map(ob, 0);
1550
1551         /* only the active group */
1552         if(ob->type == OB_MESH) {
1553                 Mesh *me= ob->data;
1554                 EditMesh *em = BKE_mesh_get_editmesh(me);
1555
1556
1557                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
1558                         MEM_freeN(flip_map);
1559                         return;
1560                 }
1561
1562                 EM_cache_x_mirror_vert(ob, em);
1563
1564                 /* Go through the list of editverts and assign them */
1565                 for(eve=em->verts.first; eve; eve=eve->next){
1566                         if((eve_mirr=eve->tmp.v)) {
1567                                 sel= eve->f & SELECT;
1568                                 sel_mirr= eve_mirr->f & SELECT;
1569
1570                                 if((sel || sel_mirr) && (eve != eve_mirr)) {
1571                                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1572                                         dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
1573                                         if(dvert && dvert_mirr) {
1574                                                 VGROUP_MIRR_OP;
1575                                         }
1576                                 }
1577
1578                                 eve->tmp.v= eve_mirr->tmp.v= NULL;
1579                         }
1580                 }
1581
1582                 BKE_mesh_end_editmesh(me, em);
1583         }
1584         else if (ob->type == OB_LATTICE) {
1585                 Lattice *lt= ob->data;
1586                 int i1, i2;
1587                 int u, v, w;
1588                 int pntsu_half;
1589                 /* half but found up odd value */
1590
1591                 if(lt->editlatt) lt= lt->editlatt->latt;
1592
1593                 if(lt->pntsu == 1 || lt->dvert == NULL) {
1594                         MEM_freeN(flip_map);
1595                         return;
1596                 }
1597
1598                 /* unlike editmesh we know that by only looping over the first hald of
1599                  * the 'u' indicies it will cover all points except the middle which is
1600                  * ok in this case */
1601                 pntsu_half= lt->pntsu / 2;
1602
1603                 for(w=0; w<lt->pntsw; w++) {
1604                         for(v=0; v<lt->pntsv; v++) {
1605                                 for(u=0; u<pntsu_half; u++) {
1606                                         int u_inv= (lt->pntsu - 1) - u;
1607                                         if(u != u_inv) {
1608                                                 BPoint *bp, *bp_mirr;
1609
1610                                                 i1= LT_INDEX(lt, u, v, w);
1611                                                 i2= LT_INDEX(lt, u_inv, v, w);
1612
1613                                                 bp= &lt->def[i1];
1614                                                 bp_mirr= &lt->def[i2];
1615
1616                                                 sel= bp->f1 & SELECT;
1617                                                 sel_mirr= bp_mirr->f1 & SELECT;
1618
1619                                                 if(sel || sel_mirr) {
1620                                                         dvert= &lt->dvert[i1];
1621                                                         dvert_mirr= &lt->dvert[i2];
1622
1623                                                         VGROUP_MIRR_OP;
1624                                                 }
1625                                         }
1626                                 }
1627                         }
1628                 }
1629         }
1630
1631         MEM_freeN(flip_map);
1632
1633 #undef VGROUP_MIRR_OP
1634 }
1635
1636 static void vgroup_remap_update_users(Object *ob, int *map)
1637 {
1638         ExplodeModifierData *emd;
1639         ModifierData *md;
1640         ParticleSystem *psys;
1641         ClothModifierData *clmd;
1642         ClothSimSettings *clsim;
1643         int a;
1644
1645         /* these cases don't use names to refer to vertex groups, so when
1646          * they get deleted the numbers get out of sync, this corrects that */
1647
1648         if(ob->soft)
1649                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1650
1651         for(md=ob->modifiers.first; md; md=md->next) {
1652                 if(md->type == eModifierType_Explode) {
1653                         emd= (ExplodeModifierData*)md;
1654                         emd->vgroup= map[emd->vgroup];
1655                 }
1656                 else if(md->type == eModifierType_Cloth) {
1657                         clmd= (ClothModifierData*)md;
1658                         clsim= clmd->sim_parms;
1659
1660                         if(clsim) {
1661                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1662                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1663                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1664                         }
1665                 }
1666         }
1667
1668         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1669                 for(a=0; a<PSYS_TOT_VG; a++)
1670                         psys->vgroup[a]= map[psys->vgroup[a]];
1671         }
1672 }
1673
1674
1675 static void vgroup_delete_update_users(Object *ob, int id)
1676 {
1677         int i, tot= BLI_countlist(&ob->defbase) + 1;
1678         int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del");
1679
1680         map[id]= map[0]= 0;
1681         for(i=1; i<id; i++) map[i]=i;
1682         for(i=id+1; i<tot; i++) map[i]=i-1;
1683
1684         vgroup_remap_update_users(ob, map);
1685         MEM_freeN(map);
1686 }
1687
1688
1689 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1690 {
1691         MDeformVert *dvert_array=NULL;
1692         int i, e, dvert_tot=0;
1693         const int dg_index= BLI_findindex(&ob->defbase, dg);
1694
1695         assert(dg_index > -1);
1696         
1697         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1698
1699         if(dvert_array) {
1700                 MDeformVert *dvert;
1701                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1702                         ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */
1703                 }
1704
1705                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1706                         for(e = 0; e < dvert->totweight; e++) {
1707                                 if(dvert->dw[e].def_nr > dg_index) {
1708                                         dvert->dw[e].def_nr--;
1709                                 }
1710                         }
1711                 }
1712         }
1713
1714         vgroup_delete_update_users(ob, dg_index + 1);
1715
1716         /* Remove the group */
1717         BLI_freelinkN(&ob->defbase, dg);
1718
1719         /* Update the active deform index if necessary */
1720         if(ob->actdef > dg_index)
1721                 ob->actdef--;
1722         if(ob->actdef < 1 && ob->defbase.first)
1723                 ob->actdef= 1;
1724
1725 }
1726
1727 /* only in editmode */
1728 /* removes from active defgroup, if allverts==0 only selected vertices */
1729 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1730 {
1731         EditVert *eve;
1732         MDeformVert *dvert;
1733         MDeformWeight *newdw;
1734         bDeformGroup *eg;
1735         int     i;
1736
1737         if(ob->type == OB_MESH) {
1738                 Mesh *me= ob->data;
1739                 EditMesh *em = BKE_mesh_get_editmesh(me);
1740
1741                 for(eve=em->verts.first; eve; eve=eve->next){
1742                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1743                 
1744                         if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){
1745                                 for(i=0; i<dvert->totweight; i++){
1746                                         /* Find group */
1747                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1748                                         if(eg == dg){
1749                                                 dvert->totweight--;
1750                                                 if(dvert->totweight){
1751                                                         newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1752                                                         
1753                                                         if(dvert->dw){
1754                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1755                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1756                                                                 MEM_freeN(dvert->dw);
1757                                                         }
1758                                                         dvert->dw=newdw;
1759                                                 }
1760                                                 else{
1761                                                         MEM_freeN(dvert->dw);
1762                                                         dvert->dw=NULL;
1763                                                         break;
1764                                                 }
1765                                         }
1766                                 }
1767                         }
1768                 }
1769                 BKE_mesh_end_editmesh(me, em);
1770         }
1771         else if(ob->type == OB_LATTICE) {
1772                 Lattice *lt= vgroup_edit_lattice(ob);
1773                 
1774                 if(lt->dvert) {
1775                         BPoint *bp;
1776                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1777                                 
1778                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1779                                 if(allverts || (bp->f1 & SELECT))
1780                                         ED_vgroup_vert_remove(ob, dg, a);
1781                         }
1782                 }
1783         }
1784 }
1785
1786 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1787 {
1788         int i;
1789         const int dg_index= BLI_findindex(&ob->defbase, dg);
1790
1791         assert(dg_index > -1);
1792
1793         /* Make sure that no verts are using this group */
1794         vgroup_active_remove_verts(ob, TRUE, dg);
1795
1796         /* Make sure that any verts with higher indices are adjusted accordingly */
1797         if(ob->type==OB_MESH) {
1798                 Mesh *me= ob->data;
1799                 EditMesh *em = BKE_mesh_get_editmesh(me);
1800                 EditVert *eve;
1801                 MDeformVert *dvert;
1802                 
1803                 for(eve=em->verts.first; eve; eve=eve->next){
1804                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1805
1806                         if(dvert)
1807                                 for(i=0; i<dvert->totweight; i++)
1808                                         if(dvert->dw[i].def_nr > dg_index)
1809                                                 dvert->dw[i].def_nr--;
1810                 }
1811                 BKE_mesh_end_editmesh(me, em);
1812         }
1813         else if(ob->type==OB_LATTICE) {
1814                 Lattice *lt= vgroup_edit_lattice(ob);
1815                 BPoint *bp;
1816                 MDeformVert *dvert= lt->dvert;
1817                 int a, tot;
1818                 
1819                 if(dvert) {
1820                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1821                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1822                                 for(i=0; i<dvert->totweight; i++){
1823                                         if(dvert->dw[i].def_nr > dg_index)
1824                                                 dvert->dw[i].def_nr--;
1825                                 }
1826                         }
1827                 }
1828         }
1829
1830         vgroup_delete_update_users(ob, dg_index + 1);
1831
1832         /* Remove the group */
1833         BLI_freelinkN (&ob->defbase, dg);
1834
1835         /* Update the active deform index if necessary */
1836         if(ob->actdef > dg_index)
1837                 ob->actdef--;
1838         if(ob->actdef < 1 && ob->defbase.first)
1839                 ob->actdef= 1;
1840
1841         /* remove all dverts */
1842         if(ob->defbase.first == NULL) {
1843                 if(ob->type==OB_MESH) {
1844                         Mesh *me= ob->data;
1845                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1846                         me->dvert= NULL;
1847                 }
1848                 else if(ob->type==OB_LATTICE) {
1849                         Lattice *lt= vgroup_edit_lattice(ob);
1850                         if(lt->dvert) {
1851                                 MEM_freeN(lt->dvert);
1852                                 lt->dvert= NULL;
1853                         }
1854                 }
1855         }
1856 }
1857
1858 static int vgroup_object_in_edit_mode(Object *ob)
1859 {
1860         if(ob->type == OB_MESH)
1861                 return (((Mesh*)ob->data)->edit_mesh != NULL);
1862         else if(ob->type == OB_LATTICE)
1863                 return (((Lattice*)ob->data)->editlatt != NULL);
1864         
1865         return 0;
1866 }
1867
1868 static void vgroup_delete(Object *ob)
1869 {
1870         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
1871         if(!dg)
1872                 return;
1873
1874         if(vgroup_object_in_edit_mode(ob))
1875                 vgroup_delete_edit_mode(ob, dg);
1876         else
1877                 vgroup_delete_object_mode(ob, dg);
1878 }
1879
1880 static void vgroup_delete_all(Object *ob)
1881 {
1882         /* Remove all DVerts */
1883         if(ob->type==OB_MESH) {
1884                 Mesh *me= ob->data;
1885                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1886                 me->dvert= NULL;
1887         }
1888         else if(ob->type==OB_LATTICE) {
1889                 Lattice *lt= vgroup_edit_lattice(ob);
1890                 if(lt->dvert) {
1891                         MEM_freeN(lt->dvert);
1892                         lt->dvert= NULL;
1893                 }
1894         }
1895         
1896         /* Remove all DefGroups */
1897         BLI_freelistN(&ob->defbase);
1898         
1899         /* Fix counters/indices */
1900         ob->actdef= 0;
1901 }
1902
1903 /* only in editmode */
1904 static void vgroup_assign_verts(Object *ob, float weight)
1905 {
1906         EditVert *eve;
1907         bDeformGroup *dg, *eg;
1908         MDeformWeight *newdw;
1909         MDeformVert *dvert;
1910         int     i, done;
1911
1912         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1913         if(!dg)
1914                 return;
1915
1916         if(ob->type == OB_MESH) {
1917                 Mesh *me= ob->data;
1918                 EditMesh *em = BKE_mesh_get_editmesh(me);
1919
1920                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1921                         EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT, NULL);
1922
1923                 /* Go through the list of editverts and assign them */
1924                 for(eve=em->verts.first; eve; eve=eve->next){
1925                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1926
1927                         if(dvert && (eve->f & SELECT)){
1928                                 /* See if this vert already has a reference to this group */
1929                                 /*              If so: Change its weight */
1930                                 done=0;
1931                                 for(i=0; i<dvert->totweight; i++){
1932                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1933                                         /* Find the actual group */
1934                                         if(eg==dg){
1935                                                 dvert->dw[i].weight= weight;
1936                                                 done=1;
1937                                                 break;
1938                                         }
1939                                  }
1940                                 /*              If not: Add the group and set its weight */
1941                                 if(!done){
1942                                         newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1943                                         if(dvert->dw){
1944                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1945                                                 MEM_freeN(dvert->dw);
1946                                         }
1947                                         dvert->dw=newdw;
1948
1949                                         dvert->dw[dvert->totweight].weight= weight;
1950                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1951
1952                                         dvert->totweight++;
1953
1954                                 }
1955                         }
1956                 }
1957                 BKE_mesh_end_editmesh(me, em);
1958         }
1959         else if(ob->type == OB_LATTICE) {
1960                 Lattice *lt= vgroup_edit_lattice(ob);
1961                 BPoint *bp;
1962                 int a, tot;
1963                 
1964                 if(lt->dvert==NULL)
1965                         ED_vgroup_data_create(&lt->id);
1966                 
1967                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1968                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1969                         if(bp->f1 & SELECT)
1970                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1971                 }
1972         }
1973 }
1974
1975 /* only in editmode */
1976 /* removes from all defgroup, if allverts==0 only selected vertices */
1977 static void vgroup_remove_verts(Object *ob, int allverts)
1978 {
1979         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1980          * only operates on the active vgroup. So we iterate through all groups, by changing
1981          * active group index
1982          */
1983         bDeformGroup *dg;
1984         for(dg= ob->defbase.first; dg; dg= dg->next) {
1985                 vgroup_active_remove_verts(ob, allverts, dg);
1986         }
1987 }
1988
1989 /********************** vertex group operators *********************/
1990
1991 static int vertex_group_poll(bContext *C)
1992 {
1993         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1994         ID *data= (ob)? ob->data: NULL;
1995         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1996 }
1997
1998 static int vertex_group_poll_edit(bContext *C)
1999 {
2000         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2001         ID *data= (ob)? ob->data: NULL;
2002
2003         if(!(ob && !ob->id.lib && data && !data->lib))
2004                 return 0;
2005
2006         return vgroup_object_in_edit_mode(ob);
2007 }
2008
2009 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
2010 {
2011         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2012
2013         ED_vgroup_add(ob);
2014         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2015         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2016         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2017         
2018         return OPERATOR_FINISHED;
2019 }
2020
2021 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
2022 {
2023         /* identifiers */
2024         ot->name= "Add Vertex Group";
2025         ot->idname= "OBJECT_OT_vertex_group_add";
2026         
2027         /* api callbacks */
2028         ot->poll= vertex_group_poll;
2029         ot->exec= vertex_group_add_exec;
2030
2031         /* flags */
2032         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2033 }
2034
2035 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
2036 {
2037         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2038
2039         if(RNA_boolean_get(op->ptr, "all"))
2040                 vgroup_delete_all(ob);
2041         else
2042                 vgroup_delete(ob);
2043
2044         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2045         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2046         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2047         
2048         return OPERATOR_FINISHED;
2049 }
2050
2051 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
2052 {
2053         /* identifiers */
2054         ot->name= "Remove Vertex Group";
2055         ot->idname= "OBJECT_OT_vertex_group_remove";
2056         
2057         /* api callbacks */
2058         ot->poll= vertex_group_poll;
2059         ot->exec= vertex_group_remove_exec;
2060
2061         /* flags */
2062         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2063
2064         /* properties */
2065         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
2066 }
2067
2068 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
2069 {
2070         ToolSettings *ts= CTX_data_tool_settings(C);
2071         Object *ob= CTX_data_edit_object(C);
2072
2073         if(RNA_boolean_get(op->ptr, "new"))
2074                 ED_vgroup_add(ob);
2075
2076         vgroup_assign_verts(ob, ts->vgroup_weight);
2077         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2078         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2079         
2080         return OPERATOR_FINISHED;
2081 }
2082
2083 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
2084 {
2085         /* identifiers */
2086         ot->name= "Assign Vertex Group";
2087         ot->idname= "OBJECT_OT_vertex_group_assign";
2088         
2089         /* api callbacks */
2090         ot->poll= vertex_group_poll_edit;
2091         ot->exec= vertex_group_assign_exec;
2092
2093         /* flags */
2094         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2095
2096         /* properties */
2097         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
2098 }
2099
2100 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
2101 {
2102         Object *ob= CTX_data_edit_object(C);
2103
2104         if(RNA_boolean_get(op->ptr, "all"))
2105                 vgroup_remove_verts(ob, 0);
2106         else {
2107                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
2108
2109                 if(dg == NULL) {
2110                         return OPERATOR_CANCELLED;
2111                 }
2112
2113                 vgroup_active_remove_verts(ob, FALSE, dg);
2114         }
2115
2116         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2117         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2118
2119         return OPERATOR_FINISHED;
2120 }
2121
2122 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
2123 {
2124         /* identifiers */
2125         ot->name= "Remove from Vertex Group";
2126         ot->idname= "OBJECT_OT_vertex_group_remove_from";
2127
2128         /* api callbacks */
2129         ot->poll= vertex_group_poll_edit;
2130         ot->exec= vertex_group_remove_from_exec;
2131
2132         /* flags */
2133         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2134
2135         /* properties */
2136         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
2137 }
2138
2139 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
2140 {
2141         Object *ob= CTX_data_edit_object(C);
2142
2143         if(!ob || ob->id.lib)
2144                 return OPERATOR_CANCELLED;
2145
2146         vgroup_select_verts(ob, 1);
2147         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2148
2149         return OPERATOR_FINISHED;
2150 }
2151
2152 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
2153 {
2154         /* identifiers */
2155         ot->name= "Select Vertex Group";
2156         ot->idname= "OBJECT_OT_vertex_group_select";
2157
2158         /* api callbacks */
2159         ot->poll= vertex_group_poll_edit;
2160         ot->exec= vertex_group_select_exec;
2161
2162         /* flags */
2163         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2164 }
2165
2166 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
2167 {
2168         Object *ob= CTX_data_edit_object(C);
2169
2170         vgroup_select_verts(ob, 0);
2171         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2172
2173         return OPERATOR_FINISHED;
2174 }
2175
2176 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
2177 {
2178         /* identifiers */
2179         ot->name= "Deselect Vertex Group";
2180         ot->idname= "OBJECT_OT_vertex_group_deselect";
2181
2182         /* api callbacks */
2183         ot->poll= vertex_group_poll_edit;
2184         ot->exec= vertex_group_deselect_exec;
2185
2186         /* flags */
2187         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2188 }
2189
2190 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
2191 {
2192         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2193
2194         vgroup_duplicate(ob);
2195         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2196         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2197         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2198
2199         return OPERATOR_FINISHED;
2200 }
2201
2202 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
2203 {
2204         /* identifiers */
2205         ot->name= "Copy Vertex Group";
2206         ot->idname= "OBJECT_OT_vertex_group_copy";
2207
2208         /* api callbacks */
2209         ot->poll= vertex_group_poll;
2210         ot->exec= vertex_group_copy_exec;
2211
2212         /* flags */
2213         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2214 }
2215
2216 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
2217 {
2218         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2219         
2220         float offset= RNA_float_get(op->ptr,"offset");
2221         float gain= RNA_float_get(op->ptr,"gain");
2222         
2223         vgroup_levels(ob, offset, gain);
2224         
2225         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2226         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2227         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2228         
2229         return OPERATOR_FINISHED;
2230 }
2231
2232 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
2233 {
2234         /* identifiers */
2235         ot->name= "Vertex Group Levels";
2236         ot->idname= "OBJECT_OT_vertex_group_levels";
2237         
2238         /* api callbacks */
2239         ot->poll= vertex_group_poll;
2240         ot->exec= vertex_group_levels_exec;
2241         
2242         /* flags */
2243         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2244         
2245         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
2246         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
2247 }
2248
2249 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
2250 {
2251         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2252
2253         vgroup_normalize(ob);
2254
2255         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2256         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2257         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2258
2259         return OPERATOR_FINISHED;
2260 }
2261
2262 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
2263 {
2264         /* identifiers */
2265         ot->name= "Normalize Vertex Group";
2266         ot->idname= "OBJECT_OT_vertex_group_normalize";
2267
2268         /* api callbacks */
2269         ot->poll= vertex_group_poll;
2270         ot->exec= vertex_group_normalize_exec;
2271
2272         /* flags */
2273         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2274 }
2275
2276 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
2277 {
2278         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2279         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
2280
2281         vgroup_normalize_all(ob, lock_active);
2282
2283         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2284         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2285         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2286
2287         return OPERATOR_FINISHED;
2288 }
2289
2290 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
2291 {
2292         /* identifiers */
2293         ot->name= "Normalize All Vertex Groups";
2294         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
2295
2296         /* api callbacks */
2297         ot->poll= vertex_group_poll;
2298         ot->exec= vertex_group_normalize_all_exec;
2299
2300         /* flags */
2301         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2302
2303         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
2304 }
2305 /* Jason */
2306 static int vertex_group_fix_exec(bContext *C, wmOperator *op)
2307 {
2308         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2309         Scene *scene= CTX_data_scene(C);
2310         
2311         float distToBe= RNA_float_get(op->ptr,"dist");
2312         float strength= RNA_float_get(op->ptr,"strength");
2313         float cp= RNA_float_get(op->ptr,"cp");
2314         ModifierData *md = ob->modifiers.first;
2315
2316         while(md) {
2317                 if(md->type == eModifierType_Mirror && (md->mode&eModifierMode_Realtime)) {
2318                         break;
2319                 }
2320                 md = md->next;
2321         }
2322         
2323         if(md && md->type == eModifierType_Mirror) {
2324                 BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
2325                 return OPERATOR_CANCELLED;
2326         }
2327         vgroup_fix(scene, ob, distToBe, strength, cp);
2328         
2329         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2330         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2331         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2332         
2333         return OPERATOR_FINISHED;
2334 }
2335
2336 void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
2337 {
2338         /* identifiers */
2339         ot->name= "Fix Vertex Group Deform";
2340         ot->idname= "OBJECT_OT_vertex_group_fix";
2341         
2342         /* api callbacks */
2343         ot->poll= vertex_group_poll;
2344         ot->exec= vertex_group_fix_exec;
2345         
2346         /* flags */
2347         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2348         RNA_def_float(ot->srna, "dist", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "The distance to move to.", -10.0f, 10.0f);        
2349         RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength", "The distance moved can be changed by this multiplier.", -2.0f, 2.0f);
2350         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);
2351 }
2352 /* Jason was here */
2353 static int vertex_group_invert_locks_exec(bContext *C, wmOperator *op)
2354 {
2355         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2356
2357         vgroup_invert_locks(ob);
2358
2359         return OPERATOR_FINISHED;
2360 }
2361 /* Jason was here */
2362 void OBJECT_OT_vertex_group_invert_locks(wmOperatorType *ot)
2363 {
2364         /* identifiers */
2365         ot->name= "Invert All Vertex Group Locks";
2366         ot->idname= "OBJECT_OT_vertex_group_invert_locks";
2367
2368         /* api callbacks */
2369         ot->poll= vertex_group_poll;
2370         ot->exec= vertex_group_invert_locks_exec;
2371
2372         /* flags */
2373         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2374 }
2375 /* Jason was here */
2376 static int vertex_group_lock_all_exec(bContext *C, wmOperator *op)
2377 {
2378         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2379
2380         vgroup_lock_all(ob);
2381
2382         return OPERATOR_FINISHED;
2383 }
2384 /* Jason was here */
2385 void OBJECT_OT_vertex_group_lock_all(wmOperatorType *ot)
2386 {
2387         /* identifiers */
2388         ot->name= "Turn on all Vertex Group Locks";
2389         ot->idname= "OBJECT_OT_vertex_group_lock_all";
2390
2391         /* api callbacks */
2392         ot->poll= vertex_group_poll;
2393         ot->exec= vertex_group_lock_all_exec;
2394
2395         /* flags */
2396         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2397 }
2398 /* Jason was here */
2399 static int vertex_group_unlock_all_exec(bContext *C, wmOperator *op)
2400 {
2401         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2402
2403         vgroup_unlock_all(ob);
2404
2405         return OPERATOR_FINISHED;
2406 }
2407 /* Jason was here */
2408 void OBJECT_OT_vertex_group_unlock_all(wmOperatorType *ot)
2409 {
2410         /* identifiers */
2411         ot->name= "Turn off all Vertex Group Locks";
2412         ot->idname= "OBJECT_OT_vertex_group_unlock_all";
2413
2414         /* api callbacks */
2415         ot->poll= vertex_group_poll;
2416         ot->exec= vertex_group_unlock_all_exec;
2417
2418         /* flags */
2419         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2420 }
2421 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
2422 {
2423         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2424         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
2425         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
2426
2427         vgroup_invert(ob, auto_assign, auto_remove);
2428         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2429         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2430         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2431
2432         return OPERATOR_FINISHED;
2433 }
2434
2435 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
2436 {
2437         /* identifiers */
2438         ot->name= "Invert Vertex Group";
2439         ot->idname= "OBJECT_OT_vertex_group_invert";
2440
2441         /* api callbacks */
2442         ot->poll= vertex_group_poll;
2443         ot->exec= vertex_group_invert_exec;
2444
2445         /* flags */
2446         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2447
2448         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
2449         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
2450 }
2451
2452
2453 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op))
2454 {
2455         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2456
2457         vgroup_blend(ob);
2458
2459         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2460         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2461         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2462
2463         return OPERATOR_FINISHED;
2464 }
2465
2466 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
2467 {
2468         /* identifiers */
2469         ot->name= "Blend Vertex Group";
2470         ot->idname= "OBJECT_OT_vertex_group_blend";
2471         ot->description= "";
2472
2473         /* api callbacks */
2474         ot->poll= vertex_group_poll;
2475         ot->exec= vertex_group_blend_exec;
2476
2477         /* flags */
2478         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2479 }
2480
2481
2482 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
2483 {
2484         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2485
2486         float limit= RNA_float_get(op->ptr,"limit");
2487         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
2488         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
2489
2490         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
2491         else                    vgroup_clean(ob, limit, keep_single);
2492
2493         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2494         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2495         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2496
2497         return OPERATOR_FINISHED;
2498 }
2499
2500 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
2501 {
2502         /* identifiers */
2503         ot->name= "Clean Vertex Group";
2504         ot->idname= "OBJECT_OT_vertex_group_clean";
2505         ot->description= "Remove Vertex Group assignments which aren't required";
2506
2507         /* api callbacks */
2508         ot->poll= vertex_group_poll;
2509         ot->exec= vertex_group_clean_exec;
2510
2511         /* flags */
2512         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2513
2514         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
2515         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
2516         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
2517 }
2518
2519
2520 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
2521 {
2522         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2523
2524         ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
2525
2526         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2527         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2528         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2529
2530         return OPERATOR_FINISHED;
2531 }
2532
2533 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
2534 {
2535         /* identifiers */
2536         ot->name= "Mirror Vertex Group";
2537         ot->idname= "OBJECT_OT_vertex_group_mirror";
2538         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";
2539
2540         /* api callbacks */
2541         ot->poll= vertex_group_poll_edit;
2542         ot->exec= vertex_group_mirror_exec;
2543
2544         /* flags */
2545         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2546
2547         /* properties */
2548         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
2549         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names.");
2550
2551 }
2552
2553 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
2554 {
2555         Scene *scene= CTX_data_scene(C);
2556         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2557         Base *base;
2558         int retval= OPERATOR_CANCELLED;
2559
2560         for(base=scene->base.first; base; base= base->next) {
2561                 if(base->object->type==ob->type) {
2562                         if(base->object!=ob && base->object->data==ob->data) {
2563                                 BLI_freelistN(&base->object->defbase);
2564                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
2565                                 base->object->actdef= ob->actdef;
2566
2567                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
2568                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
2569                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
2570
2571                                 retval = OPERATOR_FINISHED;
2572                         }
2573                 }
2574         }
2575
2576         return retval;
2577 }
2578
2579 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
2580 {
2581         /* identifiers */
2582         ot->name= "Copy Vertex Groups to Linked";
2583         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
2584         ot->description= "Copy Vertex Groups to all users of the same Geometry data";
2585
2586         /* api callbacks */
2587         ot->poll= vertex_group_poll;
2588         ot->exec= vertex_group_copy_to_linked_exec;
2589
2590         /* flags */
2591         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2592 }
2593
2594 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
2595 {
2596         Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2597         int change= 0;
2598         int fail= 0;
2599
2600         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
2601         {
2602                 if(obact != ob) {
2603                         if(ED_vgroup_copy_array(ob, obact)) change++;
2604                         else                                fail++;
2605                 }
2606         }
2607         CTX_DATA_END;
2608
2609         if((change == 0 && fail == 0) || fail) {
2610                 BKE_reportf(op->reports, RPT_ERROR, "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indicies", change, fail);
2611         }
2612
2613         return OPERATOR_FINISHED;
2614 }
2615
2616
2617 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
2618 {
2619         /* identifiers */
2620         ot->name= "Copy Vertex Group to Selected";
2621         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected";
2622         ot->description= "Copy Vertex Groups to other selected objects with matching indices";
2623
2624         /* api callbacks */
2625         ot->poll= vertex_group_poll;
2626         ot->exec= vertex_group_copy_to_selected_exec;
2627
2628         /* flags */
2629         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2630 }
2631
2632 static EnumPropertyItem vgroup_items[]= {
2633         {0, NULL, 0, NULL, NULL}};
2634
2635 static int set_active_group_exec(bContext *C, wmOperator *op)
2636 {
2637         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2638         int nr= RNA_enum_get(op->ptr, "group");
2639
2640         ob->actdef= nr+1;
2641
2642         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2643         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2644
2645         return OPERATOR_FINISHED;
2646 }
2647
2648 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
2649 {       
2650         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2651         EnumPropertyItem tmp = {0, "", 0, "", ""};
2652         EnumPropertyItem *item= NULL;
2653         bDeformGroup *def;
2654         int a, totitem= 0;
2655         
2656         if(!ob)
2657                 return vgroup_items;
2658         
2659         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
2660                 tmp.value= a;
2661                 tmp.icon= ICON_GROUP_VERTEX;
2662                 tmp.identifier= def->name;
2663                 tmp.name= def->name;
2664                 RNA_enum_item_add(&item, &totitem, &tmp);
2665         }
2666
2667         RNA_enum_item_end(&item, &totitem);
2668         *free= 1;
2669
2670         return item;
2671 }
2672
2673 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2674 {
2675         PropertyRNA *prop;
2676
2677         /* identifiers */
2678         ot->name= "Set Active Vertex Group";
2679         ot->idname= "OBJECT_OT_vertex_group_set_active";
2680         ot->description= "Set the active vertex group";
2681
2682         /* api callbacks */
2683         ot->poll= vertex_group_poll;
2684         ot->exec= set_active_group_exec;
2685         ot->invoke= WM_menu_invoke;
2686
2687         /* flags */
2688         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2689
2690         /* properties */
2691         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
2692         RNA_def_enum_funcs(prop, vgroup_itemf);
2693         ot->prop= prop;
2694 }
2695
2696 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling
2697   with the order of vgroups then call vgroup_do_remap after*/
2698 static char *vgroup_init_remap(Object *ob)
2699 {
2700         bDeformGroup *def;
2701         int def_tot = BLI_countlist(&ob->defbase);
2702         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups");
2703         char *name;
2704
2705         name= name_array;
2706         for(def = ob->defbase.first; def; def=def->next) {
2707                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
2708                 name += MAX_VGROUP_NAME;
2709         }
2710
2711         return name_array;
2712 }
2713
2714 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
2715 {
2716         MDeformVert *dvert= NULL;
2717         bDeformGroup *def;
2718         int def_tot = BLI_countlist(&ob->defbase);
2719         int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/
2720         int *sort_map= sort_map_update + 1;
2721         char *name;
2722         int i;
2723
2724         name= name_array;
2725         for(def= ob->defbase.first, i=0; def; def=def->next, i++){
2726                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
2727                 name += MAX_VGROUP_NAME;
2728         }
2729
2730         if(ob->mode == OB_MODE_EDIT) {
2731                 if(ob->type==OB_MESH) {
2732                         EditMesh *em = BKE_mesh_get_editmesh(ob->data);
2733                         EditVert *eve;
2734
2735                         for(eve=em->verts.first; eve; eve=eve->next){
2736                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
2737                                 if(dvert && dvert->totweight){
2738                                         defvert_remap(dvert, sort_map);
2739                                 }
2740                         }
2741                 }
2742                 else {
2743                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet.");
2744                         MEM_freeN(sort_map_update);
2745                         return OPERATOR_CANCELLED;
2746                 }
2747         }
2748         else {
2749                 int dvert_tot=0;
2750
2751                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
2752
2753                 /*create as necassary*/
2754                 while(dvert && dvert_tot--) {
2755                         if(dvert->totweight)
2756                                 defvert_remap(dvert, sort_map);
2757                         dvert++;
2758                 }
2759         }
2760
2761         /* update users */
2762         for(i=0; i<def_tot; i++)
2763                 sort_map[i]++;
2764
2765         sort_map_update[0]= 0;
2766         vgroup_remap_update_users(ob, sort_map_update);
2767
2768         ob->actdef= sort_map_update[ob->actdef];
2769         
2770         MEM_freeN(sort_map_update);
2771
2772         return OPERATOR_FINISHED;
2773 }
2774
2775 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
2776 {
2777         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
2778         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
2779
2780         return BLI_natstrcmp(def_a->name, def_b->name);
2781 }
2782
2783 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
2784 {
2785         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2786         char *name_array;
2787         int ret;
2788
2789         /*init remapping*/
2790         name_array = vgroup_init_remap(ob);
2791
2792         /*sort vgroup names*/
2793         BLI_sortlist(&ob->defbase, vgroup_sort);
2794
2795         /*remap vgroup data to map to correct names*/
2796         ret = vgroup_do_remap(ob, name_array, op);
2797
2798         if (ret != OPERATOR_CANCELLED) {
2799                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2800                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2801         }
2802
2803         if (name_array) MEM_freeN(name_array);
2804
2805         return ret;
2806 }
2807
2808 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
2809 {
2810         ot->name= "Sort Vertex Groups";
2811         ot->idname= "OBJECT_OT_vertex_group_sort";
2812         ot->description= "Sorts vertex groups alphabetically";
2813
2814         /* api callbacks */
2815         ot->poll= vertex_group_poll;
2816         ot->exec= vertex_group_sort_exec;
2817
2818         /* flags */
2819         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2820 }
2821
2822 static int vgroup_move_exec(bContext *C, wmOperator *op)
2823 {
2824         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2825         bDeformGroup *def;
2826         char *name_array;
2827         int dir= RNA_enum_get(op->ptr, "direction"), ret;
2828
2829         def = BLI_findlink(&ob->defbase, ob->actdef - 1);
2830         if (!def) {
2831                 return OPERATOR_CANCELLED;
2832         }
2833
2834         name_array = vgroup_init_remap(ob);
2835
2836         if (dir == 1) { /*up*/
2837                 void *prev = def->prev;
2838
2839                 BLI_remlink(&ob->defbase, def);
2840                 BLI_insertlinkbefore(&ob->defbase, prev, def);
2841         } else { /*down*/
2842                 void *next = def->next;
2843
2844                 BLI_remlink(&ob->defbase, def);
2845                 BLI_insertlinkafter(&ob->defbase, next, def);
2846         }
2847
2848         ret = vgroup_do_remap(ob, name_array, op);
2849
2850         if (name_array) MEM_freeN(name_array);
2851
2852         if (ret != OPERATOR_CANCELLED) {
2853                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2854                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2855         }
2856
2857         return ret;
2858 }
2859
2860 void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
2861 {
2862         static EnumPropertyItem vgroup_slot_move[] = {
2863                 {1, "UP", 0, "Up", ""},
2864                 {-1, "DOWN", 0, "Down", ""},
2865                 {0, NULL, 0, NULL, NULL}
2866         };
2867
2868         /* identifiers */
2869         ot->name= "Move Vertex Group";
2870         ot->idname= "OBJECT_OT_vertex_group_move";
2871
2872         /* api callbacks */
2873         ot->poll= vertex_group_poll;
2874         ot->exec= vgroup_move_exec;
2875
2876         /* flags */
2877         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2878
2879         RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
2880 }