5e5390b7d702cdfac7561f3afcbec4ee2147d344
[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
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 = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
117         if(dv->dw) {
118                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
119                 MEM_freeN(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 = MEM_mallocN(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                                         MEM_freeN(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 = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), 
335                                                          "deformWeight");
336                 if(dv->dw){
337                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
338                         MEM_freeN(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 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
404 {
405         MDeformVert *dvert= NULL;
406         EditVert *eve;
407         Mesh *me;
408         int i;
409
410         /* get the deform vertices corresponding to the vertnum */
411         if(ob->type==OB_MESH) {
412                 me= ob->data;
413
414                 if(me->edit_mesh) {
415                         eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
416                         if(!eve) return 0.0f;
417                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
418                         vertnum= 0;
419                 }
420                 else
421                         dvert = me->dvert;
422         }
423         else if(ob->type==OB_LATTICE) {
424                 Lattice *lt= vgroup_edit_lattice(ob);
425                 
426                 if(lt->dvert)
427                         dvert = lt->dvert;
428         }
429         
430         if(dvert==NULL)
431                 return 0.0f;
432         
433         dvert += vertnum;
434         
435         for(i=dvert->totweight-1 ; i>=0 ; i--)
436                 if(dvert->dw[i].def_nr == def_nr)
437                         return dvert->dw[i].weight;
438
439         return 0.0f;
440 }
441
442 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
443 {
444         int def_nr;
445
446         if(!ob) return 0.0f;
447
448         def_nr = get_defgroup_num(ob, dg);
449         if(def_nr < 0) return 0.0f;
450
451         return get_vert_def_nr(ob, def_nr, vertnum);
452 }
453
454 void ED_vgroup_select_by_name(Object *ob, char *name)
455 {
456         bDeformGroup *curdef;
457         int actdef= 1;
458         
459         for(curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){
460                 if(!strcmp(curdef->name, name)) {
461                         ob->actdef= actdef;
462                         return;
463                 }
464         }
465
466         ob->actdef=0;   // this signals on painting to create a new one, if a bone in posemode is selected */
467 }
468
469 /********************** Operator Implementations *********************/
470
471 /* only in editmode */
472 static void vgroup_select_verts(Object *ob, int select)
473 {
474         EditVert *eve;
475         MDeformVert *dvert;
476         int i;
477
478         if(ob->type == OB_MESH) {
479                 Mesh *me= ob->data;
480                 EditMesh *em = BKE_mesh_get_editmesh(me);
481
482                 for(eve=em->verts.first; eve; eve=eve->next){
483                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
484
485                         if(dvert && dvert->totweight){
486                                 for(i=0; i<dvert->totweight; i++){
487                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
488                                                 if(select) eve->f |= SELECT;
489                                                 else eve->f &= ~SELECT;
490                                                 
491                                                 break;
492                                         }
493                                 }
494                         }
495                 }
496                 /* this has to be called, because this function operates on vertices only */
497                 if(select) EM_select_flush(em); // vertices to edges/faces
498                 else EM_deselect_flush(em);
499
500                 BKE_mesh_end_editmesh(me, em);
501         }
502         else if(ob->type == OB_LATTICE) {
503                 Lattice *lt= vgroup_edit_lattice(ob);
504                 
505                 if(lt->dvert) {
506                         BPoint *bp;
507                         int a, tot;
508                         
509                         dvert= lt->dvert;
510
511                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
512                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
513                                 for(i=0; i<dvert->totweight; i++){
514                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
515                                                 if(select) bp->f1 |= SELECT;
516                                                 else bp->f1 &= ~SELECT;
517                                                 
518                                                 break;
519                                         }
520                                 }
521                         }
522                 }
523         }
524 }
525
526 static void vgroup_duplicate(Object *ob)
527 {
528         bDeformGroup *dg, *cdg;
529         char name[32], s[32];
530         MDeformWeight *org, *cpy;
531         MDeformVert *dvert, *dvert_array=NULL;
532         int i, idg, icdg, dvert_tot=0;
533
534         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
535         if(!dg)
536                 return;
537         
538         if(strstr(dg->name, "_copy")) {
539                 BLI_strncpy(name, dg->name, 32); /* will be renamed _copy.001... etc */
540         }
541         else {
542                 BLI_snprintf(name, 32, "%s_copy", dg->name);
543                 while(get_named_vertexgroup(ob, name)) {
544                         if((strlen(name) + 6) > 32) {
545                                 printf("Internal error: the name for the new vertex group is > 32 characters");
546                                 return;
547                         }
548                         strcpy(s, name);
549                         BLI_snprintf(name, 32, "%s_copy", s);
550                 }
551         }               
552
553         cdg = copy_defgroup(dg);
554         strcpy(cdg->name, name);
555         unique_vertexgroup_name(cdg, ob);
556         
557         BLI_addtail(&ob->defbase, cdg);
558
559         idg = (ob->actdef-1);
560         ob->actdef = BLI_countlist(&ob->defbase);
561         icdg = (ob->actdef-1);
562
563         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
564         
565         if(!dvert_array)
566                 return;
567
568         for(i = 0; i < dvert_tot; i++) {
569                 dvert = dvert_array+i;
570                 org = ED_vgroup_weight_get(dvert, idg);
571                 if(org) {
572                         float weight = org->weight;
573                         /* ED_vgroup_weight_verify re-allocs org so need to store the weight first */
574                         cpy = ED_vgroup_weight_verify(dvert, icdg);
575                         cpy->weight = weight;
576                 }
577         }
578 }
579
580 static void vgroup_normalize(Object *ob)
581 {
582         bDeformGroup *dg;
583         MDeformWeight *dw;
584         MDeformVert *dvert, *dvert_array=NULL;
585         int i, def_nr, dvert_tot=0;
586
587         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
588
589         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
590
591         if(dg) {
592                 float weight_max = 0.0f;
593
594                 def_nr= ob->actdef-1;
595
596                 for(i = 0; i < dvert_tot; i++) {
597                         dvert = dvert_array+i;
598                         dw = ED_vgroup_weight_get(dvert, def_nr);
599                         if(dw) {
600                                 weight_max = MAX2(dw->weight, weight_max);
601                         }
602                 }
603
604                 if(weight_max > 0.0f) {
605                         for(i = 0; i < dvert_tot; i++) {
606                                 dvert = dvert_array+i;
607                                 dw = ED_vgroup_weight_get(dvert, def_nr);
608                                 if(dw) {
609                                         dw->weight /= weight_max;
610                                         
611                                         /* incase of division errors with very low weights */
612                                         CLAMP(dw->weight, 0.0f, 1.0f);
613                                 }
614                         }
615                 }
616         }
617 }
618
619 static void vgroup_levels(Object *ob, float offset, float gain)
620 {
621         bDeformGroup *dg;
622         MDeformWeight *dw;
623         MDeformVert *dvert, *dvert_array=NULL;
624         int i, def_nr, dvert_tot=0;
625         
626         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
627         
628         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
629         
630         if(dg) {
631                 def_nr= ob->actdef-1;
632                 
633                 for(i = 0; i < dvert_tot; i++) {
634                         dvert = dvert_array+i;
635                         dw = ED_vgroup_weight_get(dvert, def_nr);
636                         if(dw) {
637                                 dw->weight = gain * (dw->weight + offset);
638                                 
639                                 CLAMP(dw->weight, 0.0f, 1.0f);
640                         }
641                 }
642         }
643 }
644
645 /* TODO - select between groups */
646 static void vgroup_normalize_all(Object *ob, int lock_active)
647 {
648         MDeformWeight *dw, *dw_act;
649         MDeformVert *dvert, *dvert_array=NULL;
650         int i, dvert_tot=0;
651         float tot_weight;
652
653         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
654
655         if(dvert_array) {
656                 if(lock_active) {
657                         int def_nr= ob->actdef-1;
658
659                         for(i = 0; i < dvert_tot; i++) {
660                                 float lock_iweight= 1.0f;
661                                 int j;
662
663                                 tot_weight= 0.0f;
664                                 dw_act= NULL;
665                                 dvert = dvert_array+i;
666
667                                 j= dvert->totweight;
668                                 while(j--) {
669                                         dw= dvert->dw + j;
670
671                                         if(dw->def_nr==def_nr) {
672                                                 dw_act= dw;
673                                                 lock_iweight = (1.0f - dw_act->weight);
674                                         }
675                                         else {
676                                                 tot_weight += dw->weight;
677                                         }
678                                 }
679
680                                 if(tot_weight) {
681                                         j= dvert->totweight;
682                                         while(j--) {
683                                                 dw= dvert->dw + j;
684                                                 if(dw == dw_act) {
685                                                         if (dvert->totweight==1) {
686                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
687                                                         }
688                                                 } else {
689                                                         if(dw->weight > 0.0f)
690                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
691                                                 }
692
693                                                 /* incase of division errors with very low weights */
694                                                 CLAMP(dw->weight, 0.0f, 1.0f);
695                                         }
696                                 }
697                         }
698                 }
699                 else {
700                         for(i = 0; i < dvert_tot; i++) {
701                                 int j;
702                                 tot_weight= 0.0f;
703                                 dvert = dvert_array+i;
704
705                                 j= dvert->totweight;
706                                 while(j--) {
707                                         dw= dvert->dw + j;
708                                         tot_weight += dw->weight;
709                                 }
710
711                                 if(tot_weight) {
712                                         j= dvert->totweight;
713                                         while(j--) {
714                                                 dw= dvert->dw + j;
715                                                 dw->weight /= tot_weight;
716
717                                                 /* incase of division errors with very low weights */
718                                                 CLAMP(dw->weight, 0.0f, 1.0f);
719                                         }
720                                 }
721                         }
722                 }
723         }
724 }
725
726
727 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
728 {
729         bDeformGroup *dg;
730         MDeformWeight *dw;
731         MDeformVert *dvert, *dvert_array=NULL;
732         int i, def_nr, dvert_tot=0;
733
734         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
735
736         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
737
738         if(dg) {
739                 def_nr= ob->actdef-1;
740
741
742                 for(i = 0; i < dvert_tot; i++) {
743                         dvert = dvert_array+i;
744
745                         if(auto_assign) {
746                                 dw= ED_vgroup_weight_verify(dvert, def_nr);
747                         } else {
748                                 dw= ED_vgroup_weight_get(dvert, def_nr);
749                         }
750
751                         if(dw) {
752                                 dw->weight = 1.0f-dw->weight;
753
754                                 if(auto_remove && dw->weight <= 0.0f) {
755                                         /* could have a faster function for this */
756                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
757                                 }
758                         }
759                 }
760         }
761 }
762
763 static void vgroup_blend(Object *ob)
764 {
765         bDeformGroup *dg;
766         MDeformWeight *dw;
767         MDeformVert *dvert_array=NULL, *dvert;
768         int i, def_nr, dvert_tot=0;
769
770         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
771         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
772
773         if(em==NULL)
774                 return;
775
776         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
777
778         if(dg) {
779                 int sel1, sel2;
780                 int i1, i2;
781
782                 EditEdge *eed;
783                 EditVert *eve;
784                 float *vg_weights;
785                 float *vg_users;
786
787                 def_nr= ob->actdef-1;
788
789                 i= 0;
790                 for(eve= em->verts.first; eve; eve= eve->next)
791                         eve->tmp.l= i++;
792
793                 dvert_tot= i;
794
795                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
796                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
797
798                 for(eed= em->edges.first; eed; eed= eed->next) {
799                         sel1= eed->v1->f & SELECT;
800                         sel2= eed->v2->f & SELECT;
801
802                         if(sel1 != sel2) {
803                                 /* i1 is always the selected one */
804                                 if(sel1==TRUE && sel2==FALSE) {
805                                         i1= eed->v1->tmp.l;
806                                         i2= eed->v2->tmp.l;
807                                         eve= eed->v2;
808                                 }
809                                 else {
810                                         i2= eed->v1->tmp.l;
811                                         i1= eed->v2->tmp.l;
812                                         eve= eed->v1;
813                                 }
814
815                                 vg_users[i1]++;
816
817                                 /* TODO, we may want object mode blending */
818                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
819                                 else    dvert= dvert_array+i2;
820
821                                 dw= ED_vgroup_weight_get(dvert, def_nr);
822
823                                 if(dw) {
824                                         vg_weights[i1] += dw->weight;
825                                 }
826                         }
827                 }
828
829                 i= 0;
830                 for(eve= em->verts.first; eve; eve= eve->next) {
831                         if(eve->f & SELECT && vg_users[i] > 0) {
832                                 /* TODO, we may want object mode blending */
833                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
834                                 else    dvert= dvert_array+i;
835
836                                 dw= ED_vgroup_weight_verify(dvert, def_nr);
837                                 dw->weight= vg_weights[i] / (float)vg_users[i];
838                         }
839
840                         i++;
841                 }
842                 MEM_freeN(vg_weights);
843                 MEM_freeN(vg_users);
844         }
845 }
846
847 static void vgroup_clean(Object *ob, float eul, int keep_single)
848 {
849         bDeformGroup *dg;
850         MDeformWeight *dw;
851         MDeformVert *dvert, *dvert_array=NULL;
852         int i, def_nr, dvert_tot=0;
853
854         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
855
856         /* only the active group */
857         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
858         if(dg) {
859                 def_nr= ob->actdef-1;
860
861                 for(i = 0; i < dvert_tot; i++) {
862                         dvert = dvert_array+i;
863
864                         dw= ED_vgroup_weight_get(dvert, def_nr);
865
866                         if(dw) {
867                                 if(dw->weight <= eul)
868                                         if(keep_single==FALSE || dvert->totweight > 1)
869                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
870                         }
871                 }
872         }
873 }
874
875 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
876 {
877
878         MDeformWeight *dw;
879         MDeformVert *dvert, *dvert_array=NULL;
880         int i, dvert_tot=0;
881
882         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
883
884         if(dvert_array) {
885                 for(i = 0; i < dvert_tot; i++) {
886                         int j;
887                         dvert = dvert_array+i;
888                         j= dvert->totweight;
889
890                         while(j--) {
891
892                                 if(keep_single && dvert->totweight == 1)
893                                         break;
894
895                                 dw= dvert->dw + j;
896
897                                 if(dw->weight <= eul)
898                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
899
900                         }
901                 }
902         }
903 }
904
905 static void vgroup_delete_update_users(Object *ob, int id)
906 {
907         ExplodeModifierData *emd;
908         ModifierData *md;
909         ParticleSystem *psys;
910         ClothModifierData *clmd;
911         ClothSimSettings *clsim;
912         int a;
913
914         /* these cases don't use names to refer to vertex groups, so when
915          * they get deleted the numbers get out of sync, this corrects that */
916
917         if(ob->soft) {
918                 if(ob->soft->vertgroup == id)
919                         ob->soft->vertgroup= 0;
920                 else if(ob->soft->vertgroup > id)
921                         ob->soft->vertgroup--;
922         }
923
924         for(md=ob->modifiers.first; md; md=md->next) {
925                 if(md->type == eModifierType_Explode) {
926                         emd= (ExplodeModifierData*)md;
927
928                         if(emd->vgroup == id)
929                                 emd->vgroup= 0;
930                         else if(emd->vgroup > id)
931                                 emd->vgroup--;
932                 }
933                 else if(md->type == eModifierType_Cloth) {
934                         clmd= (ClothModifierData*)md;
935                         clsim= clmd->sim_parms;
936
937                         if(clsim) {
938                                 if(clsim->vgroup_mass == id)
939                                         clsim->vgroup_mass= 0;
940                                 else if(clsim->vgroup_mass > id)
941                                         clsim->vgroup_mass--;
942
943                                 if(clsim->vgroup_bend == id)
944                                         clsim->vgroup_bend= 0;
945                                 else if(clsim->vgroup_bend > id)
946                                         clsim->vgroup_bend--;
947
948                                 if(clsim->vgroup_struct == id)
949                                         clsim->vgroup_struct= 0;
950                                 else if(clsim->vgroup_struct > id)
951                                         clsim->vgroup_struct--;
952                         }
953                 }
954         }
955
956         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
957                 for(a=0; a<PSYS_TOT_VG; a++)
958                         if(psys->vgroup[a] == id)
959                                 psys->vgroup[a]= 0;
960                         else if(psys->vgroup[a] > id)
961                                 psys->vgroup[a]--;
962         }
963 }
964
965 static void vgroup_delete_object_mode(Object *ob)
966 {
967         bDeformGroup *dg;
968         MDeformVert *dvert, *dvert_array=NULL;
969         int i, e, dvert_tot=0;
970         
971         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
972         if(!dg)
973                 return;
974         
975         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
976
977         if(dvert_array) {
978                 for(i = 0; i < dvert_tot; i++) {
979                         dvert = dvert_array + i;
980                         if(dvert) {
981                                 if(ED_vgroup_weight_get(dvert, (ob->actdef-1)))
982                                         ED_vgroup_vert_remove(ob, dg, i);
983                         }
984                 }
985
986                 for(i = 0; i < dvert_tot; i++) {
987                         dvert = dvert_array+i;
988                         if(dvert) {
989                                 for(e = 0; e < dvert->totweight; e++) {
990                                         if(dvert->dw[e].def_nr > (ob->actdef-1))
991                                                 dvert->dw[e].def_nr--;
992                                 }
993                         }
994                 }
995         }
996
997         vgroup_delete_update_users(ob, ob->actdef);
998
999         /* Update the active deform index if necessary */
1000         if(ob->actdef == BLI_countlist(&ob->defbase))
1001                 ob->actdef--;
1002   
1003         /* Remove the group */
1004         BLI_freelinkN(&ob->defbase, dg);
1005 }
1006
1007 /* only in editmode */
1008 /* removes from active defgroup, if allverts==0 only selected vertices */
1009 static void vgroup_active_remove_verts(Object *ob, int allverts)
1010 {
1011         EditVert *eve;
1012         MDeformVert *dvert;
1013         MDeformWeight *newdw;
1014         bDeformGroup *dg, *eg;
1015         int     i;
1016
1017         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1018         if(!dg)
1019                 return;
1020
1021         if(ob->type == OB_MESH) {
1022                 Mesh *me= ob->data;
1023                 EditMesh *em = BKE_mesh_get_editmesh(me);
1024
1025                 for(eve=em->verts.first; eve; eve=eve->next){
1026                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1027                 
1028                         if(dvert && dvert->dw && ((eve->f & 1) || allverts)){
1029                                 for(i=0; i<dvert->totweight; i++){
1030                                         /* Find group */
1031                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1032                                         if(eg == dg){
1033                                                 dvert->totweight--;
1034                                                 if(dvert->totweight){
1035                                                         newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1036                                                         
1037                                                         if(dvert->dw){
1038                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1039                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1040                                                                 MEM_freeN(dvert->dw);
1041                                                         }
1042                                                         dvert->dw=newdw;
1043                                                 }
1044                                                 else{
1045                                                         MEM_freeN(dvert->dw);
1046                                                         dvert->dw=NULL;
1047                                                         break;
1048                                                 }
1049                                         }
1050                                 }
1051                         }
1052                 }
1053                 BKE_mesh_end_editmesh(me, em);
1054         }
1055         else if(ob->type == OB_LATTICE) {
1056                 Lattice *lt= vgroup_edit_lattice(ob);
1057                 
1058                 if(lt->dvert) {
1059                         BPoint *bp;
1060                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1061                                 
1062                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1063                                 if(allverts || (bp->f1 & SELECT))
1064                                         ED_vgroup_vert_remove(ob, dg, a);
1065                         }
1066                 }
1067         }
1068 }
1069
1070 static void vgroup_delete_edit_mode(Object *ob)
1071 {
1072         bDeformGroup *defgroup;
1073         int i;
1074
1075         if(!ob->actdef)
1076                 return;
1077
1078         defgroup = BLI_findlink(&ob->defbase, ob->actdef-1);
1079         if(!defgroup)
1080                 return;
1081
1082         /* Make sure that no verts are using this group */
1083         vgroup_active_remove_verts(ob, 1);
1084
1085         /* Make sure that any verts with higher indices are adjusted accordingly */
1086         if(ob->type==OB_MESH) {
1087                 Mesh *me= ob->data;
1088                 EditMesh *em = BKE_mesh_get_editmesh(me);
1089                 EditVert *eve;
1090                 MDeformVert *dvert;
1091                 
1092                 for(eve=em->verts.first; eve; eve=eve->next){
1093                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1094
1095                         if(dvert)
1096                                 for(i=0; i<dvert->totweight; i++)
1097                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
1098                                                 dvert->dw[i].def_nr--;
1099                 }
1100                 BKE_mesh_end_editmesh(me, em);
1101         }
1102         else if(ob->type==OB_LATTICE) {
1103                 Lattice *lt= vgroup_edit_lattice(ob);
1104                 BPoint *bp;
1105                 MDeformVert *dvert= lt->dvert;
1106                 int a, tot;
1107                 
1108                 if(dvert) {
1109                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1110                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1111                                 for(i=0; i<dvert->totweight; i++){
1112                                         if(dvert->dw[i].def_nr > (ob->actdef-1))
1113                                                 dvert->dw[i].def_nr--;
1114                                 }
1115                         }
1116                 }
1117         }
1118
1119         vgroup_delete_update_users(ob, ob->actdef);
1120
1121         /* Update the active deform index if necessary */
1122         if(ob->actdef==BLI_countlist(&ob->defbase))
1123                 ob->actdef--;
1124         
1125         /* Remove the group */
1126         BLI_freelinkN (&ob->defbase, defgroup);
1127         
1128         /* remove all dverts */
1129         if(ob->actdef==0) {
1130                 if(ob->type==OB_MESH) {
1131                         Mesh *me= ob->data;
1132                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1133                         me->dvert= NULL;
1134                 }
1135                 else if(ob->type==OB_LATTICE) {
1136                         Lattice *lt= vgroup_edit_lattice(ob);
1137                         if(lt->dvert) {
1138                                 MEM_freeN(lt->dvert);
1139                                 lt->dvert= NULL;
1140                         }
1141                 }
1142         }
1143 }
1144
1145 static int vgroup_object_in_edit_mode(Object *ob)
1146 {
1147         if(ob->type == OB_MESH)
1148                 return (((Mesh*)ob->data)->edit_mesh != NULL);
1149         else if(ob->type == OB_LATTICE)
1150                 return (((Lattice*)ob->data)->editlatt != NULL);
1151         
1152         return 0;
1153 }
1154
1155 static void vgroup_delete(Object *ob)
1156 {
1157         if(vgroup_object_in_edit_mode(ob))
1158                 vgroup_delete_edit_mode(ob);
1159         else
1160                 vgroup_delete_object_mode(ob);
1161 }
1162
1163 static void vgroup_delete_all(Object *ob)
1164 {
1165         /* Remove all DVerts */
1166         if(ob->type==OB_MESH) {
1167                 Mesh *me= ob->data;
1168                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1169                 me->dvert= NULL;
1170         }
1171         else if(ob->type==OB_LATTICE) {
1172                 Lattice *lt= vgroup_edit_lattice(ob);
1173                 if(lt->dvert) {
1174                         MEM_freeN(lt->dvert);
1175                         lt->dvert= NULL;
1176                 }
1177         }
1178         
1179         /* Remove all DefGroups */
1180         BLI_freelistN(&ob->defbase);
1181         
1182         /* Fix counters/indices */
1183         ob->actdef= 0;
1184 }
1185
1186 /* only in editmode */
1187 static void vgroup_assign_verts(Object *ob, float weight)
1188 {
1189         EditVert *eve;
1190         bDeformGroup *dg, *eg;
1191         MDeformWeight *newdw;
1192         MDeformVert *dvert;
1193         int     i, done;
1194
1195         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1196         if(!dg)
1197                 return;
1198
1199         if(ob->type == OB_MESH) {
1200                 Mesh *me= ob->data;
1201                 EditMesh *em = BKE_mesh_get_editmesh(me);
1202
1203                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1204                         EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT);
1205
1206                 /* Go through the list of editverts and assign them */
1207                 for(eve=em->verts.first; eve; eve=eve->next){
1208                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1209
1210                         if(dvert && (eve->f & 1)){
1211                                 done=0;
1212                                 /* See if this vert already has a reference to this group */
1213                                 /*              If so: Change its weight */
1214                                 done=0;
1215                                 for(i=0; i<dvert->totweight; i++){
1216                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1217                                         /* Find the actual group */
1218                                         if(eg==dg){
1219                                                 dvert->dw[i].weight= weight;
1220                                                 done=1;
1221                                                 break;
1222                                         }
1223                                 }
1224                                 /*              If not: Add the group and set its weight */
1225                                 if(!done){
1226                                         newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1227                                         if(dvert->dw){
1228                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1229                                                 MEM_freeN(dvert->dw);
1230                                         }
1231                                         dvert->dw=newdw;
1232
1233                                         dvert->dw[dvert->totweight].weight= weight;
1234                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1235
1236                                         dvert->totweight++;
1237
1238                                 }
1239                         }
1240                 }
1241                 BKE_mesh_end_editmesh(me, em);
1242         }
1243         else if(ob->type == OB_LATTICE) {
1244                 Lattice *lt= vgroup_edit_lattice(ob);
1245                 BPoint *bp;
1246                 int a, tot;
1247                 
1248                 if(lt->dvert==NULL)
1249                         ED_vgroup_data_create(&lt->id);
1250                 
1251                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1252                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1253                         if(bp->f1 & SELECT)
1254                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1255                 }
1256         }
1257 }
1258
1259 /* only in editmode */
1260 /* removes from all defgroup, if allverts==0 only selected vertices */
1261 static void vgroup_remove_verts(Object *ob, int allverts)
1262 {
1263         int actdef, defCount;
1264         
1265         actdef= ob->actdef;
1266         defCount= BLI_countlist(&ob->defbase);
1267         
1268         if(defCount == 0)
1269                 return;
1270         
1271         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1272          * only operates on the active vgroup. So we iterate through all groups, by changing
1273          * active group index
1274          */
1275         for(ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
1276                 vgroup_active_remove_verts(ob, allverts);
1277                 
1278         ob->actdef= actdef;
1279 }
1280
1281 /********************** vertex group operators *********************/
1282
1283 static int vertex_group_poll(bContext *C)
1284 {
1285         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1286         ID *data= (ob)? ob->data: NULL;
1287         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1288 }
1289
1290 static int vertex_group_poll_edit(bContext *C)
1291 {
1292         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1293         ID *data= (ob)? ob->data: NULL;
1294
1295         if(!(ob && !ob->id.lib && data && !data->lib))
1296                 return 0;
1297
1298         return vgroup_object_in_edit_mode(ob);
1299 }
1300
1301 static int vertex_group_add_exec(bContext *C, wmOperator *op)
1302 {
1303         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1304
1305         ED_vgroup_add(ob);
1306         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1307         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1308         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1309         
1310         return OPERATOR_FINISHED;
1311 }
1312
1313 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
1314 {
1315         /* identifiers */
1316         ot->name= "Add Vertex Group";
1317         ot->idname= "OBJECT_OT_vertex_group_add";
1318         
1319         /* api callbacks */
1320         ot->poll= vertex_group_poll;
1321         ot->exec= vertex_group_add_exec;
1322
1323         /* flags */
1324         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1325 }
1326
1327 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1328 {
1329         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1330
1331         if(RNA_boolean_get(op->ptr, "all"))
1332                 vgroup_delete_all(ob);
1333         else
1334                 vgroup_delete(ob);
1335
1336         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1337         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1338         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1339         
1340         return OPERATOR_FINISHED;
1341 }
1342
1343 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1344 {
1345         /* identifiers */
1346         ot->name= "Remove Vertex Group";
1347         ot->idname= "OBJECT_OT_vertex_group_remove";
1348         
1349         /* api callbacks */
1350         ot->poll= vertex_group_poll;
1351         ot->exec= vertex_group_remove_exec;
1352
1353         /* flags */
1354         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1355
1356         /* properties */
1357         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1358 }
1359
1360 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1361 {
1362         ToolSettings *ts= CTX_data_tool_settings(C);
1363         Object *ob= CTX_data_edit_object(C);
1364
1365         if(RNA_boolean_get(op->ptr, "new"))
1366                 ED_vgroup_add(ob);
1367
1368         vgroup_assign_verts(ob, ts->vgroup_weight);
1369         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1370         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1371         
1372         return OPERATOR_FINISHED;
1373 }
1374
1375 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1376 {
1377         /* identifiers */
1378         ot->name= "Assign Vertex Group";
1379         ot->idname= "OBJECT_OT_vertex_group_assign";
1380         
1381         /* api callbacks */
1382         ot->poll= vertex_group_poll_edit;
1383         ot->exec= vertex_group_assign_exec;
1384
1385         /* flags */
1386         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1387
1388         /* properties */
1389         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1390 }
1391
1392 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1393 {
1394         Object *ob= CTX_data_edit_object(C);
1395
1396         vgroup_remove_verts(ob, 0);
1397         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1398         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1399
1400         return OPERATOR_FINISHED;
1401 }
1402
1403 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1404 {
1405         /* identifiers */
1406         ot->name= "Remove from Vertex Group";
1407         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1408
1409         /* api callbacks */
1410         ot->poll= vertex_group_poll_edit;
1411         ot->exec= vertex_group_remove_from_exec;
1412
1413         /* flags */
1414         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1415
1416         /* properties */
1417         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1418 }
1419
1420 static int vertex_group_select_exec(bContext *C, wmOperator *op)
1421 {
1422         Object *ob= CTX_data_edit_object(C);
1423
1424         if(!ob || ob->id.lib)
1425                 return OPERATOR_CANCELLED;
1426
1427         vgroup_select_verts(ob, 1);
1428         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1429
1430         return OPERATOR_FINISHED;
1431 }
1432
1433 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1434 {
1435         /* identifiers */
1436         ot->name= "Select Vertex Group";
1437         ot->idname= "OBJECT_OT_vertex_group_select";
1438
1439         /* api callbacks */
1440         ot->poll= vertex_group_poll_edit;
1441         ot->exec= vertex_group_select_exec;
1442
1443         /* flags */
1444         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1445 }
1446
1447 static int vertex_group_deselect_exec(bContext *C, wmOperator *op)
1448 {
1449         Object *ob= CTX_data_edit_object(C);
1450
1451         vgroup_select_verts(ob, 0);
1452         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1453
1454         return OPERATOR_FINISHED;
1455 }
1456
1457 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1458 {
1459         /* identifiers */
1460         ot->name= "Deselect Vertex Group";
1461         ot->idname= "OBJECT_OT_vertex_group_deselect";
1462
1463         /* api callbacks */
1464         ot->poll= vertex_group_poll_edit;
1465         ot->exec= vertex_group_deselect_exec;
1466
1467         /* flags */
1468         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1469 }
1470
1471 static int vertex_group_copy_exec(bContext *C, wmOperator *op)
1472 {
1473         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1474
1475         vgroup_duplicate(ob);
1476         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1477         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1478         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1479
1480         return OPERATOR_FINISHED;
1481 }
1482
1483 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1484 {
1485         /* identifiers */
1486         ot->name= "Copy Vertex Group";
1487         ot->idname= "OBJECT_OT_vertex_group_copy";
1488
1489         /* api callbacks */
1490         ot->poll= vertex_group_poll;
1491         ot->exec= vertex_group_copy_exec;
1492
1493         /* flags */
1494         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1495 }
1496
1497 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
1498 {
1499         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1500         
1501         float offset= RNA_float_get(op->ptr,"offset");
1502         float gain= RNA_float_get(op->ptr,"gain");
1503         
1504         vgroup_levels(ob, offset, gain);
1505         
1506         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1507         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1508         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1509         
1510         return OPERATOR_FINISHED;
1511 }
1512
1513 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
1514 {
1515         /* identifiers */
1516         ot->name= "Vertex Group Levels";
1517         ot->idname= "OBJECT_OT_vertex_group_levels";
1518         
1519         /* api callbacks */
1520         ot->poll= vertex_group_poll;
1521         ot->exec= vertex_group_levels_exec;
1522         
1523         /* flags */
1524         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1525         
1526         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
1527         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
1528 }
1529
1530 static int vertex_group_normalize_exec(bContext *C, wmOperator *op)
1531 {
1532         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1533
1534         vgroup_normalize(ob);
1535
1536         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1537         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1538         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1539
1540         return OPERATOR_FINISHED;
1541 }
1542
1543 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
1544 {
1545         /* identifiers */
1546         ot->name= "Normalize Vertex Group";
1547         ot->idname= "OBJECT_OT_vertex_group_normalize";
1548
1549         /* api callbacks */
1550         ot->poll= vertex_group_poll;
1551         ot->exec= vertex_group_normalize_exec;
1552
1553         /* flags */
1554         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1555 }
1556
1557 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
1558 {
1559         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1560         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
1561
1562         vgroup_normalize_all(ob, lock_active);
1563
1564         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1565         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1566         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1567
1568         return OPERATOR_FINISHED;
1569 }
1570
1571 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
1572 {
1573         /* identifiers */
1574         ot->name= "Normalize All Vertex Groups";
1575         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
1576
1577         /* api callbacks */
1578         ot->poll= vertex_group_poll;
1579         ot->exec= vertex_group_normalize_all_exec;
1580
1581         /* flags */
1582         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1583
1584         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
1585 }
1586
1587 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
1588 {
1589         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1590         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
1591         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
1592
1593         vgroup_invert(ob, auto_assign, auto_remove);
1594         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1595         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1596         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1597
1598         return OPERATOR_FINISHED;
1599 }
1600
1601 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
1602 {
1603         /* identifiers */
1604         ot->name= "Invert Vertex Group";
1605         ot->idname= "OBJECT_OT_vertex_group_invert";
1606
1607         /* api callbacks */
1608         ot->poll= vertex_group_poll;
1609         ot->exec= vertex_group_invert_exec;
1610
1611         /* flags */
1612         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1613
1614         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
1615         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
1616 }
1617
1618
1619 static int vertex_group_blend_exec(bContext *C, wmOperator *op)
1620 {
1621         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1622
1623         vgroup_blend(ob);
1624
1625         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1626         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1627         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1628
1629         return OPERATOR_FINISHED;
1630 }
1631
1632 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
1633 {
1634         /* identifiers */
1635         ot->name= "Blend Vertex Group";
1636         ot->idname= "OBJECT_OT_vertex_group_blend";
1637         ot->description= "";
1638
1639         /* api callbacks */
1640         ot->poll= vertex_group_poll;
1641         ot->exec= vertex_group_blend_exec;
1642
1643         /* flags */
1644         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1645 }
1646
1647
1648 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
1649 {
1650         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1651
1652         float limit= RNA_float_get(op->ptr,"limit");
1653         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
1654         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
1655
1656         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
1657         else                    vgroup_clean(ob, limit, keep_single);
1658
1659         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1660         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1661         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1662
1663         return OPERATOR_FINISHED;
1664 }
1665
1666 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
1667 {
1668         /* identifiers */
1669         ot->name= "Clean Vertex Group";
1670         ot->idname= "OBJECT_OT_vertex_group_clean";
1671         ot->description= "Remove Vertex Group assignments which aren't required.";
1672
1673         /* api callbacks */
1674         ot->poll= vertex_group_poll;
1675         ot->exec= vertex_group_clean_exec;
1676
1677         /* flags */
1678         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1679
1680         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
1681         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
1682         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
1683 }
1684
1685
1686 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
1687 {
1688         Scene *scene= CTX_data_scene(C);
1689         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1690         Base *base;
1691         int retval= OPERATOR_CANCELLED;
1692
1693         for(base=scene->base.first; base; base= base->next) {
1694                 if(base->object->type==ob->type) {
1695                         if(base->object!=ob && base->object->data==ob->data) {
1696                                 BLI_freelistN(&base->object->defbase);
1697                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1698                                 base->object->actdef= ob->actdef;
1699
1700                                 DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
1701                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1702                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1703
1704                                 retval = OPERATOR_FINISHED;
1705                         }
1706                 }
1707         }
1708
1709         return retval;
1710 }
1711
1712 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1713 {
1714         /* identifiers */
1715         ot->name= "Copy Vertex Group to Linked";
1716         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1717         ot->description= "Copy Vertex Groups to all users of the same Geometry data.";
1718
1719         /* api callbacks */
1720         ot->poll= vertex_group_poll;
1721         ot->exec= vertex_group_copy_to_linked_exec;
1722
1723         /* flags */
1724         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1725 }
1726
1727 static EnumPropertyItem vgroup_items[]= {
1728         {0, NULL, 0, NULL, NULL}};
1729
1730 static int set_active_group_exec(bContext *C, wmOperator *op)
1731 {
1732         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1733         int nr= RNA_enum_get(op->ptr, "group");
1734
1735         ob->actdef= nr+1;
1736
1737         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1738         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1739
1740         return OPERATOR_FINISHED;
1741 }
1742
1743 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *ptr, int *free)
1744 {       
1745         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1746         EnumPropertyItem tmp = {0, "", 0, "", ""};
1747         EnumPropertyItem *item= NULL;
1748         bDeformGroup *def;
1749         int a, totitem= 0;
1750         
1751         if(!ob)
1752                 return vgroup_items;
1753         
1754         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
1755                 tmp.value= a;
1756                 tmp.identifier= def->name;
1757                 tmp.name= def->name;
1758                 RNA_enum_item_add(&item, &totitem, &tmp);
1759         }
1760
1761         RNA_enum_item_end(&item, &totitem);
1762         *free= 1;
1763
1764         return item;
1765 }
1766
1767 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
1768 {
1769         PropertyRNA *prop;
1770
1771         /* identifiers */
1772         ot->name= "Set Active Vertex Group";
1773         ot->idname= "OBJECT_OT_vertex_group_set_active";
1774         ot->description= "Set the active vertex group.";
1775
1776         /* api callbacks */
1777         ot->poll= vertex_group_poll;
1778         ot->exec= set_active_group_exec;
1779         ot->invoke= WM_menu_invoke;
1780
1781         /* flags */
1782         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1783
1784         /* properties */
1785         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
1786         RNA_def_enum_funcs(prop, vgroup_itemf);
1787 }
1788
1789 static int vertex_group_menu_exec(bContext *C, wmOperator *op)
1790 {
1791         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1792         uiPopupMenu *pup;
1793         uiLayout *layout;
1794
1795         pup= uiPupMenuBegin(C, "Vertex Groups", 0);
1796         layout= uiPupMenuLayout(pup);
1797         uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
1798
1799         if(vgroup_object_in_edit_mode(ob)) {
1800                 uiItemBooleanO(layout, "Assign to New Group", 0, "OBJECT_OT_vertex_group_assign", "new", 1);
1801
1802                 if(BLI_countlist(&ob->defbase) && ob->actdef) {
1803                         uiItemO(layout, "Assign to Group", 0, "OBJECT_OT_vertex_group_assign");
1804                         uiItemO(layout, "Remove from Group", 0, "OBJECT_OT_vertex_group_remove_from");
1805                         uiItemBooleanO(layout, "Remove from All", 0, "OBJECT_OT_vertex_group_remove_from", "all", 1);
1806                 }
1807         }
1808
1809         if(BLI_countlist(&ob->defbase) && ob->actdef) {
1810                 if(vgroup_object_in_edit_mode(ob))
1811                         uiItemS(layout);
1812
1813                 uiItemMenuEnumO(layout, "Set Active Group", 0, "OBJECT_OT_vertex_group_set_active", "group");
1814                 uiItemO(layout, "Remove Group", 0, "OBJECT_OT_vertex_group_remove");
1815                 uiItemBooleanO(layout, "Remove All Groups", 0, "OBJECT_OT_vertex_group_remove", "all", 1);
1816         }
1817
1818         uiPupMenuEnd(C, pup);
1819
1820         return OPERATOR_FINISHED;
1821 }
1822
1823 void OBJECT_OT_vertex_group_menu(wmOperatorType *ot)
1824 {
1825         /* identifiers */
1826         ot->name= "Vertex Group Menu";
1827         ot->idname= "OBJECT_OT_vertex_group_menu";
1828         ot->description= "Menu showing the operators available for editing Vertex Groups";
1829
1830         /* api callbacks */
1831         ot->poll= vertex_group_poll;
1832         ot->exec= vertex_group_menu_exec;
1833 }
1834