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