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