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