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