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