update glew from 1.6 to 1.7:
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/editors/object/object_vgroup.c
31  *  \ingroup edobj
32  */
33
34
35 #include <string.h>
36 #include <stddef.h>
37 #include <math.h>
38 #include <assert.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "DNA_cloth_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_lattice_types.h"
45 #include "DNA_meshdata_types.h"
46 #include "DNA_modifier_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_object_force.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_particle_types.h"
51
52 #include "BLI_blenlib.h"
53 #include "BLI_editVert.h"
54 #include "BLI_utildefines.h"
55
56 #include "BKE_context.h"
57 #include "BKE_customdata.h"
58 #include "BKE_deform.h"
59 #include "BKE_depsgraph.h"
60 #include "BKE_global.h"
61 #include "BKE_mesh.h"
62 #include "BKE_report.h"
63
64 #include "RNA_access.h"
65 #include "RNA_define.h"
66
67 #include "WM_api.h"
68 #include "WM_types.h"
69
70 #include "ED_mesh.h"
71
72 #include "UI_resources.h"
73
74 #include "object_intern.h"
75
76 /************************ Exported Functions **********************/
77 static void vgroup_remap_update_users(Object *ob, int *map);
78 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
79 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
80 static void vgroup_delete_all(Object *ob);
81
82 static Lattice *vgroup_edit_lattice(Object *ob)
83 {
84         Lattice *lt= ob->data;
85         BLI_assert(ob->type==OB_LATTICE);
86         return (lt->editlatt)? lt->editlatt->latt: lt;
87 }
88
89 int ED_vgroup_object_is_edit_mode(Object *ob)
90 {
91         if(ob->type == OB_MESH)
92                 return (((Mesh*)ob->data)->edit_mesh != NULL);
93         else if(ob->type == OB_LATTICE)
94                 return (((Lattice*)ob->data)->editlatt != NULL);
95
96         return 0;
97 }
98
99 bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
100 {
101         bDeformGroup *defgroup;
102         
103         if(!ob || !ELEM(ob->type, OB_MESH, OB_LATTICE))
104                 return NULL;
105         
106         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
107
108         BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
109
110         BLI_addtail(&ob->defbase, defgroup);
111         defgroup_unique_name(defgroup, ob);
112
113         ob->actdef = BLI_countlist(&ob->defbase);
114
115         return defgroup;
116 }
117
118 bDeformGroup *ED_vgroup_add(Object *ob) 
119 {
120         return ED_vgroup_add_name(ob, "Group");
121 }
122
123 void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) 
124 {
125         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
126
127         while (dg) {
128                 if (dg == defgroup)
129                         break;
130                 dg = dg->next;
131         }
132
133         if (dg == NULL)
134                 return;
135
136         if(ED_vgroup_object_is_edit_mode(ob))
137                 vgroup_delete_edit_mode(ob, dg);
138         else
139                 vgroup_delete_object_mode(ob, dg);
140 }
141
142 int ED_vgroup_data_create(ID *id)
143 {
144         /* create deform verts */
145
146         if(GS(id->name)==ID_ME) {
147                 Mesh *me= (Mesh *)id;
148                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
149                 return TRUE;
150         }
151         else if(GS(id->name)==ID_LT) {
152                 Lattice *lt= (Lattice *)id;
153                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
154                 return TRUE;
155         }
156         else {
157                 return FALSE;
158         }
159 }
160
161 static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot)
162 {
163         *dvert_tot = 0;
164         *dvert_arr = NULL;
165
166         if(id) {
167                 switch(GS(id->name)) {
168                         case ID_ME:
169                         {
170                                 Mesh *me = (Mesh *)id;
171
172                                 if(me->edit_mesh) {
173                                         EditMesh *em = me->edit_mesh;
174                                         EditVert *eve;
175                                         int i;
176
177                                         if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
178                                                 return 0;
179                                         }
180
181                                         i= BLI_countlist(&em->verts);
182
183                                         *dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me");
184                                         *dvert_tot = i;
185
186                                         i = 0;
187                                         for (eve=em->verts.first; eve; eve=eve->next, i++) {
188                                                 (*dvert_arr)[i] = CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
189                                         }
190
191                                         return 1;
192                                 }
193                                 else if(me->dvert) {
194                                         int i;
195
196                                         *dvert_tot= me->totvert;
197                                         *dvert_arr= MEM_mallocN(sizeof(void*)*me->totvert, "vgroup parray from me");
198
199                                         for (i=0; i<me->totvert; i++) {
200                                                 (*dvert_arr)[i] = me->dvert + i;
201                                         }
202
203                                         return 1;
204                                 }
205                                 else {
206                                         return 0;
207                                 }
208                         }
209                         case ID_LT:
210                         {
211                                 int i=0;
212
213                                 Lattice *lt= (Lattice *)id;
214                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
215
216                                 if(lt->dvert) {
217                                         *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
218                                         *dvert_arr= MEM_mallocN(sizeof(void*)*(*dvert_tot), "vgroup parray from me");
219
220                                         for (i=0; i<*dvert_tot; i++) {
221                                                 (*dvert_arr)[i] = lt->dvert + i;
222                                         }
223
224                                         return 1;
225                                 }
226                                 else {
227                                         return 0;
228                                 }
229                         }
230                 }
231         }
232
233         return 0;
234 }
235
236 /* returns true if the id type supports weights */
237 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
238 {
239         if(id) {
240                 switch(GS(id->name)) {
241                         case ID_ME:
242                         {
243                                 Mesh *me = (Mesh *)id;
244                                 *dvert_arr= me->dvert;
245                                 *dvert_tot= me->totvert;
246                                 return TRUE;
247                         }
248                         case ID_LT:
249                         {
250                                 Lattice *lt= (Lattice *)id;
251                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
252                                 *dvert_arr= lt->dvert;
253                                 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
254                                 return TRUE;
255                         }
256                 }
257         }
258
259         *dvert_arr= NULL;
260         *dvert_tot= 0;
261         return FALSE;
262 }
263
264 /* matching index only */
265 int ED_vgroup_copy_array(Object *ob, Object *ob_from)
266 {
267         MDeformVert **dvert_array_from, **dvf;
268         MDeformVert **dvert_array, **dv;
269         int dvert_tot_from;
270         int dvert_tot;
271         int i;
272         int totdef_from= BLI_countlist(&ob_from->defbase);
273         int totdef= BLI_countlist(&ob->defbase);
274         short new_vgroup= FALSE;
275
276         ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from);
277         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
278
279         if((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
280                 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
281                 new_vgroup= TRUE;
282         }
283
284         if(ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) {
285                 if (dvert_array) MEM_freeN(dvert_array);
286                 if (dvert_array_from) MEM_freeN(dvert_array_from);
287
288                 if(new_vgroup == TRUE) {
289                         /* free the newly added vgroup since it wasn't compatible */
290                         vgroup_delete_all(ob);
291                 }
292                 return 0;
293         }
294
295         /* do the copy */
296         BLI_freelistN(&ob->defbase);
297         BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
298         ob->actdef= ob_from->actdef;
299
300         if(totdef_from < totdef) {
301                 /* correct vgroup indices because the number of vgroups is being reduced. */
302                 int *remap= MEM_mallocN(sizeof(int) * (totdef + 1), "ED_vgroup_copy_array");
303                 for(i=0; i<=totdef_from; i++) remap[i]= i;
304                 for(; i<=totdef; i++) remap[i]= 0; /* can't use these, so disable */
305
306                 vgroup_remap_update_users(ob, remap);
307                 MEM_freeN(remap);
308         }
309
310         dvf= dvert_array_from;
311         dv= dvert_array;
312
313         for(i=0; i<dvert_tot; i++, dvf++, dv++) {
314                 if((*dv)->dw)
315                         MEM_freeN((*dv)->dw);
316
317                 *(*dv)= *(*dvf);
318
319                 if((*dv)->dw)
320                         (*dv)->dw= MEM_dupallocN((*dv)->dw);
321         }
322
323         MEM_freeN(dvert_array);
324         MEM_freeN(dvert_array_from);
325
326         return 1;
327 }
328
329 /* for mesh in object mode
330    lattice can be in editmode */
331 static void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
332 {
333         /* This routine removes the vertex from the deform
334          * group with number def_nr.
335          *
336          * This routine is meant to be fast, so it is the
337          * responsibility of the calling routine to:
338          *   a) test whether ob is non-NULL
339          *   b) test whether ob is a mesh
340          *   c) calculate def_nr
341          */
342
343         MDeformWeight *newdw;
344         MDeformVert *dvert= NULL;
345         int i, tot;
346
347         /* get the deform vertices corresponding to the
348          * vertnum
349          */
350         ED_vgroup_give_array(ob->data, &dvert, &tot);
351
352         if(dvert==NULL)
353                 return;
354         
355         dvert+= vertnum;
356
357         /* for all of the deform weights in the
358          * deform vert
359          */
360         for(i=dvert->totweight - 1 ; i>=0 ; i--){
361
362                 /* if the def_nr is the same as the one
363                  * for our weight group then remove it
364                  * from this deform vert.
365                  */
366                 if(dvert->dw[i].def_nr == def_nr) {
367                         dvert->totweight--;
368
369                         /* if there are still other deform weights
370                          * attached to this vert then remove this
371                          * deform weight, and reshuffle the others
372                          */
373                         if(dvert->totweight) {
374                                 newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), 
375                                                                          "deformWeight");
376                                 if(dvert->dw){
377                                         memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
378                                         memcpy(newdw+i, dvert->dw+i+1, 
379                                                         sizeof(MDeformWeight)*(dvert->totweight-i));
380                                         MEM_freeN(dvert->dw);
381                                 }
382                                 dvert->dw=newdw;
383                         }
384                         /* if there are no other deform weights
385                          * left then just remove the deform weight
386                          */
387                         else {
388                                 MEM_freeN(dvert->dw);
389                                 dvert->dw = NULL;
390                                 break;
391                         }
392                 }
393         }
394
395 }
396
397 /* for Mesh in Object mode */
398 /* allows editmode for Lattice */
399 static void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, int assignmode)
400 {
401         /* add the vert to the deform group with the
402          * specified number
403          */
404         MDeformVert *dv= NULL;
405         MDeformWeight *newdw;
406         int     i, tot;
407
408         /* get the vert */
409         ED_vgroup_give_array(ob->data, &dv, &tot);
410         
411         if(dv==NULL)
412                 return;
413         
414         /* check that vertnum is valid before trying to get the relevant dvert */
415         if ((vertnum < 0) || (vertnum >= tot))
416                 return;
417         else
418                 dv += vertnum;
419
420         /* Lets first check to see if this vert is
421          * already in the weight group -- if so
422          * lets update it
423          */
424         for(i=0; i<dv->totweight; i++){
425                 
426                 /* if this weight cooresponds to the
427                  * deform group, then add it using
428                  * the assign mode provided
429                  */
430                 if(dv->dw[i].def_nr == def_nr){
431                         
432                         switch(assignmode) {
433                         case WEIGHT_REPLACE:
434                                 dv->dw[i].weight=weight;
435                                 break;
436                         case WEIGHT_ADD:
437                                 dv->dw[i].weight+=weight;
438                                 if(dv->dw[i].weight >= 1.0f)
439                                         dv->dw[i].weight = 1.0f;
440                                 break;
441                         case WEIGHT_SUBTRACT:
442                                 dv->dw[i].weight-=weight;
443                                 /* if the weight is zero or less then
444                                  * remove the vert from the deform group
445                                  */
446                                 if(dv->dw[i].weight <= 0.0f)
447                                         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
448                                 break;
449                         }
450                         return;
451                 }
452         }
453
454         /* if the vert wasn't in the deform group then
455          * we must take a different form of action ...
456          */
457
458         switch(assignmode) {
459         case WEIGHT_SUBTRACT:
460                 /* if we are subtracting then we don't
461                  * need to do anything
462                  */
463                 return;
464
465         case WEIGHT_REPLACE:
466         case WEIGHT_ADD:
467                 /* if we are doing an additive assignment, then
468                  * we need to create the deform weight
469                  */
470                 newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), 
471                                                          "deformWeight");
472                 if(dv->dw){
473                         memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
474                         MEM_freeN(dv->dw);
475                 }
476                 dv->dw=newdw;
477
478                 dv->dw[dv->totweight].weight=weight;
479                 dv->dw[dv->totweight].def_nr=def_nr;
480
481                 dv->totweight++;
482                 break;
483         }
484 }
485
486 /* called while not in editmode */
487 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
488 {
489         /* add the vert to the deform group with the
490          * specified assign mode
491          */
492         int     def_nr;
493
494         MDeformVert *dv= NULL;
495         int tot;
496
497         /* get the deform group number, exit if
498          * it can't be found
499          */
500         def_nr = defgroup_find_index(ob, dg);
501         if(def_nr < 0) return;
502
503         /* if there's no deform verts then create some,
504          */
505         if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
506                 ED_vgroup_data_create(ob->data);
507
508         /* call another function to do the work
509          */
510         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
511 }
512
513 /* mesh object mode, lattice can be in editmode */
514 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
515 {
516         /* This routine removes the vertex from the specified
517          * deform group.
518          */
519         const int def_nr= defgroup_find_index(ob, dg);
520         if(def_nr < 0)
521                 return;
522
523         ED_vgroup_nr_vert_remove(ob, def_nr, vertnum);
524 }
525
526 static float get_vert_def_nr(Object *ob, int def_nr, int vertnum)
527 {
528         MDeformVert *dvert= NULL;
529         EditVert *eve;
530         Mesh *me;
531         int i;
532
533         /* get the deform vertices corresponding to the vertnum */
534         if(ob->type==OB_MESH) {
535                 me= ob->data;
536
537                 if(me->edit_mesh) {
538                         eve= BLI_findlink(&me->edit_mesh->verts, vertnum);
539                         if(!eve) {
540                                 return 0.0f;
541                         }
542                         dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT);
543                         vertnum= 0;
544                 }
545                 else {
546                         if(vertnum >= me->totvert) {
547                                 return 0.0f;
548                         }
549                         dvert = me->dvert;
550                 }
551         }
552         else if(ob->type==OB_LATTICE) {
553                 Lattice *lt= vgroup_edit_lattice(ob);
554
555                 if(lt->dvert) {
556                         if(vertnum >= lt->pntsu*lt->pntsv*lt->pntsw) {
557                                 return 0.0f;
558                         }
559                         dvert = lt->dvert;
560                 }
561         }
562         
563         if(dvert==NULL)
564                 return -1;
565         
566         dvert += vertnum;
567         
568         for(i=dvert->totweight-1 ; i>=0 ; i--)
569                 if(dvert->dw[i].def_nr == def_nr)
570                         return dvert->dw[i].weight;
571
572         return -1;
573 }
574
575 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
576 {
577         int def_nr;
578
579         if(!ob) return -1;
580
581         def_nr = defgroup_find_index(ob, dg);
582         if(def_nr < 0) return -1;
583
584         return get_vert_def_nr(ob, def_nr, vertnum);
585 }
586
587 void ED_vgroup_select_by_name(Object *ob, const char *name)
588 {       /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */
589         ob->actdef= defgroup_name_index(ob, name) + 1;
590 }
591
592 /********************** Operator Implementations *********************/
593
594 /* only in editmode */
595 static void vgroup_select_verts(Object *ob, int select)
596 {
597         EditVert *eve;
598         MDeformVert *dvert;
599         int i;
600
601         if(ob->type == OB_MESH) {
602                 Mesh *me= ob->data;
603                 EditMesh *em = BKE_mesh_get_editmesh(me);
604
605                 for(eve=em->verts.first; eve; eve=eve->next){
606                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
607
608                         if(dvert && dvert->totweight){
609                                 for(i=0; i<dvert->totweight; i++){
610                                         if(dvert->dw[i].def_nr == (ob->actdef-1)){
611                                                 if(!eve->h) {
612                                                         if(select) eve->f |= SELECT;
613                                                         else eve->f &= ~SELECT;
614                                                 }
615                                                 break;
616                                         }
617                                 }
618                         }
619                 }
620                 /* this has to be called, because this function operates on vertices only */
621                 if(select) EM_select_flush(em); // vertices to edges/faces
622                 else EM_deselect_flush(em);
623
624                 BKE_mesh_end_editmesh(me, em);
625         }
626         else if(ob->type == OB_LATTICE) {
627                 Lattice *lt= vgroup_edit_lattice(ob);
628                 
629                 if(lt->dvert) {
630                         BPoint *bp;
631                         int a, tot;
632                         
633                         dvert= lt->dvert;
634
635                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
636                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
637                                 for(i=0; i<dvert->totweight; i++){
638                                         if(dvert->dw[i].def_nr == (ob->actdef-1)) {
639                                                 if(select) bp->f1 |= SELECT;
640                                                 else bp->f1 &= ~SELECT;
641                                                 
642                                                 break;
643                                         }
644                                 }
645                         }
646                 }
647         }
648 }
649
650 static void vgroup_duplicate(Object *ob)
651 {
652         bDeformGroup *dg, *cdg;
653         char name[sizeof(dg->name)];
654         MDeformWeight *org, *cpy;
655         MDeformVert *dvert, **dvert_array=NULL;
656         int i, idg, icdg, dvert_tot=0;
657
658         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
659         if(!dg)
660                 return;
661         
662         if(!strstr(dg->name, "_copy")) {
663                 BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
664         }
665         else {
666                 BLI_snprintf(name, sizeof(name), "%s", dg->name);
667         }
668
669         cdg = defgroup_duplicate(dg);
670         strcpy(cdg->name, name);
671         defgroup_unique_name(cdg, ob);
672
673         BLI_addtail(&ob->defbase, cdg);
674
675         idg = (ob->actdef-1);
676         ob->actdef = BLI_countlist(&ob->defbase);
677         icdg = (ob->actdef-1);
678
679         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
680         
681         if(!dvert_array)
682                 return;
683
684         for(i = 0; i < dvert_tot; i++) {
685                 dvert = dvert_array[i];
686                 org = defvert_find_index(dvert, idg);
687                 if(org) {
688                         float weight = org->weight;
689                         /* defvert_verify_index re-allocs org so need to store the weight first */
690                         cpy = defvert_verify_index(dvert, icdg);
691                         cpy->weight = weight;
692                 }
693         }
694
695         MEM_freeN(dvert_array);
696 }
697
698 static void vgroup_normalize(Object *ob)
699 {
700         bDeformGroup *dg;
701         MDeformWeight *dw;
702         MDeformVert *dvert, **dvert_array=NULL;
703         int i, def_nr, dvert_tot=0;
704
705         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
706
707         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
708
709         if(dg) {
710                 float weight_max = 0.0f;
711
712                 def_nr= ob->actdef-1;
713
714                 for(i = 0; i < dvert_tot; i++) {
715                         dvert = dvert_array[i];
716                         dw = defvert_find_index(dvert, def_nr);
717                         if(dw) {
718                                 weight_max = MAX2(dw->weight, weight_max);
719                         }
720                 }
721
722                 if(weight_max > 0.0f) {
723                         for(i = 0; i < dvert_tot; i++) {
724                                 dvert = dvert_array[i];
725                                 dw = defvert_find_index(dvert, def_nr);
726                                 if(dw) {
727                                         dw->weight /= weight_max;
728                                         
729                                         /* incase of division errors with very low weights */
730                                         CLAMP(dw->weight, 0.0f, 1.0f);
731                                 }
732                         }
733                 }
734         }
735
736         if (dvert_array) MEM_freeN(dvert_array);
737 }
738
739 static void vgroup_levels(Object *ob, float offset, float gain)
740 {
741         bDeformGroup *dg;
742         MDeformWeight *dw;
743         MDeformVert *dvert, **dvert_array=NULL;
744         int i, def_nr, dvert_tot=0;
745         
746         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
747         
748         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
749         
750         if(dg) {
751                 def_nr= ob->actdef-1;
752                 
753                 for(i = 0; i < dvert_tot; i++) {
754                         dvert = dvert_array[i];
755                         dw = defvert_find_index(dvert, def_nr);
756                         if(dw) {
757                                 dw->weight = gain * (dw->weight + offset);
758                                 
759                                 CLAMP(dw->weight, 0.0f, 1.0f);
760                         }
761                 }
762         }
763
764         if (dvert_array) MEM_freeN(dvert_array);
765 }
766
767 /* TODO - select between groups */
768 static void vgroup_normalize_all(Object *ob, int lock_active)
769 {
770         MDeformWeight *dw, *dw_act;
771         MDeformVert *dvert, **dvert_array=NULL;
772         int i, dvert_tot=0;
773         float tot_weight;
774
775         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
776
777         if(dvert_array) {
778                 if(lock_active) {
779                         int def_nr= ob->actdef-1;
780
781                         for(i = 0; i < dvert_tot; i++) {
782                                 float lock_iweight= 1.0f;
783                                 int j;
784
785                                 tot_weight= 0.0f;
786                                 dw_act= NULL;
787                                 dvert = dvert_array[i];
788
789                                 j= dvert->totweight;
790                                 while(j--) {
791                                         dw= dvert->dw + j;
792
793                                         if(dw->def_nr==def_nr) {
794                                                 dw_act= dw;
795                                                 lock_iweight = (1.0f - dw_act->weight);
796                                         }
797                                         else {
798                                                 tot_weight += dw->weight;
799                                         }
800                                 }
801
802                                 if(tot_weight) {
803                                         j= dvert->totweight;
804                                         while(j--) {
805                                                 dw= dvert->dw + j;
806                                                 if(dw == dw_act) {
807                                                         if (dvert->totweight==1) {
808                                                                 dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
809                                                         }
810                                                 } else {
811                                                         if(dw->weight > 0.0f)
812                                                                 dw->weight = (dw->weight / tot_weight) * lock_iweight;
813                                                 }
814
815                                                 /* incase of division errors with very low weights */
816                                                 CLAMP(dw->weight, 0.0f, 1.0f);
817                                         }
818                                 }
819                         }
820                 }
821                 else {
822                         for(i = 0; i < dvert_tot; i++) {
823                                 int j;
824                                 tot_weight= 0.0f;
825                                 dvert = dvert_array[i];
826
827                                 j= dvert->totweight;
828                                 while(j--) {
829                                         dw= dvert->dw + j;
830                                         tot_weight += dw->weight;
831                                 }
832
833                                 if(tot_weight) {
834                                         j= dvert->totweight;
835                                         while(j--) {
836                                                 dw= dvert->dw + j;
837                                                 dw->weight /= tot_weight;
838
839                                                 /* incase of division errors with very low weights */
840                                                 CLAMP(dw->weight, 0.0f, 1.0f);
841                                         }
842                                 }
843                         }
844                 }
845         }
846
847         if (dvert_array) MEM_freeN(dvert_array);
848 }
849
850
851 static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
852 {
853         bDeformGroup *dg;
854         MDeformWeight *dw;
855         MDeformVert *dvert, **dvert_array=NULL;
856         int i, def_nr, dvert_tot=0;
857
858         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
859
860         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
861
862         if(dg) {
863                 def_nr= ob->actdef-1;
864
865
866                 for(i = 0; i < dvert_tot; i++) {
867                         dvert = dvert_array[i];
868
869                         if(auto_assign) {
870                                 dw= defvert_verify_index(dvert, def_nr);
871                         } else {
872                                 dw= defvert_find_index(dvert, def_nr);
873                         }
874
875                         if(dw) {
876                                 dw->weight = 1.0f-dw->weight;
877
878                                 if(auto_remove && dw->weight <= 0.0f) {
879                                         /* could have a faster function for this */
880                                         ED_vgroup_nr_vert_remove(ob, def_nr, i);
881                                 }
882                         }
883                 }
884         }
885
886         if (dvert_array) MEM_freeN(dvert_array);
887 }
888
889 static void vgroup_blend(Object *ob)
890 {
891         bDeformGroup *dg;
892         MDeformWeight *dw;
893         MDeformVert *dvert_array=NULL, *dvert;
894         int i, def_nr, dvert_tot=0;
895
896         EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)ob->data));
897         // ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
898
899         if(em==NULL)
900                 return;
901
902         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
903
904         if(dg) {
905                 int sel1, sel2;
906                 int i1, i2;
907
908                 EditEdge *eed;
909                 EditVert *eve;
910                 float *vg_weights;
911                 float *vg_users;
912
913                 def_nr= ob->actdef-1;
914
915                 i= 0;
916                 for(eve= em->verts.first; eve; eve= eve->next)
917                         eve->tmp.l= i++;
918
919                 dvert_tot= i;
920
921                 vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
922                 vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
923
924                 for(eed= em->edges.first; eed; eed= eed->next) {
925                         sel1= eed->v1->f & SELECT;
926                         sel2= eed->v2->f & SELECT;
927
928                         if(sel1 != sel2) {
929                                 /* i1 is always the selected one */
930                                 if(sel1==TRUE && sel2==FALSE) {
931                                         i1= eed->v1->tmp.l;
932                                         i2= eed->v2->tmp.l;
933                                         eve= eed->v2;
934                                 }
935                                 else {
936                                         i2= eed->v1->tmp.l;
937                                         i1= eed->v2->tmp.l;
938                                         eve= eed->v1;
939                                 }
940
941                                 vg_users[i1]++;
942
943                                 /* TODO, we may want object mode blending */
944                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
945                                 else    dvert= dvert_array+i2;
946
947                                 dw= defvert_find_index(dvert, def_nr);
948
949                                 if(dw) {
950                                         vg_weights[i1] += dw->weight;
951                                 }
952                         }
953                 }
954
955                 i= 0;
956                 for(eve= em->verts.first; eve; eve= eve->next) {
957                         if(eve->f & SELECT && vg_users[i] > 0) {
958                                 /* TODO, we may want object mode blending */
959                                 if(em)  dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
960                                 else    dvert= dvert_array+i;
961
962                                 dw= defvert_verify_index(dvert, def_nr);
963                                 dw->weight= vg_weights[i] / (float)vg_users[i];
964                         }
965
966                         i++;
967                 }
968                 MEM_freeN(vg_weights);
969                 MEM_freeN(vg_users);
970         }
971 }
972
973 static void vgroup_clean(Object *ob, float eul, int keep_single)
974 {
975         bDeformGroup *dg;
976         MDeformWeight *dw;
977         MDeformVert *dvert, **dvert_array=NULL;
978         int i, def_nr, dvert_tot=0;
979
980         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
981
982         /* only the active group */
983         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
984         if(dg) {
985                 def_nr= ob->actdef-1;
986
987                 for(i = 0; i < dvert_tot; i++) {
988                         dvert = dvert_array[i];
989
990                         dw= defvert_find_index(dvert, def_nr);
991
992                         if(dw) {
993                                 if(dw->weight <= eul)
994                                         if(keep_single==FALSE || dvert->totweight > 1)
995                                                 ED_vgroup_nr_vert_remove(ob, def_nr, i);
996                         }
997                 }
998         }
999
1000         if (dvert_array) MEM_freeN(dvert_array);
1001 }
1002
1003 static void vgroup_clean_all(Object *ob, float eul, int keep_single)
1004 {
1005
1006         MDeformWeight *dw;
1007         MDeformVert *dvert, **dvert_array=NULL;
1008         int i, dvert_tot=0;
1009
1010         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot);
1011
1012         if(dvert_array) {
1013                 for(i = 0; i < dvert_tot; i++) {
1014                         int j;
1015                         dvert = dvert_array[i];
1016                         j= dvert->totweight;
1017
1018                         while(j--) {
1019
1020                                 if(keep_single && dvert->totweight == 1)
1021                                         break;
1022
1023                                 dw= dvert->dw + j;
1024
1025                                 if(dw->weight <= eul)
1026                                         ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
1027
1028                         }
1029                 }
1030         }
1031
1032         if (dvert_array) MEM_freeN(dvert_array);
1033 }
1034
1035
1036 static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
1037                             const char sel, const char sel_mirr,
1038                             const int *flip_map,
1039                             const short mirror_weights, const short flip_vgroups)
1040 {
1041         BLI_assert(sel || sel_mirr);
1042
1043         if(sel_mirr && sel) {
1044                 /* swap */
1045                 if(mirror_weights)
1046                         SWAP(MDeformVert, *dvert, *dvert_mirr);
1047                 if(flip_vgroups) {
1048                         defvert_flip(dvert, flip_map);
1049                         defvert_flip(dvert_mirr, flip_map);
1050                 }
1051         }
1052         else {
1053                 /* dvert should always be the target */
1054                 if(sel_mirr) {
1055                         SWAP(MDeformVert *, dvert, dvert_mirr);
1056                 }
1057
1058                 if(mirror_weights)
1059                         defvert_copy(dvert, dvert_mirr);
1060                 if(flip_vgroups) {
1061                         defvert_flip(dvert, flip_map);
1062                 }
1063         }
1064 }
1065
1066 void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups)
1067 {
1068 #define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups)
1069
1070         EditVert *eve, *eve_mirr;
1071         MDeformVert *dvert, *dvert_mirr;
1072         short sel, sel_mirr;
1073         int     *flip_map;
1074
1075         if(mirror_weights==0 && flip_vgroups==0)
1076                 return;
1077
1078         flip_map= defgroup_flip_map(ob, 0);
1079
1080         /* only the active group */
1081         if(ob->type == OB_MESH) {
1082                 Mesh *me= ob->data;
1083                 EditMesh *em = BKE_mesh_get_editmesh(me);
1084
1085
1086                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
1087                         MEM_freeN(flip_map);
1088                         return;
1089                 }
1090
1091                 EM_cache_x_mirror_vert(ob, em);
1092
1093                 /* Go through the list of editverts and assign them */
1094                 for(eve=em->verts.first; eve; eve=eve->next){
1095                         if((eve_mirr=eve->tmp.v)) {
1096                                 sel= eve->f & SELECT;
1097                                 sel_mirr= eve_mirr->f & SELECT;
1098
1099                                 if((sel || sel_mirr) && (eve != eve_mirr)) {
1100                                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1101                                         dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
1102                                         if(dvert && dvert_mirr) {
1103                                                 VGROUP_MIRR_OP;
1104                                         }
1105                                 }
1106
1107                                 eve->tmp.v= eve_mirr->tmp.v= NULL;
1108                         }
1109                 }
1110
1111                 BKE_mesh_end_editmesh(me, em);
1112         }
1113         else if (ob->type == OB_LATTICE) {
1114                 Lattice *lt= ob->data;
1115                 int i1, i2;
1116                 int u, v, w;
1117                 int pntsu_half;
1118                 /* half but found up odd value */
1119
1120                 if(lt->editlatt) lt= lt->editlatt->latt;
1121
1122                 if(lt->pntsu == 1 || lt->dvert == NULL) {
1123                         MEM_freeN(flip_map);
1124                         return;
1125                 }
1126
1127                 /* unlike editmesh we know that by only looping over the first hald of
1128                  * the 'u' indicies it will cover all points except the middle which is
1129                  * ok in this case */
1130                 pntsu_half= lt->pntsu / 2;
1131
1132                 for(w=0; w<lt->pntsw; w++) {
1133                         for(v=0; v<lt->pntsv; v++) {
1134                                 for(u=0; u<pntsu_half; u++) {
1135                                         int u_inv= (lt->pntsu - 1) - u;
1136                                         if(u != u_inv) {
1137                                                 BPoint *bp, *bp_mirr;
1138
1139                                                 i1= LT_INDEX(lt, u, v, w);
1140                                                 i2= LT_INDEX(lt, u_inv, v, w);
1141
1142                                                 bp= &lt->def[i1];
1143                                                 bp_mirr= &lt->def[i2];
1144
1145                                                 sel= bp->f1 & SELECT;
1146                                                 sel_mirr= bp_mirr->f1 & SELECT;
1147
1148                                                 if(sel || sel_mirr) {
1149                                                         dvert= &lt->dvert[i1];
1150                                                         dvert_mirr= &lt->dvert[i2];
1151
1152                                                         VGROUP_MIRR_OP;
1153                                                 }
1154                                         }
1155                                 }
1156                         }
1157                 }
1158         }
1159
1160         MEM_freeN(flip_map);
1161
1162 #undef VGROUP_MIRR_OP
1163 }
1164
1165 static void vgroup_remap_update_users(Object *ob, int *map)
1166 {
1167         ExplodeModifierData *emd;
1168         ModifierData *md;
1169         ParticleSystem *psys;
1170         ClothModifierData *clmd;
1171         ClothSimSettings *clsim;
1172         int a;
1173
1174         /* these cases don't use names to refer to vertex groups, so when
1175          * they get deleted the numbers get out of sync, this corrects that */
1176
1177         if(ob->soft)
1178                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1179
1180         for(md=ob->modifiers.first; md; md=md->next) {
1181                 if(md->type == eModifierType_Explode) {
1182                         emd= (ExplodeModifierData*)md;
1183                         emd->vgroup= map[emd->vgroup];
1184                 }
1185                 else if(md->type == eModifierType_Cloth) {
1186                         clmd= (ClothModifierData*)md;
1187                         clsim= clmd->sim_parms;
1188
1189                         if(clsim) {
1190                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1191                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1192                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1193                         }
1194                 }
1195         }
1196
1197         for(psys=ob->particlesystem.first; psys; psys=psys->next) {
1198                 for(a=0; a<PSYS_TOT_VG; a++)
1199                         psys->vgroup[a]= map[psys->vgroup[a]];
1200         }
1201 }
1202
1203
1204 static void vgroup_delete_update_users(Object *ob, int id)
1205 {
1206         int i, tot= BLI_countlist(&ob->defbase) + 1;
1207         int *map= MEM_mallocN(sizeof(int) * tot, "vgroup del");
1208
1209         map[id]= map[0]= 0;
1210         for(i=1; i<id; i++) map[i]=i;
1211         for(i=id+1; i<tot; i++) map[i]=i-1;
1212
1213         vgroup_remap_update_users(ob, map);
1214         MEM_freeN(map);
1215 }
1216
1217
1218 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1219 {
1220         MDeformVert *dvert_array=NULL;
1221         int i, e, dvert_tot=0;
1222         const int dg_index= BLI_findindex(&ob->defbase, dg);
1223
1224         assert(dg_index > -1);
1225         
1226         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1227
1228         if(dvert_array) {
1229                 MDeformVert *dvert;
1230                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1231                         ED_vgroup_vert_remove(ob, dg, i); /* ok if the dg isnt in this dvert, will continue silently */
1232                 }
1233
1234                 for(i= 0, dvert= dvert_array; i < dvert_tot; i++, dvert++) {
1235                         for(e = 0; e < dvert->totweight; e++) {
1236                                 if(dvert->dw[e].def_nr > dg_index) {
1237                                         dvert->dw[e].def_nr--;
1238                                 }
1239                         }
1240                 }
1241         }
1242
1243         vgroup_delete_update_users(ob, dg_index + 1);
1244
1245         /* Remove the group */
1246         BLI_freelinkN(&ob->defbase, dg);
1247
1248         /* Update the active deform index if necessary */
1249         if(ob->actdef > dg_index)
1250                 ob->actdef--;
1251         if(ob->actdef < 1 && ob->defbase.first)
1252                 ob->actdef= 1;
1253
1254 }
1255
1256 /* only in editmode */
1257 /* removes from active defgroup, if allverts==0 only selected vertices */
1258 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1259 {
1260         EditVert *eve;
1261         MDeformVert *dvert;
1262         MDeformWeight *newdw;
1263         bDeformGroup *eg;
1264         int     i;
1265
1266         if(ob->type == OB_MESH) {
1267                 Mesh *me= ob->data;
1268                 EditMesh *em = BKE_mesh_get_editmesh(me);
1269
1270                 for(eve=em->verts.first; eve; eve=eve->next){
1271                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1272                 
1273                         if(dvert && dvert->dw && ((eve->f & SELECT) || allverts)){
1274                                 for(i=0; i<dvert->totweight; i++){
1275                                         /* Find group */
1276                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1277                                         if(eg == dg){
1278                                                 dvert->totweight--;
1279                                                 if(dvert->totweight){
1280                                                         newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
1281                                                         
1282                                                         if(dvert->dw){
1283                                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
1284                                                                 memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
1285                                                                 MEM_freeN(dvert->dw);
1286                                                         }
1287                                                         dvert->dw=newdw;
1288                                                 }
1289                                                 else{
1290                                                         MEM_freeN(dvert->dw);
1291                                                         dvert->dw=NULL;
1292                                                         break;
1293                                                 }
1294                                         }
1295                                 }
1296                         }
1297                 }
1298                 BKE_mesh_end_editmesh(me, em);
1299         }
1300         else if(ob->type == OB_LATTICE) {
1301                 Lattice *lt= vgroup_edit_lattice(ob);
1302                 
1303                 if(lt->dvert) {
1304                         BPoint *bp;
1305                         int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1306                                 
1307                         for(a=0, bp= lt->def; a<tot; a++, bp++) {
1308                                 if(allverts || (bp->f1 & SELECT))
1309                                         ED_vgroup_vert_remove(ob, dg, a);
1310                         }
1311                 }
1312         }
1313 }
1314
1315 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1316 {
1317         int i;
1318         const int dg_index= BLI_findindex(&ob->defbase, dg);
1319
1320         assert(dg_index > -1);
1321
1322         /* Make sure that no verts are using this group */
1323         vgroup_active_remove_verts(ob, TRUE, dg);
1324
1325         /* Make sure that any verts with higher indices are adjusted accordingly */
1326         if(ob->type==OB_MESH) {
1327                 Mesh *me= ob->data;
1328                 EditMesh *em = BKE_mesh_get_editmesh(me);
1329                 EditVert *eve;
1330                 MDeformVert *dvert;
1331                 
1332                 for(eve=em->verts.first; eve; eve=eve->next){
1333                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1334
1335                         if(dvert)
1336                                 for(i=0; i<dvert->totweight; i++)
1337                                         if(dvert->dw[i].def_nr > dg_index)
1338                                                 dvert->dw[i].def_nr--;
1339                 }
1340                 BKE_mesh_end_editmesh(me, em);
1341         }
1342         else if(ob->type==OB_LATTICE) {
1343                 Lattice *lt= vgroup_edit_lattice(ob);
1344                 BPoint *bp;
1345                 MDeformVert *dvert= lt->dvert;
1346                 int a, tot;
1347                 
1348                 if(dvert) {
1349                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
1350                         for(a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
1351                                 for(i=0; i<dvert->totweight; i++){
1352                                         if(dvert->dw[i].def_nr > dg_index)
1353                                                 dvert->dw[i].def_nr--;
1354                                 }
1355                         }
1356                 }
1357         }
1358
1359         vgroup_delete_update_users(ob, dg_index + 1);
1360
1361         /* Remove the group */
1362         BLI_freelinkN (&ob->defbase, dg);
1363
1364         /* Update the active deform index if necessary */
1365         if(ob->actdef > dg_index)
1366                 ob->actdef--;
1367         if(ob->actdef < 1 && ob->defbase.first)
1368                 ob->actdef= 1;
1369
1370         /* remove all dverts */
1371         if(ob->defbase.first == NULL) {
1372                 if(ob->type==OB_MESH) {
1373                         Mesh *me= ob->data;
1374                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1375                         me->dvert= NULL;
1376                 }
1377                 else if(ob->type==OB_LATTICE) {
1378                         Lattice *lt= vgroup_edit_lattice(ob);
1379                         if(lt->dvert) {
1380                                 MEM_freeN(lt->dvert);
1381                                 lt->dvert= NULL;
1382                         }
1383                 }
1384         }
1385 }
1386
1387 static int vgroup_object_in_edit_mode(Object *ob)
1388 {
1389         if(ob->type == OB_MESH)
1390                 return (((Mesh*)ob->data)->edit_mesh != NULL);
1391         else if(ob->type == OB_LATTICE)
1392                 return (((Lattice*)ob->data)->editlatt != NULL);
1393         
1394         return 0;
1395 }
1396
1397 static void vgroup_delete(Object *ob)
1398 {
1399         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
1400         if(!dg)
1401                 return;
1402
1403         if(vgroup_object_in_edit_mode(ob))
1404                 vgroup_delete_edit_mode(ob, dg);
1405         else
1406                 vgroup_delete_object_mode(ob, dg);
1407 }
1408
1409 static void vgroup_delete_all(Object *ob)
1410 {
1411         /* Remove all DVerts */
1412         if(ob->type==OB_MESH) {
1413                 Mesh *me= ob->data;
1414                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
1415                 me->dvert= NULL;
1416         }
1417         else if(ob->type==OB_LATTICE) {
1418                 Lattice *lt= vgroup_edit_lattice(ob);
1419                 if(lt->dvert) {
1420                         MEM_freeN(lt->dvert);
1421                         lt->dvert= NULL;
1422                 }
1423         }
1424         
1425         /* Remove all DefGroups */
1426         BLI_freelistN(&ob->defbase);
1427         
1428         /* Fix counters/indices */
1429         ob->actdef= 0;
1430 }
1431
1432 /* only in editmode */
1433 static void vgroup_assign_verts(Object *ob, float weight)
1434 {
1435         EditVert *eve;
1436         bDeformGroup *dg, *eg;
1437         MDeformWeight *newdw;
1438         MDeformVert *dvert;
1439         int     i, done;
1440
1441         dg=BLI_findlink(&ob->defbase, ob->actdef-1);
1442         if(!dg)
1443                 return;
1444
1445         if(ob->type == OB_MESH) {
1446                 Mesh *me= ob->data;
1447                 EditMesh *em = BKE_mesh_get_editmesh(me);
1448
1449                 if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT))
1450                         EM_add_data_layer(em, &em->vdata, CD_MDEFORMVERT, NULL);
1451
1452                 /* Go through the list of editverts and assign them */
1453                 for(eve=em->verts.first; eve; eve=eve->next){
1454                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
1455
1456                         if(dvert && (eve->f & SELECT)){
1457                                 /* See if this vert already has a reference to this group */
1458                                 /*              If so: Change its weight */
1459                                 done=0;
1460                                 for(i=0; i<dvert->totweight; i++){
1461                                         eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
1462                                         /* Find the actual group */
1463                                         if(eg==dg){
1464                                                 dvert->dw[i].weight= weight;
1465                                                 done=1;
1466                                                 break;
1467                                         }
1468                                  }
1469                                 /*              If not: Add the group and set its weight */
1470                                 if(!done){
1471                                         newdw = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
1472                                         if(dvert->dw){
1473                                                 memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
1474                                                 MEM_freeN(dvert->dw);
1475                                         }
1476                                         dvert->dw=newdw;
1477
1478                                         dvert->dw[dvert->totweight].weight= weight;
1479                                         dvert->dw[dvert->totweight].def_nr= ob->actdef-1;
1480
1481                                         dvert->totweight++;
1482
1483                                 }
1484                         }
1485                 }
1486                 BKE_mesh_end_editmesh(me, em);
1487         }
1488         else if(ob->type == OB_LATTICE) {
1489                 Lattice *lt= vgroup_edit_lattice(ob);
1490                 BPoint *bp;
1491                 int a, tot;
1492                 
1493                 if(lt->dvert==NULL)
1494                         ED_vgroup_data_create(&lt->id);
1495                 
1496                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
1497                 for(a=0, bp= lt->def; a<tot; a++, bp++) {
1498                         if(bp->f1 & SELECT)
1499                                 ED_vgroup_nr_vert_add(ob, ob->actdef-1, a, weight, WEIGHT_REPLACE);
1500                 }
1501         }
1502 }
1503
1504 /* only in editmode */
1505 /* removes from all defgroup, if allverts==0 only selected vertices */
1506 static void vgroup_remove_verts(Object *ob, int allverts)
1507 {
1508         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
1509          * only operates on the active vgroup. So we iterate through all groups, by changing
1510          * active group index
1511          */
1512         bDeformGroup *dg;
1513         for(dg= ob->defbase.first; dg; dg= dg->next) {
1514                 vgroup_active_remove_verts(ob, allverts, dg);
1515         }
1516 }
1517
1518 /********************** vertex group operators *********************/
1519
1520 static int vertex_group_poll(bContext *C)
1521 {
1522         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1523         ID *data= (ob)? ob->data: NULL;
1524         return (ob && !ob->id.lib && ELEM(ob->type, OB_MESH, OB_LATTICE) && data && !data->lib);
1525 }
1526
1527 static int vertex_group_poll_edit(bContext *C)
1528 {
1529         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1530         ID *data= (ob)? ob->data: NULL;
1531
1532         if(!(ob && !ob->id.lib && data && !data->lib))
1533                 return 0;
1534
1535         return vgroup_object_in_edit_mode(ob);
1536 }
1537
1538 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
1539 {
1540         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1541
1542         ED_vgroup_add(ob);
1543         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1544         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1545         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1546         
1547         return OPERATOR_FINISHED;
1548 }
1549
1550 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
1551 {
1552         /* identifiers */
1553         ot->name= "Add Vertex Group";
1554         ot->idname= "OBJECT_OT_vertex_group_add";
1555         
1556         /* api callbacks */
1557         ot->poll= vertex_group_poll;
1558         ot->exec= vertex_group_add_exec;
1559
1560         /* flags */
1561         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1562 }
1563
1564 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
1565 {
1566         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1567
1568         if(RNA_boolean_get(op->ptr, "all"))
1569                 vgroup_delete_all(ob);
1570         else
1571                 vgroup_delete(ob);
1572
1573         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1574         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1575         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1576         
1577         return OPERATOR_FINISHED;
1578 }
1579
1580 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
1581 {
1582         /* identifiers */
1583         ot->name= "Remove Vertex Group";
1584         ot->idname= "OBJECT_OT_vertex_group_remove";
1585         
1586         /* api callbacks */
1587         ot->poll= vertex_group_poll;
1588         ot->exec= vertex_group_remove_exec;
1589
1590         /* flags */
1591         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1592
1593         /* properties */
1594         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1595 }
1596
1597 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
1598 {
1599         ToolSettings *ts= CTX_data_tool_settings(C);
1600         Object *ob= CTX_data_edit_object(C);
1601
1602         if(RNA_boolean_get(op->ptr, "new"))
1603                 ED_vgroup_add(ob);
1604
1605         vgroup_assign_verts(ob, ts->vgroup_weight);
1606         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1607         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1608         
1609         return OPERATOR_FINISHED;
1610 }
1611
1612 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
1613 {
1614         /* identifiers */
1615         ot->name= "Assign Vertex Group";
1616         ot->idname= "OBJECT_OT_vertex_group_assign";
1617         
1618         /* api callbacks */
1619         ot->poll= vertex_group_poll_edit;
1620         ot->exec= vertex_group_assign_exec;
1621
1622         /* flags */
1623         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1624
1625         /* properties */
1626         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group.");
1627 }
1628
1629 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
1630 {
1631         Object *ob= CTX_data_edit_object(C);
1632
1633         if(RNA_boolean_get(op->ptr, "all"))
1634                 vgroup_remove_verts(ob, 0);
1635         else {
1636                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
1637
1638                 if(dg == NULL) {
1639                         return OPERATOR_CANCELLED;
1640                 }
1641
1642                 vgroup_active_remove_verts(ob, FALSE, dg);
1643         }
1644
1645         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1646         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1647
1648         return OPERATOR_FINISHED;
1649 }
1650
1651 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
1652 {
1653         /* identifiers */
1654         ot->name= "Remove from Vertex Group";
1655         ot->idname= "OBJECT_OT_vertex_group_remove_from";
1656
1657         /* api callbacks */
1658         ot->poll= vertex_group_poll_edit;
1659         ot->exec= vertex_group_remove_from_exec;
1660
1661         /* flags */
1662         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1663
1664         /* properties */
1665         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups.");
1666 }
1667
1668 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
1669 {
1670         Object *ob= CTX_data_edit_object(C);
1671
1672         if(!ob || ob->id.lib)
1673                 return OPERATOR_CANCELLED;
1674
1675         vgroup_select_verts(ob, 1);
1676         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1677
1678         return OPERATOR_FINISHED;
1679 }
1680
1681 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
1682 {
1683         /* identifiers */
1684         ot->name= "Select Vertex Group";
1685         ot->idname= "OBJECT_OT_vertex_group_select";
1686
1687         /* api callbacks */
1688         ot->poll= vertex_group_poll_edit;
1689         ot->exec= vertex_group_select_exec;
1690
1691         /* flags */
1692         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1693 }
1694
1695 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
1696 {
1697         Object *ob= CTX_data_edit_object(C);
1698
1699         vgroup_select_verts(ob, 0);
1700         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
1701
1702         return OPERATOR_FINISHED;
1703 }
1704
1705 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
1706 {
1707         /* identifiers */
1708         ot->name= "Deselect Vertex Group";
1709         ot->idname= "OBJECT_OT_vertex_group_deselect";
1710
1711         /* api callbacks */
1712         ot->poll= vertex_group_poll_edit;
1713         ot->exec= vertex_group_deselect_exec;
1714
1715         /* flags */
1716         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1717 }
1718
1719 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
1720 {
1721         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1722
1723         vgroup_duplicate(ob);
1724         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1725         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1726         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1727
1728         return OPERATOR_FINISHED;
1729 }
1730
1731 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
1732 {
1733         /* identifiers */
1734         ot->name= "Copy Vertex Group";
1735         ot->idname= "OBJECT_OT_vertex_group_copy";
1736
1737         /* api callbacks */
1738         ot->poll= vertex_group_poll;
1739         ot->exec= vertex_group_copy_exec;
1740
1741         /* flags */
1742         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1743 }
1744
1745 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
1746 {
1747         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1748         
1749         float offset= RNA_float_get(op->ptr,"offset");
1750         float gain= RNA_float_get(op->ptr,"gain");
1751         
1752         vgroup_levels(ob, offset, gain);
1753         
1754         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1755         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1756         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1757         
1758         return OPERATOR_FINISHED;
1759 }
1760
1761 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
1762 {
1763         /* identifiers */
1764         ot->name= "Vertex Group Levels";
1765         ot->idname= "OBJECT_OT_vertex_group_levels";
1766         
1767         /* api callbacks */
1768         ot->poll= vertex_group_poll;
1769         ot->exec= vertex_group_levels_exec;
1770         
1771         /* flags */
1772         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1773         
1774         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights.", -1.0f, 1.f);
1775         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by.", 0.0f, 10.f);
1776 }
1777
1778 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
1779 {
1780         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1781
1782         vgroup_normalize(ob);
1783
1784         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1785         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1786         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1787
1788         return OPERATOR_FINISHED;
1789 }
1790
1791 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
1792 {
1793         /* identifiers */
1794         ot->name= "Normalize Vertex Group";
1795         ot->idname= "OBJECT_OT_vertex_group_normalize";
1796
1797         /* api callbacks */
1798         ot->poll= vertex_group_poll;
1799         ot->exec= vertex_group_normalize_exec;
1800
1801         /* flags */
1802         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1803 }
1804
1805 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
1806 {
1807         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1808         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
1809
1810         vgroup_normalize_all(ob, lock_active);
1811
1812         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1813         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1814         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1815
1816         return OPERATOR_FINISHED;
1817 }
1818
1819 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
1820 {
1821         /* identifiers */
1822         ot->name= "Normalize All Vertex Groups";
1823         ot->idname= "OBJECT_OT_vertex_group_normalize_all";
1824
1825         /* api callbacks */
1826         ot->poll= vertex_group_poll;
1827         ot->exec= vertex_group_normalize_all_exec;
1828
1829         /* flags */
1830         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1831
1832         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
1833 }
1834
1835 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
1836 {
1837         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1838         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
1839         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
1840
1841         vgroup_invert(ob, auto_assign, auto_remove);
1842         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1843         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1844         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1845
1846         return OPERATOR_FINISHED;
1847 }
1848
1849 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
1850 {
1851         /* identifiers */
1852         ot->name= "Invert Vertex Group";
1853         ot->idname= "OBJECT_OT_vertex_group_invert";
1854
1855         /* api callbacks */
1856         ot->poll= vertex_group_poll;
1857         ot->exec= vertex_group_invert_exec;
1858
1859         /* flags */
1860         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1861
1862         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
1863         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
1864 }
1865
1866
1867 static int vertex_group_blend_exec(bContext *C, wmOperator *UNUSED(op))
1868 {
1869         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1870
1871         vgroup_blend(ob);
1872
1873         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1874         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1875         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1876
1877         return OPERATOR_FINISHED;
1878 }
1879
1880 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
1881 {
1882         /* identifiers */
1883         ot->name= "Blend Vertex Group";
1884         ot->idname= "OBJECT_OT_vertex_group_blend";
1885         ot->description= "";
1886
1887         /* api callbacks */
1888         ot->poll= vertex_group_poll;
1889         ot->exec= vertex_group_blend_exec;
1890
1891         /* flags */
1892         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1893 }
1894
1895
1896 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
1897 {
1898         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1899
1900         float limit= RNA_float_get(op->ptr,"limit");
1901         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
1902         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
1903
1904         if(all_groups)  vgroup_clean_all(ob, limit, keep_single);
1905         else                    vgroup_clean(ob, limit, keep_single);
1906
1907         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1908         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1909         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1910
1911         return OPERATOR_FINISHED;
1912 }
1913
1914 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
1915 {
1916         /* identifiers */
1917         ot->name= "Clean Vertex Group";
1918         ot->idname= "OBJECT_OT_vertex_group_clean";
1919         ot->description= "Remove Vertex Group assignments which aren't required";
1920
1921         /* api callbacks */
1922         ot->poll= vertex_group_poll;
1923         ot->exec= vertex_group_clean_exec;
1924
1925         /* flags */
1926         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1927
1928         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
1929         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
1930         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
1931 }
1932
1933
1934 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
1935 {
1936         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1937
1938         ED_vgroup_mirror(ob, RNA_boolean_get(op->ptr,"mirror_weights"), RNA_boolean_get(op->ptr,"flip_group_names"));
1939
1940         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1941         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
1942         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
1943
1944         return OPERATOR_FINISHED;
1945 }
1946
1947 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
1948 {
1949         /* identifiers */
1950         ot->name= "Mirror Vertex Group";
1951         ot->idname= "OBJECT_OT_vertex_group_mirror";
1952         ot->description= "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, flipping when both sides are selected otherwise copy from unselected";
1953
1954         /* api callbacks */
1955         ot->poll= vertex_group_poll_edit;
1956         ot->exec= vertex_group_mirror_exec;
1957
1958         /* flags */
1959         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1960
1961         /* properties */
1962         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights.");
1963         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names.");
1964
1965 }
1966
1967 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
1968 {
1969         Scene *scene= CTX_data_scene(C);
1970         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1971         Base *base;
1972         int retval= OPERATOR_CANCELLED;
1973
1974         for(base=scene->base.first; base; base= base->next) {
1975                 if(base->object->type==ob->type) {
1976                         if(base->object!=ob && base->object->data==ob->data) {
1977                                 BLI_freelistN(&base->object->defbase);
1978                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
1979                                 base->object->actdef= ob->actdef;
1980
1981                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
1982                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
1983                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
1984
1985                                 retval = OPERATOR_FINISHED;
1986                         }
1987                 }
1988         }
1989
1990         return retval;
1991 }
1992
1993 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
1994 {
1995         /* identifiers */
1996         ot->name= "Copy Vertex Groups to Linked";
1997         ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
1998         ot->description= "Copy Vertex Groups to all users of the same Geometry data";
1999
2000         /* api callbacks */
2001         ot->poll= vertex_group_poll;
2002         ot->exec= vertex_group_copy_to_linked_exec;
2003
2004         /* flags */
2005         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2006 }
2007
2008 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
2009 {
2010         Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2011         int change= 0;
2012         int fail= 0;
2013
2014         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
2015         {
2016                 if(obact != ob) {
2017                         if(ED_vgroup_copy_array(ob, obact)) change++;
2018                         else                                fail++;
2019                 }
2020         }
2021         CTX_DATA_END;
2022
2023         if((change == 0 && fail == 0) || fail) {
2024                 BKE_reportf(op->reports, RPT_ERROR, "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indicies", change, fail);
2025         }
2026
2027         return OPERATOR_FINISHED;
2028 }
2029
2030
2031 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
2032 {
2033         /* identifiers */
2034         ot->name= "Copy Vertex Group to Selected";
2035         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected";
2036         ot->description= "Copy Vertex Groups to other selected objects with matching indices";
2037
2038         /* api callbacks */
2039         ot->poll= vertex_group_poll;
2040         ot->exec= vertex_group_copy_to_selected_exec;
2041
2042         /* flags */
2043         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2044 }
2045
2046 static EnumPropertyItem vgroup_items[]= {
2047         {0, NULL, 0, NULL, NULL}};
2048
2049 static int set_active_group_exec(bContext *C, wmOperator *op)
2050 {
2051         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2052         int nr= RNA_enum_get(op->ptr, "group");
2053
2054         ob->actdef= nr+1;
2055
2056         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2057         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2058
2059         return OPERATOR_FINISHED;
2060 }
2061
2062 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
2063 {       
2064         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2065         EnumPropertyItem tmp = {0, "", 0, "", ""};
2066         EnumPropertyItem *item= NULL;
2067         bDeformGroup *def;
2068         int a, totitem= 0;
2069         
2070         if(!ob)
2071                 return vgroup_items;
2072         
2073         for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
2074                 tmp.value= a;
2075                 tmp.icon= ICON_GROUP_VERTEX;
2076                 tmp.identifier= def->name;
2077                 tmp.name= def->name;
2078                 RNA_enum_item_add(&item, &totitem, &tmp);
2079         }
2080
2081         RNA_enum_item_end(&item, &totitem);
2082         *free= 1;
2083
2084         return item;
2085 }
2086
2087 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2088 {
2089         PropertyRNA *prop;
2090
2091         /* identifiers */
2092         ot->name= "Set Active Vertex Group";
2093         ot->idname= "OBJECT_OT_vertex_group_set_active";
2094         ot->description= "Set the active vertex group";
2095
2096         /* api callbacks */
2097         ot->poll= vertex_group_poll;
2098         ot->exec= set_active_group_exec;
2099         ot->invoke= WM_menu_invoke;
2100
2101         /* flags */
2102         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2103
2104         /* properties */
2105         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
2106         RNA_def_enum_funcs(prop, vgroup_itemf);
2107         ot->prop= prop;
2108 }
2109
2110 /*creates the name_array parameter for vgroup_do_remap, call this before fiddling
2111   with the order of vgroups then call vgroup_do_remap after*/
2112 static char *vgroup_init_remap(Object *ob)
2113 {
2114         bDeformGroup *def;
2115         int def_tot = BLI_countlist(&ob->defbase);
2116         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * def_tot, "sort vgroups");
2117         char *name;
2118
2119         name= name_array;
2120         for(def = ob->defbase.first; def; def=def->next) {
2121                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
2122                 name += MAX_VGROUP_NAME;
2123         }
2124
2125         return name_array;
2126 }
2127
2128 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
2129 {
2130         MDeformVert *dvert= NULL;
2131         bDeformGroup *def;
2132         int def_tot = BLI_countlist(&ob->defbase);
2133         int *sort_map_update= MEM_mallocN(MAX_VGROUP_NAME * sizeof(int) * def_tot + 1, "sort vgroups"); /* needs a dummy index at the start*/
2134         int *sort_map= sort_map_update + 1;
2135         char *name;
2136         int i;
2137
2138         name= name_array;
2139         for(def= ob->defbase.first, i=0; def; def=def->next, i++){
2140                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
2141                 name += MAX_VGROUP_NAME;
2142         }
2143
2144         if(ob->mode == OB_MODE_EDIT) {
2145                 if(ob->type==OB_MESH) {
2146                         EditMesh *em = BKE_mesh_get_editmesh(ob->data);
2147                         EditVert *eve;
2148
2149                         for(eve=em->verts.first; eve; eve=eve->next){
2150                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
2151                                 if(dvert && dvert->totweight){
2152                                         defvert_remap(dvert, sort_map);
2153                                 }
2154                         }
2155                 }
2156                 else {
2157                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isnt supported yet.");
2158                         MEM_freeN(sort_map_update);
2159                         return OPERATOR_CANCELLED;
2160                 }
2161         }
2162         else {
2163                 int dvert_tot=0;
2164
2165                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
2166
2167                 /*create as necassary*/
2168                 while(dvert && dvert_tot--) {
2169                         if(dvert->totweight)
2170                                 defvert_remap(dvert, sort_map);
2171                         dvert++;
2172                 }
2173         }
2174
2175         /* update users */
2176         for(i=0; i<def_tot; i++)
2177                 sort_map[i]++;
2178
2179         sort_map_update[0]= 0;
2180         vgroup_remap_update_users(ob, sort_map_update);
2181
2182         ob->actdef= sort_map_update[ob->actdef];
2183         
2184         MEM_freeN(sort_map_update);
2185
2186         return OPERATOR_FINISHED;
2187 }
2188
2189 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
2190 {
2191         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
2192         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
2193
2194         return BLI_natstrcmp(def_a->name, def_b->name);
2195 }
2196
2197 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
2198 {
2199         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2200         char *name_array;
2201         int ret;
2202
2203         /*init remapping*/
2204         name_array = vgroup_init_remap(ob);
2205
2206         /*sort vgroup names*/
2207         BLI_sortlist(&ob->defbase, vgroup_sort);
2208
2209         /*remap vgroup data to map to correct names*/
2210         ret = vgroup_do_remap(ob, name_array, op);
2211
2212         if (ret != OPERATOR_CANCELLED) {
2213                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2214                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2215         }
2216
2217         if (name_array) MEM_freeN(name_array);
2218
2219         return ret;
2220 }
2221
2222 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
2223 {
2224         ot->name= "Sort Vertex Groups";
2225         ot->idname= "OBJECT_OT_vertex_group_sort";
2226         ot->description= "Sorts vertex groups alphabetically";
2227
2228         /* api callbacks */
2229         ot->poll= vertex_group_poll;
2230         ot->exec= vertex_group_sort_exec;
2231
2232         /* flags */
2233         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2234 }
2235
2236 static int vgroup_move_exec(bContext *C, wmOperator *op)
2237 {
2238         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
2239         bDeformGroup *def;
2240         char *name_array;
2241         int dir= RNA_enum_get(op->ptr, "direction"), ret;
2242
2243         def = BLI_findlink(&ob->defbase, ob->actdef - 1);
2244         if (!def) {
2245                 return OPERATOR_CANCELLED;
2246         }
2247
2248         name_array = vgroup_init_remap(ob);
2249
2250         if (dir == 1) { /*up*/
2251                 void *prev = def->prev;
2252
2253                 BLI_remlink(&ob->defbase, def);
2254                 BLI_insertlinkbefore(&ob->defbase, prev, def);
2255         } else { /*down*/
2256                 void *next = def->next;
2257
2258                 BLI_remlink(&ob->defbase, def);
2259                 BLI_insertlinkafter(&ob->defbase, next, def);
2260         }
2261
2262         ret = vgroup_do_remap(ob, name_array, op);
2263
2264         if (name_array) MEM_freeN(name_array);
2265
2266         if (ret != OPERATOR_CANCELLED) {
2267                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2268                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2269         }
2270
2271         return ret;
2272 }
2273
2274 void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
2275 {
2276         static EnumPropertyItem vgroup_slot_move[] = {
2277                 {1, "UP", 0, "Up", ""},
2278                 {-1, "DOWN", 0, "Down", ""},
2279                 {0, NULL, 0, NULL, NULL}
2280         };
2281
2282         /* identifiers */
2283         ot->name= "Move Vertex Group";
2284         ot->idname= "OBJECT_OT_vertex_group_move";
2285
2286         /* api callbacks */
2287         ot->poll= vertex_group_poll;
2288         ot->exec= vgroup_move_exec;
2289
2290         /* flags */
2291         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2292
2293         RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
2294 }