ok, apparently didn't commit this either. apparently includes a merge with trunk...
[blender-staging.git] / source / blender / editors / object / object_vgroup.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include <string.h>
31 #include <math.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_cloth_types.h"
36 #include "DNA_curve_types.h"
37 #include "DNA_lattice_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_modifier_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_object_force.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_particle_types.h"
45 #include "DNA_windowmanager_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_cellalloc.h"
49
50 #include "BKE_context.h"
51 #include "BKE_customdata.h"
52 #include "BKE_deform.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_DerivedMesh.h"
55 #include "BKE_displist.h"
56 #include "BKE_global.h"
57 #include "BKE_lattice.h"
58 #include "BKE_mesh.h"
59 #include "BKE_paint.h"
60 #include "BKE_utildefines.h"
61 #include "BKE_tessmesh.h"
62
63 #include "RNA_access.h"
64 #include "RNA_define.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "ED_mesh.h"
70 #include "ED_view3d.h"
71
72 #include "UI_interface.h"
73 #include "UI_resources.h"
74
75 #include "object_intern.h"
76
77 /************************ Exported Functions **********************/
78
79 static Lattice *vgroup_edit_lattice(Object *ob)
80 {
81         if(ob->type==OB_LATTICE) {
82                 Lattice *lt= ob->data;
83                 return (lt->editlatt)? lt->editlatt: lt;
84         }
85
86         return NULL;
87 }
88
89 /* check if deform vertex has defgroup index */
90 MDeformWeight *ED_vgroup_weight_get(MDeformVert *dv, int defgroup)
91 {
92         int i;
93         
94         if(!dv || defgroup<0)
95                 return NULL;
96         
97         for(i=0; i<dv->totweight; i++)
98                 if(dv->dw[i].def_nr == defgroup)
99                         return dv->dw+i;
100
101         return NULL;
102 }
103
104 /* Ensures that mv has a deform weight entry for the specified defweight group */
105 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
106 MDeformWeight *ED_vgroup_weight_verify(MDeformVert *dv, int defgroup)
107 {
108         MDeformWeight *newdw;
109
110         /* do this check always, this function is used to check for it */
111         if(!dv || defgroup<0)
112                 return NULL;
113         
114         newdw = ED_vgroup_weight_get(dv, defgroup);
115         if(newdw)
116                 return newdw;
117         
118         newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
119         if(dv->dw) {
120                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
121                 BLI_cellalloc_free(dv->dw);
122         }
123         dv->dw=newdw;
124         
125         dv->dw[dv->totweight].weight=0.0f;
126         dv->dw[dv->totweight].def_nr=defgroup;
127         /* Group index */
128         
129         dv->totweight++;
130
131         return dv->dw+(dv->totweight-1);
132 }
133
134 bDeformGroup *ED_vgroup_add_name(Object *ob, char *name)
135 {
136         bDeformGroup *defgroup;
137         
138         if(!ob)
139                 return NULL;
140         
141         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
142
143         BLI_strncpy(defgroup->name, name, 32);
144
145         BLI_addtail(&ob->defbase, defgroup);
146         unique_vertexgroup_name(defgroup, ob);
147
148         ob->actdef = BLI_countlist(&ob->defbase);
149
150         return defgroup;
151 }
152
153 bDeformGroup *ED_vgroup_add(Object *ob) 
154 {
155         return ED_vgroup_add_name(ob, "Group");
156 }
157
158 void ED_vgroup_data_create(ID *id)
159 {
160         /* create deform verts */
161
162         if(GS(id->name)==ID_ME) {
163                 Mesh *me= (Mesh *)id;
164                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
165         }
166         else if(GS(id->name)==ID_LT) {
167                 Lattice *lt= (Lattice *)id;
168                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
169         }
170 }
171
172 /* returns true if the id type supports weights */
173 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
174 {
175         if(id) {
176                 switch(GS(id->name)) {
177                         case ID_ME:
178                         {
179                                 Mesh *me = (Mesh *)id;
180                                 *dvert_arr= me->dvert;
181                                 *dvert_tot= me->totvert;
182                                 return TRUE;
183                         }
184                         case ID_LT:
185                         {
186                                 Lattice *lt= (Lattice *)id;
187                                 lt= (lt->editlatt)? lt->editlatt: lt;
188                                 *dvert_arr= lt->dvert;
189                                 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
190                                 return TRUE;
191                         }
192                 }
193         }
194
195         *dvert_arr= NULL;
196         *dvert_tot= 0;
197         return FALSE;
198 }
199 /* for mesh in object mode
200    lattice can be in editmode */
201 void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
202 {
203         /* This routine removes the vertex from the deform
204          * group with number def_nr.
205          *
206          * This routine is meant to be fast, so it is the
207          * responsibility of the calling routine to:
208          *   a) test whether ob is non-NULL
209          *   b) test whether ob is a mesh
210          *   c) calculate def_nr
211          */
212
213         MDeformWeight *newdw;
214         MDeformVert *dvert= NULL;
215         int i, tot;
216
217         /* get the deform vertices corresponding to the
218          * vertnum
219          */
220         ED_vgroup_give_array(ob->data, &dvert, &tot);
221
222         if(dvert==NULL)
223                 return;
224         
225         dvert+= vertnum;
226
227         /* for all of the deform weights in the
228          * deform vert
229          */
230         for(i=dvert->totweight - 1 ; i>=0 ; i--){
231
232                 /* if the def_nr is the same as the one
233                  * for our weight group then remove it
234                  * from this deform vert.
235                  */
236                 if(dvert->dw[i].def_nr == def_nr) {
237                         dvert->totweight--;
238         
239                         /* if there are still other deform weights
240                          * attached to this vert then remove this
241                          * deform weight, and reshuffle the others
242                          */
243                         if(dvert->totweight) {
244                                 newdw = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight), 
245                                                                          "deformWeight");
246                                 if(dvert->dw){
247                                         memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
248                                         memcpy(newdw+i, dvert->dw+i+1, 
249                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
250                                         BLI_cellalloc_free(dvert->dw);
251                                 }
252                                 dvert->dw=newdw;
253                         }
254                         /* if there are no other deform weights
255                          * left then just remove the deform weight
256                          */
257                         else {
258                                 MEM_freeN(dvert->dw);
259                                 dvert->dw = NULL;
260                                 break;
261                         }
262                 }
263         }
264
265 }
266
267 /* for Mesh in Object mode */
268 /* allows editmode for Lattice */
269 void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode)
270 {
271         /* add the vert to the deform group with the
272          * specified number
273          */
274         MDeformVert *dv= NULL;
275         MDeformWeight *newdw;
276         int     i, tot;
277
278         /* get the vert */
279         ED_vgroup_give_array(ob->data, &dv, &tot);
280         
281         if(dv==NULL)
282                 return;
283         
284         dv+= vertnum;
285
286         /* Lets first check to see if this vert is
287          * already in the weight group -- if so
288          * lets update it
289          */
290         for(i=0; i<dv->totweight; i++){
291                 
292                 /* if this weight cooresponds to the
293                  * deform group, then add it using
294                  * the assign mode provided
295                  */
296                 if(dv->dw[i].def_nr == def_nr){
297                         
298                         switch(assignmode) {
299                         case WEIGHT_REPLACE:
300                                 dv->dw[i].weight=weight;
301                                 break;
302                         case WEIGHT_ADD:
303                                 dv->dw[i].weight+=weight;
304                                 if(dv->dw[i].weight >= 1.0)
305                                         dv->dw[i].weight = 1.0;
306                                 break;
307                         case WEIGHT_SUBTRACT:
308                                 dv->dw[i].weight-=weight;
309                                 /* if the weight is zero or less then
310                                  * remove the vert from the deform group
311                                  */
312                                 if(dv->dw[i].weight <= 0.0)
313                                         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
314                                 break;
315                         }
316                         return;
317                 }
318         }
319
320         /* if the vert wasn't in the deform group then
321          * we must take a different form of action ...
322          */
323
324         switch(assignmode) {
325         case WEIGHT_SUBTRACT:
326                 /* if we are subtracting then we don't
327                  * need to do anything
328                  */
329                 return;
330
331         case WEIGHT_REPLACE:
332         case WEIGHT_ADD:
333                 /* if we are doing an additive assignment, then
334                  * we need to create the deform weight
335                  */
336                 newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dv->totweight+1), 
337                                                          "deformWeight");
338                 if(dv->dw){
339                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
340                         BLI_cellalloc_free(dv->dw);
341                 }
342                 dv->dw=newdw;
343     
344                 dv->dw[dv->totweight].weight=weight;
345                 dv->dw[dv->totweight].def_nr=def_nr;
346     
347                 dv->totweight++;
348                 break;
349         }
350 }
351
352 /* called while not in editmode */
353 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
354 {
355         /* add the vert to the deform group with the
356          * specified assign mode
357          */
358         int     def_nr;
359
360         MDeformVert *dv= NULL;
361         int tot;
362
363         /* get the deform group number, exit if
364          * it can't be found
365          */
366         def_nr = get_defgroup_num(ob, dg);
367         if(def_nr < 0) return;
368
369         /* if there's no deform verts then create some,
370          */
371         if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
372                 ED_vgroup_data_create(ob->data);
373
374         /* call another function to do the work
375          */
376         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
377 }
378
379 /* mesh object mode, lattice can be in editmode */
380 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
381 {
382         /* This routine removes the vertex from the specified
383          * deform group.
384          */
385
386         int def_nr;
387
388         /* if the object is NULL abort
389          */
390         if(!ob)
391                 return;
392
393         /* get the deform number that cooresponds
394          * to this deform group, and abort if it
395          * can not be found.
396          */
397         def_nr = get_defgroup_num(ob, dg);
398         if(def_nr < 0) return;
399
400         /* call another routine to do the work
401          */
402         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
403 }
404
405
406 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
407 {
408         MDeformVert *dvert= NULL;
409         BMVert *eve;
410         Mesh *me;
411         int i;
412
413         /* get the deform vertices corresponding to the vertnum */
414         if(ob->type==OB_MESH) {
415                 me= ob->data;
416
417                 if(me->edit_btmesh) {
418                         eve= BMIter_AtIndex(me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL, vertnum);
419                         if(!eve) return 0.0f;
420                         dvert= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT);
421                         vertnum= 0;
422                 }
423                 else
424                         dvert = me->dvert;
425         }
426         else if(ob->type==OB_LATTICE) {
427                 Lattice *lt= vgroup_edit_lattice(ob);
428                 
429                 if(lt->dvert)
430                         dvert = lt->dvert;
431         }
432         
433         if(dvert==NULL)
434                 return 0.0f;
435         
436         dvert += vertnum;
437         
438         for(i=dvert->totweight-1 ; i>=0 ; i--)
439                 if(dvert->dw[i].def_nr == def_nr)
440                         return dvert->dw[i].weight;
441
442         return 0.0f;
443 }
444
445 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
446 {
447         int def_nr;
448
449         if(!ob) return 0.0f;
450
451         def_nr = get_defgroup_num(ob, dg);
452         if(def_nr < 0) return 0.0f;
453
454         return get_vert_def_nr(ob, def_nr, vertnum);
455 }
456
457 void ED_vgroup_select_by_name(Object *ob, char *name)
458 {
459         bDeformGroup *curdef;
460         int actdef= 1;
461         
462         for(curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
463                 if(!strcmp(curdef->name, name)) {
464                         ob->actdef= actdef;
465                         return;
466                 }
467         }
468
469         ob->actdef=0;   // this signals on painting to create a new one, if a bone in posemode is selected */
470 }
471
472 /********************** Operator Implementations *********************/
473
474 /* only in editmode */
475 static void vgroup_select_verts(Object *ob, int select)
476 {
477         BMVert *eve;
478         MDeformVert *dvert;
479         int i;
480
481         if(ob->type == OB_MESH) {
482                 Mesh *me= ob->data;
483                 BMEditMesh *em = me->edit_btmesh;
484                 BMIter iter;
485
486                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
487                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
488
489                         if(dvert && dvert->totweight){
490                                 for(i=0; i<dvert->totweight; i++){
491                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
492                                                 BM_Select(em->bm, eve, select);
493                                                 break;
494                                         }
495                                 }
496                         }
497                 }
498                 /* this has to be called, because this function operates on vertices only */
499                 if(select) EDBM_selectmode_flush(em);   // vertices to edges/faces
500                 else EDBM_deselect_flush(em);
501         }
502         else if(ob->type == OB_LATTICE) {
503                 Lattice *lt= vgroup_edit_lattice(ob);
504                 
505                 if(lt->dvert) {
506                         BPoint *bp;
507                         int a, tot;
508                         
509                         dvert= lt->dvert;
510
511                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
512                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
513                                 for(i=0; i<dvert->totweight; i++){
514                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
515                                                 if(select) bp->f1 |= SELECT;
516                                                 else bp->f1 &= ~SELECT;
517                                                 
518                                                 break;
519                                         }
520                                 }
521                         }
522                 }
523         }
524 }
525
526 static void vgroup_duplicate(Object *ob)
527 {
528         bDeformGroup *dg, *cdg;
529         char name[32], s[32];
530         MDeformWeight *org, *cpy;
531         MDeformVert *dvert, *dvert_array=NULL;
532         int i, idg, icdg, dvert_tot=0;
533
534         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
535         if(!dg)
536                 return;
537         
538         if(strstr(dg->name, "_copy")) {
539                 BLI_strncpy(name, dg->name, 32); /* will be renamed _copy.001... etc */
540         }
541         else {
542                 BLI_snprintf(name, 32, "%s_copy", dg->name);
543                 while(get_named_vertexgroup(ob, name)) {
544                         if((strlen(name) + 6) > 32) {
545                                 printf("Internal error: the name for the new vertex group is > 32 characters");
546                                 return;
547                         }
548                         strcpy(s, name);
549                         BLI_snprintf(name, 32, "%s_copy", s);
550                 }
551         }               
552
553         cdg = copy_defgroup(dg);
554         strcpy(cdg->name, name);
555         unique_vertexgroup_name(cdg, ob);
556         
557         BLI_addtail(&ob->defbase, cdg);
558
559         idg = (ob->actdef-1);
560         ob->actdef = BLI_countlist(&ob->defbase);
561         icdg = (ob->actdef-1);
562
563         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
564         
565         if(!dvert_array)
566                 return;
567
568         for(i = 0; i < dvert_tot; i++) {
569                 dvert = dvert_array+i;
570                 org = ED_vgroup_weight_get(dvert, idg);
571                 if(org) {
572                         float weight = org->weight;
573                         /* ED_vgroup_weight_verify re-allocs org so need to store the weight first */
574                         cpy = ED_vgroup_weight_verify(dvert, icdg);
575                         cpy->weight = weight;
576                 }
577         }
578 }
579
580 static void vgroup_normalize(Object *ob)
581 {
582         bDeformGroup *dg;
583         MDeformWeight *dw;
584         MDeformVert *dvert, *dvert_array=NULL;
585         int i, def_nr, dvert_tot=0;
586
587         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
588
589         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
590
591         if(dg) {
592                 float weight_max = 0.0f;
593
594                 def_nr= ob->actdef-1;
595
596                 for(i = 0; i < dvert_tot; i++) {
597                         dvert = dvert_array+i;
598                         dw = ED_vgroup_weight_get(dvert, def_nr);
599                         if(dw) {
600                                 weight_max = MAX2(dw->weight, weight_max);
601                         }
602                 }
603
604                 if(weight_max > 0.0f) {
605                         for(i = 0; i < dvert_tot; i++) {
606                                 dvert = dvert_array+i;
607                                 dw = ED_vgroup_weight_get(dvert, def_nr);
608                                 if(dw) {
609                                         dw->weight /= weight_max;
610                                         
611                                         /* incase of division errors with very low weights */
612                                         CLAMP(dw->weight, 0.0f, 1.0f);
613                                 }
614                         }
615                 }
616         }
617 }
618
619 static void vgroup_levels(Object *ob, float offset, float gain)
620 {
621         bDeformGroup *dg;
622         MDeformWeight *dw;
623         MDeformVert *dvert, *dvert_array=NULL;
624         int i, def_nr, dvert_tot=0;
625         
626         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
627         
628         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
629         
630         if(dg) {
631                 def_nr= ob->actdef-1;
632                 
633                 for(i = 0; i < dvert_tot; i++) {
634                         dvert = dvert_array+i;
635                         dw = ED_vgroup_weight_get(dvert, def_nr);
636                         if(dw) {
637                                 dw->weight = gain * (dw->weight + offset);
638                                 
639                                 CLAMP(dw->weight, 0.0f, 1.0f);
640                         }
641                 }
642         }
643 }
644
645 /* TODO - select between groups */
646 static void vgroup_normalize_all(Object *ob, int lock_active)
647 {
648         MDeformWeight *dw, *dw_act;
649         MDeformVert *dvert, *dvert_array=NULL;
650         int i, dvert_tot=0;
651         float tot_weight;
652
653         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
654
655         if(dvert_array) {
656                 if(lock_active) {
657                         int def_nr= ob->actdef-1;
658
659                         for(i = 0; i < dvert_tot; i++) {
660                                 float lock_iweight= 1.0f;
661                                 int j;
662
663                                 tot_weight= 0.0f;
664                                 dw_act= NULL;
665                                 dvert = dvert_array+i;
666
667                                 j= dvert->totweight;
668                                 while(j--) {
669                                         dw= dvert->dw + j;
670
671                                         if(dw->def_nr==def_nr) {
672                                                 dw_act= dw;
673                                                 lock_iweight = (1.0f - dw_act->weight);
674                                         }
675                                         else {
676                                                 tot_weight += dw->weight;
677                                         }
678                                 }
679
680                                 if(tot_weight) {
681                                         j= dvert->totweight;
682                                         while(j--) {
683                                                 dw= dvert->dw + j;
684                                                 if(dw == dw_act) {
685                                                         if (dvert->totweight==1) {
686                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
687                                                         }
688                                                 } else {
689                                                         if(dw->weight > 0.0f)
690                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
691                                                 }
692
693                                                 /* incase of division errors with very low weights */
694                                                 CLAMP(dw->weight, 0.0f, 1.0f);
695                                         }
696                                 }
697                         }
698                 }
699                 else {
700                         for(i = 0; i < dvert_tot; i++) {
701                                 int j;
702                                 tot_weight= 0.0f;
703                                 dvert = dvert_array+i;
704
705                                 j= dvert->totweight;
706                                 while(j--) {
707                                         dw= dvert->dw + j;
708                                         tot_weight += dw->weight;
709                                 }
710
711                                 if(tot_weight) {
712                                         j= dvert->totweight;
713                                         while(j--) {
714                                                 dw= dvert->dw + j;
715                                                 dw->weight /= tot_weight;
716
717                                                 /* incase of division errors with very low weights */
718                                                 CLAMP(dw->weight, 0.0f, 1.0f);
719                                         }
720                                 }
721                         }
722                 }
723         }
724 }
725
726
727 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
728 {
729         bDeformGroup *dg;
730         MDeformWeight *dw;
731         MDeformVert *dvert, *dvert_array=NULL;
732         int i, def_nr, dvert_tot=0;
733
734         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
735
736         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
737
738         if(dg) {
739                 def_nr= ob->actdef-1;
740
741
742                 for(i = 0; i < dvert_tot; i++) {
743                         dvert = dvert_array+i;
744
745                         if(auto_assign) {
746                                 dw= ED_vgroup_weight_verify(dvert, def_nr);
747                         } else {
748                                 dw= ED_vgroup_weight_get(dvert, def_nr);
749                         }
750
751                         if(dw) {
752                                 dw->weight = 1.0f-dw->weight;
753
754                                 if(auto_remove && dw->weight <= 0.0f) {
755                                         /* could have a faster function for this */
756                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
757                                 }
758                         }
759                 }
760         }
761 }
762
763 static void vgroup_blend(Object *ob)
764 {
765         BMEditMesh *em= ((Mesh *)ob->data)->edit_btmesh;
766         bDeformGroup *dg;
767         MDeformWeight *dw;
768         MDeformVert *dvert_array=NULL, *dvert;
769         int i, def_nr, dvert_tot=0;
770
771         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
772
773         if(em==NULL)
774                 return;
775
776         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
777
778         if(dg) {
779                 BMEdge *eed;
780                 BMVert *eve;
781                 BMIter iter;
782                 float *vg_weights;
783                 float *vg_users;
784                 int sel1, sel2;
785                 int i1, i2;
786
787                 def_nr= ob->actdef-1;
788
789                 i= 0;
790                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
791                         BMINDEX_SET(eve, i);
792                         i++;
793                 }
794                 dvert_tot= i;
795
796                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
797                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
798
799                 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
800                         sel1= BM_TestHFlag(eed->v1, BM_SELECT);
801                         sel2= BM_TestHFlag(eed->v2, BM_SELECT);
802
803                         if(sel1 != sel2) {
804                                 /* i1 is always the selected one */
805                                 if(sel1==TRUE && sel2==FALSE) {
806                                         i1= BMINDEX_GET(eed->v1);
807                                         i2= BMINDEX_GET(eed->v2);
808                                         eve= eed->v2;
809                                 }
810                                 else {
811                                         i2= BMINDEX_GET(eed->v1);
812                                         i1= BMINDEX_GET(eed->v2);
813                                         eve= eed->v1;
814                                 }
815
816                                 vg_users[i1]++;
817
818                                 /* TODO, we may want object mode blending */
819                                 if(em)  dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
820                                 else    dvert= dvert_array+i2;
821
822                                 dw= ED_vgroup_weight_get(dvert, def_nr);
823
824                                 if(dw) {
825                                         vg_weights[i1] += dw->weight;
826                                 }
827                         }
828                 }
829
830                 i= 0;
831                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
832                         if(BM_TestHFlag(eve, BM_SELECT) && vg_users[i] > 0) {
833                                 /* TODO, we may want object mode blending */
834                                 if(em)  dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
835                                 else    dvert= dvert_array+i;
836
837                                 dw= ED_vgroup_weight_verify(dvert, def_nr);
838                                 dw->weight= vg_weights[i] / (float)vg_users[i];
839                         }
840
841                         i++;
842                 }
843                 MEM_freeN(vg_weights);
844                 MEM_freeN(vg_users);
845         }
846 }
847
848 static void vgroup_clean(Object *ob, float eul, int keep_single)
849 {
850         bDeformGroup *dg;
851         MDeformWeight *dw;
852         MDeformVert *dvert, *dvert_array=NULL;
853         int i, def_nr, dvert_tot=0;
854
855         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
856
857         /* only the active group */
858         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
859         if(dg) {
860                 def_nr= ob->actdef-1;
861
862                 for(i = 0; i < dvert_tot; i++) {
863                         dvert = dvert_array+i;
864
865                         dw= ED_vgroup_weight_get(dvert, def_nr);
866
867                         if(dw) {
868                                 if(dw->weight <= eul)
869                                         if(keep_single==FALSE || dvert->totweight > 1)
870                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
871                         }
872                 }
873         }
874 }
875
876 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
877 {
878
879         MDeformWeight *dw;
880         MDeformVert *dvert, *dvert_array=NULL;
881         int i, dvert_tot=0;
882
883         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
884
885         if(dvert_array) {
886                 for(i = 0; i < dvert_tot; i++) {
887                         int j;
888                         dvert = dvert_array+i;
889                         j= dvert->totweight;
890
891                         while(j--) {
892
893                                 if(keep_single && dvert->totweight == 1)
894                                         break;
895
896                                 dw= dvert->dw + j;
897
898                                 if(dw->weight <= eul)
899                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
900
901                         }
902                 }
903         }
904 }
905
906 static void vgroup_delete_update_users(Object *ob, int id)
907 {
908         ExplodeModifierData *emd;
909         ModifierData *md;
910         ParticleSystem *psys;
911         ClothModifierData *clmd;
912         ClothSimSettings *clsim;
913         int a;
914
915         /* these cases don't use names to refer to vertex groups, so when
916          * they get deleted the numbers get out of sync, this corrects that */
917
918         if(ob->soft) {
919                 if(ob->soft->vertgroup == id)
920                         ob->soft->vertgroup= 0;
921                 else if(ob->soft->vertgroup > id)
922                         ob->soft->vertgroup--;
923         }
924
925         for(md=ob->modifiers.first; md; md=md->next) {
926                 if(md->type == eModifierType_Explode) {
927                         emd= (ExplodeModifierData*)md;
928
929                         if(emd->vgroup == id)
930                                 emd->vgroup= 0;
931                         else if(emd->vgroup > id)
932                                 emd->vgroup--;
933                 }
934                 else if(md->type == eModifierType_Cloth) {
935                         clmd= (ClothModifierData*)md;
936                         clsim= clmd->sim_parms;
937
938                         if(clsim) {
939                                 if(clsim->vgroup_mass == id)
940                                         clsim->vgroup_mass= 0;
941                                 else if(clsim->vgroup_mass > id)
942                                         clsim->vgroup_mass--;
943
944                                 if(clsim->vgroup_bend == id)
945                                         clsim->vgroup_bend= 0;
946                                 else if(clsim->vgroup_bend > id)
947                                         clsim->vgroup_bend--;
948
949                                 if(clsim->vgroup_struct == id)
950                                         clsim->vgroup_struct= 0;
951                                 else if(clsim->vgroup_struct > id)
952                                         clsim->vgroup_struct--;
953                         }
954                 }
955         }
956
957         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
958                 for(a=0; a<PSYS_TOT_VG; a++)
959                         if(psys->vgroup[a] == id)
960                                 psys->vgroup[a]= 0;
961                         else if(psys->vgroup[a] > id)
962                                 psys->vgroup[a]--;
963         }
964 }
965
966 static void vgroup_delete_object_mode(Object *ob)
967 {
968         bDeformGroup *dg;
969         MDeformVert *dvert, *dvert_array=NULL;
970         int i, e, dvert_tot=0;
971         
972         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
973         if(!dg)
974                 return;
975         
976         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
977
978         if(dvert_array) {
979                 for(i = 0; i < dvert_tot; i++) {
980                         dvert = dvert_array + i;
981                         if(dvert) {
982                                 if(ED_vgroup_weight_get(dvert, (ob->actdef-1)))
983                                         ED_vgroup_vert_remove(ob, dg, i);
984                         }
985                 }
986
987                 for(i = 0; i < dvert_tot; i++) {
988                         dvert = dvert_array+i;
989                         if(dvert) {
990                                 for(e = 0; e < dvert->totweight; e++) {
991                                         if(dvert->dw[e].def_nr > (ob->actdef-1))
992                                                 dvert->dw[e].def_nr--;
993                                 }
994                         }
995                 }
996         }
997
998         vgroup_delete_update_users(ob, ob->actdef);
999
1000         /* Update the active deform index if necessary */
1001         if(ob->actdef == BLI_countlist(&ob->defbase))
1002                 ob->actdef--;
1003   
1004         /* Remove the group */
1005         BLI_freelinkN(&ob->defbase, dg);
1006 }
1007 /* only in editmode */
1008 /* removes from active defgroup, if allverts==0 only selected vertices */
1009 static void vgroup_active_remove_verts(Object *ob, int allverts)
1010 {
1011         BMVert *eve;
1012         MDeformVert *dvert;
1013         MDeformWeight *newdw;
1014         bDeformGroup *dg, *eg;
1015         int     i;
1016
1017         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1018         if(!dg)
1019                 return;
1020
1021         if(ob->type == OB_MESH) {
1022                 Mesh *me= ob->data;
1023                 BMEditMesh *em = me->edit_btmesh;
1024                 BMIter iter;
1025
1026                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1027                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1028                 
1029                         if(dvert && dvert->dw && (BM_TestHFlag(eve, BM_SELECT) || allverts)){
1030                                 for(i=0; i<dvert->totweight; i++){
1031                                         /* Find group */
1032                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1033                                         if(eg == dg){
1034                                                 dvert->totweight--;
1035                                                 if (dvert->totweight){
1036                                                         newdw = BLI_cellalloc_malloc (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1037                                                         
1038                                                         if(dvert->dw){
1039                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1040                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1041                                                                 MEM_freeN(dvert->dw);
1042                                                         }
1043                                                         dvert->dw=newdw;
1044                                                 }
1045                                                 else{
1046                                                         BLI_cellalloc_free (dvert->dw);
1047                                                         dvert->dw=NULL;
1048                                                         break;
1049                                                 }
1050                                         }
1051                                 }
1052                         }
1053                 }
1054         }
1055         else if(ob->type == OB_LATTICE) {
1056                 Lattice *lt= vgroup_edit_lattice(ob);
1057                 
1058                 if(lt->dvert) {
1059                         BPoint *bp;
1060                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1061                                 
1062                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1063                                 if(allverts || (bp->f1 & SELECT))
1064                                         ED_vgroup_vert_remove(ob, dg, a);
1065                         }
1066                 }
1067         }
1068 }
1069
1070 static void vgroup_delete_edit_mode(Object *ob)
1071 {
1072         bDeformGroup *defgroup;
1073         int i;
1074
1075         if(!ob->actdef)
1076                 return;
1077
1078         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
1079         if(!defgroup)
1080                 return;
1081
1082         /* Make sure that no verts are using this group */
1083         vgroup_active_remove_verts(ob, 1);
1084
1085         /* Make sure that any verts with higher indices are adjusted accordingly */
1086         if(ob->type==OB_MESH) {
1087                 Mesh *me= ob->data;
1088                 BMEditMesh *em = me->edit_btmesh;
1089                 BMIter iter;
1090                 BMVert *eve;
1091                 MDeformVert *dvert;
1092                 
1093                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1094                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1095
1096                         if(dvert)
1097                                 for(i=0; i<dvert->totweight; i++)
1098                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
1099                                                 dvert->dw[i].def_nr--;
1100                 }
1101         }
1102         else if(ob->type==OB_LATTICE) {
1103                 Lattice *lt= vgroup_edit_lattice(ob);
1104                 BPoint *bp;
1105                 MDeformVert *dvert= lt->dvert;
1106                 int a, tot;
1107                 
1108                 if(dvert) {
1109                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1110                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1111                                 for(i=0; i<dvert->totweight; i++){
1112                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
1113                                                 dvert->dw[i].def_nr--;
1114                                 }
1115                         }
1116                 }
1117         }
1118
1119         vgroup_delete_update_users(ob, ob->actdef);
1120
1121         /* Update the active deform index if necessary */
1122         if(ob->actdef==BLI_countlist(&ob->defbase))
1123                 ob->actdef--;
1124         
1125         /* Remove the group */
1126         BLI_freelinkN (&ob->defbase, defgroup);
1127         
1128         /* remove all dverts */
1129         if(ob->actdef==0) {
1130                 if(ob->type==OB_MESH) {
1131                         Mesh *me= ob->data;
1132                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1133                         me->dvert= NULL;
1134                 }
1135                 else if(ob->type==OB_LATTICE) {
1136                         Lattice *lt= vgroup_edit_lattice(ob);
1137                         if(lt->dvert) {
1138                                 MEM_freeN(lt->dvert);
1139                                 lt->dvert= NULL;
1140                         }
1141                 }
1142         }
1143 }
1144
1145 static int vgroup_object_in_edit_mode(Object *ob)
1146 {
1147         if(ob->type == OB_MESH)
1148                 return (((Mesh*)ob->data)->edit_btmesh != NULL);
1149         else if(ob->type == OB_LATTICE)
1150                 return (((Lattice*)ob->data)->editlatt != NULL);
1151         
1152         return 0;
1153 }
1154
1155 static void vgroup_delete(Object *ob)
1156 {
1157         if(vgroup_object_in_edit_mode(ob))
1158                 vgroup_delete_edit_mode(ob);
1159         else
1160                 vgroup_delete_object_mode(ob);
1161 }
1162
1163 static void vgroup_delete_all(Object *ob)
1164 {
1165         /* Remove all DVerts */
1166         if(ob->type==OB_MESH) {
1167                 Mesh *me= ob->data;
1168                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1169                 me->dvert= NULL;
1170         }
1171         else if(ob->type==OB_LATTICE) {
1172                 Lattice *lt= vgroup_edit_lattice(ob);
1173                 if(lt->dvert) {
1174                         MEM_freeN(lt->dvert);
1175                         lt->dvert= NULL;
1176                 }
1177         }
1178         
1179         /* Remove all DefGroups */
1180         BLI_freelistN(&ob->defbase);
1181         
1182         /* Fix counters/indices */
1183         ob->actdef= 0;
1184 }
1185
1186 /* only in editmode */
1187 static void vgroup_assign_verts(Object *ob, float weight)
1188 {
1189         BMVert *eve;
1190         bDeformGroup *dg, *eg;
1191         MDeformWeight *newdw;
1192         MDeformVert *dvert;
1193         int     i, done;
1194
1195         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1196         if(!dg)
1197                 return;
1198
1199         if(ob->type == OB_MESH) {
1200                 Mesh *me= ob->data;
1201                 BMEditMesh *em = me->edit_btmesh;
1202                 BMIter iter;
1203
1204                 if(!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
1205                         BM_add_data_layer(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
1206
1207                 /* Go through the list of editverts and assign them */
1208                 BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
1209                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1210
1211                         if(dvert && BM_TestHFlag(eve, BM_SELECT)) {
1212                                 done=0;
1213                                 /* See if this vert already has a reference to this group */
1214                                 /*              If so: Change its weight */
1215                                 done=0;
1216                                 for(i=0; i<dvert->totweight; i++){
1217                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1218                                         /* Find the actual group */
1219                                         if(eg==dg){
1220                                                 dvert->dw[i].weight= weight;
1221                                                 done=1;
1222                                                 break;
1223                                         }
1224                                 }
1225                                 /*              If not: Add the group and set its weight */
1226                                 if(!done){
1227                                         newdw = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1228                                         if(dvert->dw){
1229                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1230                                                 BLI_cellalloc_free(dvert->dw);
1231                                         }
1232                                         dvert->dw=newdw;
1233
1234                                         dvert->dw[dvert->totweight].weight= weight;
1235                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1236
1237                                         dvert->totweight++;
1238
1239                                 }
1240                         }
1241                 }
1242         }
1243         else if(ob->type == OB_LATTICE) {
1244                 Lattice *lt= vgroup_edit_lattice(ob);
1245                 BPoint *bp;
1246                 int a, tot;
1247                 
1248                 if(lt->dvert==NULL)
1249                         ED_vgroup_data_create(&lt->id);
1250                 
1251                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1252                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1253                         if(bp->f1 & SELECT)
1254                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1255                 }
1256         }
1257 }
1258
1259 /* only in editmode */
1260 /* removes from all defgroup, if allverts==0 only selected vertices */
1261 static void vgroup_remove_verts(Object *ob, int allverts)
1262 {
1263         int actdef, defCount;
1264         
1265         actdef= ob->actdef;
1266         defCount= BLI_countlist(&ob->defbase);
1267         
1268         if(defCount == 0)
1269                 return;
1270         
1271         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1272          * only operates on the active vgroup. So we iterate through all groups, by changing
1273          * active group index
1274          */
1275         for(ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
1276                 vgroup_active_remove_verts(ob, allverts);
1277                 
1278         ob->actdef= actdef;
1279 }
1280
1281 /********************** vertex group operators *********************/
1282
1283 static int vertex_group_poll(bContext *C)
1284 {
1285         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1286         ID *data= (ob)? ob->data: NULL;
1287         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1288 }
1289
1290 static int vertex_group_poll_edit(bContext *C)
1291 {
1292         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1293         ID *data= (ob)? ob->data: NULL;
1294
1295         if(!(ob && !ob->id.lib && data && !data->lib))
1296                 return 0;
1297
1298         return vgroup_object_in_edit_mode(ob);
1299 }
1300
1301 static int vertex_group_add_exec(bContext *C, wmOperator *op)
1302 {
1303         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1304
1305         ED_vgroup_add(ob);
1306         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1307         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1308         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1309         
1310         return OPERATOR_FINISHED;
1311 }
1312
1313 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
1314 {
1315         /* identifiers */
1316         ot->name= "Add Vertex Group";
1317         ot->idname= "OBJECT_OT_vertex_group_add";
1318         
1319         /* api callbacks */
1320         ot->poll= vertex_group_poll;
1321         ot->exec= vertex_group_add_exec;
1322
1323         /* flags */
1324         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1325 }
1326
1327 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1328 {
1329         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1330
1331         if(RNA_boolean_get(op->ptr, "all"))
1332                 vgroup_delete_all(ob);
1333         else
1334                 vgroup_delete(ob);
1335
1336         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1337         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1338         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1339         
1340         return OPERATOR_FINISHED;
1341 }
1342
1343 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1344 {
1345         /* identifiers */
1346         ot->name= "Remove Vertex Group";
1347         ot->idname= "OBJECT_OT_vertex_group_remove";
1348         
1349         /* api callbacks */
1350         ot->poll= vertex_group_poll;
1351         ot->exec= vertex_group_remove_exec;
1352
1353         /* flags */
1354         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1355
1356         /* properties */
1357         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1358 }
1359
1360 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1361 {
1362         ToolSettings *ts= CTX_data_tool_settings(C);
1363         Object *ob= CTX_data_edit_object(C);
1364
1365         if(RNA_boolean_get(op->ptr, "new"))
1366                 ED_vgroup_add(ob);
1367
1368         vgroup_assign_verts(ob, ts->vgroup_weight);
1369         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1370         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1371         
1372         return OPERATOR_FINISHED;
1373 }
1374
1375 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1376 {
1377         /* identifiers */
1378         ot->name= "Assign Vertex Group";
1379         ot->idname= "OBJECT_OT_vertex_group_assign";
1380         
1381         /* api callbacks */
1382         ot->poll= vertex_group_poll_edit;
1383         ot->exec= vertex_group_assign_exec;
1384
1385         /* flags */
1386         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1387
1388         /* properties */
1389         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1390 }
1391
1392 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1393 {
1394         Object *ob= CTX_data_edit_object(C);
1395
1396         vgroup_remove_verts(ob, 0);
1397         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1398         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1399
1400         return OPERATOR_FINISHED;
1401 }
1402
1403 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1404 {
1405         /* identifiers */
1406         ot->name= "Remove from Vertex Group";
1407         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1408
1409         /* api callbacks */
1410         ot->poll= vertex_group_poll_edit;
1411         ot->exec= vertex_group_remove_from_exec;
1412
1413         /* flags */
1414         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1415
1416         /* properties */
1417         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1418 }
1419
1420 static int vertex_group_select_exec(bContext *C, wmOperator *op)
1421 {
1422         Object *ob= CTX_data_edit_object(C);
1423
1424         if(!ob || ob->id.lib)
1425                 return OPERATOR_CANCELLED;
1426
1427         vgroup_select_verts(ob, 1);
1428         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1429
1430         return OPERATOR_FINISHED;
1431 }
1432
1433 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1434 {
1435         /* identifiers */
1436         ot->name= "Select Vertex Group";
1437         ot->idname= "OBJECT_OT_vertex_group_select";
1438
1439         /* api callbacks */
1440         ot->poll= vertex_group_poll_edit;
1441         ot->exec= vertex_group_select_exec;
1442
1443         /* flags */
1444         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1445 }
1446
1447 static int vertex_group_deselect_exec(bContext *C, wmOperator *op)
1448 {
1449         Object *ob= CTX_data_edit_object(C);
1450
1451         vgroup_select_verts(ob, 0);
1452         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1453
1454         return OPERATOR_FINISHED;
1455 }
1456
1457 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1458 {
1459         /* identifiers */
1460         ot->name= "Deselect Vertex Group";
1461         ot->idname= "OBJECT_OT_vertex_group_deselect";
1462
1463         /* api callbacks */
1464         ot->poll= vertex_group_poll_edit;
1465         ot->exec= vertex_group_deselect_exec;
1466
1467         /* flags */
1468         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1469 }
1470
1471 static int vertex_group_copy_exec(bContext *C, wmOperator *op)
1472 {
1473         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1474
1475         vgroup_duplicate(ob);
1476         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1477         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1478         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1479
1480         return OPERATOR_FINISHED;
1481 }
1482
1483 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1484 {
1485         /* identifiers */
1486         ot->name= "Copy Vertex Group";
1487         ot->idname= "OBJECT_OT_vertex_group_copy";
1488
1489         /* api callbacks */
1490         ot->poll= vertex_group_poll;
1491         ot->exec= vertex_group_copy_exec;
1492
1493         /* flags */
1494         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1495 }
1496
1497 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
1498 {
1499         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1500         
1501         float offset= RNA_float_get(op->ptr,"offset");
1502         float gain= RNA_float_get(op->ptr,"gain");
1503         
1504         vgroup_levels(ob, offset, gain);
1505         
1506         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1507         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1508         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1509         
1510         return OPERATOR_FINISHED;
1511 }
1512
1513 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
1514 {
1515         /* identifiers */
1516         ot->name= "Vertex Group Levels";
1517         ot->idname= "OBJECT_OT_vertex_group_levels";
1518         
1519         /* api callbacks */
1520         ot->poll= vertex_group_poll;
1521         ot->exec= vertex_group_levels_exec;
1522         
1523         /* flags */
1524         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1525         
1526         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
1527         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
1528 }
1529
1530 static int vertex_group_normalize_exec(bContext *C, wmOperator *op)
1531 {
1532         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1533
1534         vgroup_normalize(ob);
1535
1536         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1537         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1538         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1539
1540         return OPERATOR_FINISHED;
1541 }
1542
1543 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
1544 {
1545         /* identifiers */
1546         ot->name= "Normalize Vertex Group";
1547         ot->idname= "OBJECT_OT_vertex_group_normalize";
1548
1549         /* api callbacks */
1550         ot->poll= vertex_group_poll;
1551         ot->exec= vertex_group_normalize_exec;
1552
1553         /* flags */
1554         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1555 }
1556
1557 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
1558 {
1559         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1560         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
1561
1562         vgroup_normalize_all(ob, lock_active);
1563
1564         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1565         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1566         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1567
1568         return OPERATOR_FINISHED;
1569 }
1570
1571 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
1572 {
1573         /* identifiers */
1574         ot->name= "Normalize All Vertex Groups";
1575         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
1576
1577         /* api callbacks */
1578         ot->poll= vertex_group_poll;
1579         ot->exec= vertex_group_normalize_all_exec;
1580
1581         /* flags */
1582         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1583
1584         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
1585 }
1586
1587 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
1588 {
1589         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1590         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
1591         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
1592
1593         vgroup_invert(ob, auto_assign, auto_remove);
1594         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1595         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1596         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1597
1598         return OPERATOR_FINISHED;
1599 }
1600
1601 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
1602 {
1603         /* identifiers */
1604         ot->name= "Invert Vertex Group";
1605         ot->idname= "OBJECT_OT_vertex_group_invert";
1606
1607         /* api callbacks */
1608         ot->poll= vertex_group_poll;
1609         ot->exec= vertex_group_invert_exec;
1610
1611         /* flags */
1612         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1613
1614         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
1615         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
1616 }
1617
1618
1619 static int vertex_group_blend_exec(bContext *C, wmOperator *op)
1620 {
1621         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1622
1623         vgroup_blend(ob);
1624
1625         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1626         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1627         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1628
1629         return OPERATOR_FINISHED;
1630 }
1631
1632 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
1633 {
1634         /* identifiers */
1635         ot->name= "Blend Vertex Group";
1636         ot->idname= "OBJECT_OT_vertex_group_blend";
1637         ot->description= "";
1638
1639         /* api callbacks */
1640         ot->poll= vertex_group_poll;
1641         ot->exec= vertex_group_blend_exec;
1642
1643         /* flags */
1644         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1645 }
1646
1647
1648 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
1649 {
1650         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1651
1652         float limit= RNA_float_get(op->ptr,"limit");
1653         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
1654         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
1655
1656         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
1657         else                    vgroup_clean(ob, limit, keep_single);
1658
1659         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1660         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1661         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1662
1663         return OPERATOR_FINISHED;
1664 }
1665
1666 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
1667 {
1668         /* identifiers */
1669         ot->name= "Clean Vertex Group";
1670         ot->idname= "OBJECT_OT_vertex_group_clean";
1671         ot->description= "Remove Vertex Group assignments which aren't required.";
1672
1673         /* api callbacks */
1674         ot->poll= vertex_group_poll;
1675         ot->exec= vertex_group_clean_exec;
1676
1677         /* flags */
1678         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1679
1680         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
1681         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
1682         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
1683 }
1684
1685
1686 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
1687 {
1688         Scene *scene= CTX_data_scene(C);
1689         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1690         Base *base;
1691         int retval= OPERATOR_CANCELLED;
1692
1693         for(base=scene->base.first; base; base= base->next) {
1694                 if(base->object->type==ob->type) {
1695                         if(base->object!=ob && base->object->data==ob->data) {
1696                                 BLI_freelistN(&base->object->defbase);
1697                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1698                                 base->object->actdef= ob->actdef;
1699
1700                                 DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
1701                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1702                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1703
1704                                 retval = OPERATOR_FINISHED;
1705                         }
1706                 }
1707         }
1708
1709         return retval;
1710 }
1711
1712 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1713 {
1714         /* identifiers */
1715         ot->name= "Copy Vertex Group to Linked";
1716         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1717         ot->description= "Copy Vertex Groups to all users of the same Geometry data.";
1718
1719         /* api callbacks */
1720         ot->poll= vertex_group_poll;
1721         ot->exec= vertex_group_copy_to_linked_exec;
1722
1723         /* flags */
1724         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1725 }
1726
1727 static EnumPropertyItem vgroup_items[]= {
1728         {0, NULL, 0, NULL, NULL}};
1729
1730 static int set_active_group_exec(bContext *C, wmOperator *op)
1731 {
1732         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1733         int nr= RNA_enum_get(op->ptr, "group");
1734
1735         ob->actdef= nr+1;
1736
1737         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1738         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1739
1740         return OPERATOR_FINISHED;
1741 }
1742
1743 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *ptr, int *free)
1744 {       
1745         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1746         EnumPropertyItem tmp = {0, "", 0, "", ""};
1747         EnumPropertyItem *item= NULL;
1748         bDeformGroup *def;
1749         int a, totitem= 0;
1750         
1751         if(!ob)
1752                 return vgroup_items;
1753         
1754         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
1755                 tmp.value= a;
1756                 tmp.icon= ICON_GROUP_VERTEX;
1757                 tmp.identifier= def->name;
1758                 tmp.name= def->name;
1759                 RNA_enum_item_add(&item, &totitem, &tmp);
1760         }
1761
1762         RNA_enum_item_end(&item, &totitem);
1763         *free= 1;
1764
1765         return item;
1766 }
1767
1768 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
1769 {
1770         PropertyRNA *prop;
1771
1772         /* identifiers */
1773         ot->name= "Set Active Vertex Group";
1774         ot->idname= "OBJECT_OT_vertex_group_set_active";
1775         ot->description= "Set the active vertex group.";
1776
1777         /* api callbacks */
1778         ot->poll= vertex_group_poll;
1779         ot->exec= set_active_group_exec;
1780         ot->invoke= WM_menu_invoke;
1781
1782         /* flags */
1783         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1784
1785         /* properties */
1786         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
1787         RNA_def_enum_funcs(prop, vgroup_itemf);
1788 }