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