svn merge ^/trunk/blender -r44562:HEAD
[blender.git] / source / blender / editors / object / object_vgroup.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Ove M Henriksen
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/object/object_vgroup.c
29  *  \ingroup edobj
30  */
31
32
33 #include <string.h>
34 #include <stddef.h>
35 #include <math.h>
36 #include <assert.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_cloth_types.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_mesh_types.h"
45 #include "DNA_modifier_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_object_force.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_particle_types.h"
50
51 #include "BLI_array.h"
52 #include "BLI_math.h"
53 #include "BLI_blenlib.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_tessmesh.h"
63 #include "BKE_report.h"
64 #include "BKE_DerivedMesh.h"
65
66 #include "RNA_access.h"
67 #include "RNA_define.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71
72 #include "ED_object.h"
73 #include "ED_mesh.h"
74
75 #include "UI_resources.h"
76
77 #include "object_intern.h"
78 #include <stdio.h> /*only for development purposes, remove*/
79
80 /************************ Exported Functions **********************/
81 static void vgroup_remap_update_users(Object *ob, int *map);
82 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup);
83 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg);
84 static void vgroup_delete_all(Object *ob);
85
86 static Lattice *vgroup_edit_lattice(Object *ob)
87 {
88         Lattice *lt= ob->data;
89         BLI_assert(ob->type==OB_LATTICE);
90         return (lt->editlatt)? lt->editlatt->latt: lt;
91 }
92
93 int ED_vgroup_object_is_edit_mode(Object *ob)
94 {
95         if (ob->type == OB_MESH)
96                 return (BMEdit_FromObject(ob) != NULL);
97         else if (ob->type == OB_LATTICE)
98                 return (((Lattice*)ob->data)->editlatt != NULL);
99
100         return 0;
101 }
102
103 bDeformGroup *ED_vgroup_add_name(Object *ob, const char *name)
104 {
105         bDeformGroup *defgroup;
106
107         if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type))
108                 return NULL;
109         
110         defgroup = MEM_callocN(sizeof(bDeformGroup), "add deformGroup");
111
112         BLI_strncpy(defgroup->name, name, sizeof(defgroup->name));
113
114         BLI_addtail(&ob->defbase, defgroup);
115         defgroup_unique_name(defgroup, ob);
116
117         ob->actdef = BLI_countlist(&ob->defbase);
118
119         return defgroup;
120 }
121
122 bDeformGroup *ED_vgroup_add(Object *ob) 
123 {
124         return ED_vgroup_add_name(ob, "Group");
125 }
126
127 void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) 
128 {
129         bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
130
131         while (dg) {
132                 if (dg == defgroup)
133                         break;
134                 dg = dg->next;
135         }
136
137         if (dg == NULL)
138                 return;
139
140         if (ED_vgroup_object_is_edit_mode(ob))
141                 vgroup_delete_edit_mode(ob, dg);
142         else
143                 vgroup_delete_object_mode(ob, dg);
144 }
145
146 void ED_vgroup_clear(Object *ob)
147 {
148         bDeformGroup *dg= (bDeformGroup *)ob->defbase.first;
149         int edit_mode= ED_vgroup_object_is_edit_mode(ob);
150
151         while (dg) {
152                 bDeformGroup *next_dg= dg->next;
153
154                 if (edit_mode)
155                         vgroup_delete_edit_mode(ob, dg);
156                 else
157                         vgroup_delete_object_mode(ob, dg);
158
159                 dg= next_dg;
160         }
161 }
162
163 int ED_vgroup_data_create(ID *id)
164 {
165         /* create deform verts */
166
167         if (GS(id->name)==ID_ME) {
168                 Mesh *me= (Mesh *)id;
169                 me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
170                 return TRUE;
171         }
172         else if (GS(id->name)==ID_LT) {
173                 Lattice *lt= (Lattice *)id;
174                 lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert");
175                 return TRUE;
176         }
177         else {
178                 return FALSE;
179         }
180 }
181
182 static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel)
183 {
184         *dvert_tot = 0;
185         *dvert_arr = NULL;
186
187         if (id) {
188                 switch(GS(id->name)) {
189                         case ID_ME:
190                         {
191                                 Mesh *me = (Mesh *)id;
192
193                                 if (me->edit_btmesh) {
194                                         BMEditMesh *em = me->edit_btmesh;
195                                         BMIter iter;
196                                         BMVert *eve;
197                                         int i;
198
199                                         if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) {
200                                                 return 0;
201                                         }
202
203                                         i = em->bm->totvert;
204
205                                         *dvert_arr= MEM_mallocN(sizeof(void*)*i, "vgroup parray from me");
206                                         *dvert_tot = i;
207
208                                         i = 0;
209                                         if (use_vert_sel) {
210                                                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
211                                                         (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
212                                                                           CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT) : NULL;
213                                                         i++;
214                                                 }
215                                         }
216                                         else {
217                                                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
218                                                         (*dvert_arr)[i] = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
219                                                         i++;
220                                                 }
221                                         }
222
223                                         return 1;
224                                 }
225                                 else if (me->dvert) {
226                                         MVert *mvert= me->mvert;
227                                         MDeformVert *dvert= me->dvert;
228                                         int i;
229
230                                         *dvert_tot= me->totvert;
231                                         *dvert_arr= MEM_mallocN(sizeof(void*)*me->totvert, "vgroup parray from me");
232
233                                         if (use_vert_sel) {
234                                                 for (i=0; i<me->totvert; i++) {
235                                                         (*dvert_arr)[i] = (mvert[i].flag & SELECT) ?
236                                                                            &dvert[i] : NULL;
237                                                 }
238                                         }
239                                         else {
240                                                 for (i=0; i<me->totvert; i++) {
241                                                         (*dvert_arr)[i] = me->dvert + i;
242                                                 }
243                                         }
244
245                                         return 1;
246                                 }
247                                 else {
248                                         return 0;
249                                 }
250                         }
251                         case ID_LT:
252                         {
253                                 int i=0;
254
255                                 Lattice *lt= (Lattice *)id;
256                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
257
258                                 if (lt->dvert) {
259                                         BPoint *def= lt->def;
260                                         *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
261                                         *dvert_arr= MEM_mallocN(sizeof(void*)*(*dvert_tot), "vgroup parray from me");
262
263                                         if (use_vert_sel) {
264                                                 for (i=0; i<*dvert_tot; i++) {
265                                                         (*dvert_arr)[i] = (def->f1 & SELECT) ?
266                                                                            &lt->dvert[i] : NULL;
267                                                 }
268                                         }
269                                         else {
270                                                 for (i=0; i<*dvert_tot; i++) {
271                                                         (*dvert_arr)[i] = lt->dvert + i;
272                                                 }
273                                         }
274
275                                         return 1;
276                                 }
277                                 else {
278                                         return 0;
279                                 }
280                         }
281                 }
282         }
283
284         return 0;
285 }
286
287 /* returns true if the id type supports weights */
288 int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
289 {
290         if (id) {
291                 switch(GS(id->name)) {
292                         case ID_ME:
293                         {
294                                 Mesh *me = (Mesh *)id;
295                                 *dvert_arr= me->dvert;
296                                 *dvert_tot= me->totvert;
297                                 return TRUE;
298                         }
299                         case ID_LT:
300                         {
301                                 Lattice *lt= (Lattice *)id;
302                                 lt= (lt->editlatt)? lt->editlatt->latt: lt;
303                                 *dvert_arr= lt->dvert;
304                                 *dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
305                                 return TRUE;
306                         }
307                 }
308         }
309
310         *dvert_arr= NULL;
311         *dvert_tot= 0;
312         return FALSE;
313 }
314
315 /*Copy all vertex groups to target, overwriting existing. matching index only*/
316 int ED_vgroup_copy_array(Object *ob, Object *ob_from)
317 {
318         MDeformVert **dvert_array_from, **dvf;
319         MDeformVert **dvert_array, **dv;
320         int dvert_tot_from;
321         int dvert_tot;
322         int i;
323         int defbase_tot_from= BLI_countlist(&ob_from->defbase);
324         int defbase_tot= BLI_countlist(&ob->defbase);
325         short new_vgroup= FALSE;
326
327         ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from, FALSE);
328         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, FALSE);
329
330         if ((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) {
331                 ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, FALSE);
332                 new_vgroup= TRUE;
333         }
334
335         if (ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) {
336                 if (dvert_array) MEM_freeN(dvert_array);
337                 if (dvert_array_from) MEM_freeN(dvert_array_from);
338
339                 if (new_vgroup == TRUE) {
340                         /* free the newly added vgroup since it wasn't compatible */
341                         vgroup_delete_all(ob);
342                 }
343                 return 0;
344         }
345
346         /* do the copy */
347         BLI_freelistN(&ob->defbase);
348         BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
349         ob->actdef= ob_from->actdef;
350
351         if (defbase_tot_from < defbase_tot) {
352                 /* correct vgroup indices because the number of vgroups is being reduced. */
353                 int *remap= MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
354                 for (i=0; i<=defbase_tot_from; i++) remap[i]= i;
355                 for (; i<=defbase_tot; i++) remap[i]= 0; /* can't use these, so disable */
356
357                 vgroup_remap_update_users(ob, remap);
358                 MEM_freeN(remap);
359         }
360
361         dvf= dvert_array_from;
362         dv= dvert_array;
363
364         for (i=0; i<dvert_tot; i++, dvf++, dv++) {
365                 if ((*dv)->dw)
366                         MEM_freeN((*dv)->dw);
367
368                 *(*dv)= *(*dvf);
369
370                 if ((*dv)->dw)
371                         (*dv)->dw= MEM_dupallocN((*dv)->dw);
372         }
373
374         MEM_freeN(dvert_array);
375         MEM_freeN(dvert_array_from);
376
377         return 1;
378 }
379
380 /*Copy a single vertex group from source to destination with weights*/
381 int ED_vgroup_copy_single(Object *ob_dst, const Object *ob_src)
382 {
383         MDeformVert **dv_array_src;
384         MDeformVert **dv_array_dst;
385         MDeformWeight *dw_dst, *dw_src;
386         int dv_tot_src, dv_tot_dst;
387         int i, index_src, index_dst;
388         bDeformGroup *dg_src, *dg_dst;
389
390         /*get source deform group*/
391         dg_src = BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
392
393         /*Create new and overwrite vertex group on destination without data*/
394         ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
395         ED_vgroup_add_name(ob_dst, dg_src->name);
396
397         /*get destination deformgroup*/
398         dg_dst= defgroup_find_name(ob_dst, dg_src->name);
399
400         /*get vertex group arrays*/
401         ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
402         ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
403
404         /*get indexes of vertex groups*/
405         index_src= BLI_findindex(&ob_src->defbase, dg_src);
406         index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
407
408         /*Check if indices are matching, delete and return if not*/
409         if (ob_dst==ob_src || dv_tot_dst==0 || (dv_tot_dst != dv_tot_src) || dv_array_src==NULL || dv_array_dst==NULL) {
410                 ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_dst->name));
411                 return 0;
412         }
413
414         /* Loop through the vertices and copy weight*/
415         for(i=0; i<dv_tot_dst; i++, dv_array_src++, dv_array_dst++) {
416                 dw_src = defvert_verify_index(*dv_array_src, index_src);
417                 dw_dst = defvert_verify_index(*dv_array_dst, index_dst);
418                 dw_dst->weight = dw_src->weight;
419         }
420
421         return 1;
422 }
423
424 /*return distance between coordinates that are comparable to other instances but not right*/
425 float comparable_distance_between_coordinates(const float co_1[3], const float co_2[3]){
426         float x_dist, y_dist, z_dist, dist_XY_square, distance;
427         x_dist= co_1[0] - co_2[0];
428         y_dist= co_1[1] - co_2[1];
429         z_dist= co_1[2] - co_2[2];
430         dist_XY_square= x_dist * x_dist + y_dist * y_dist;
431         distance= dist_XY_square + z_dist * z_dist;
432         return distance;
433 }
434
435 /*Copy a single vertex group from source to destination with weights, get the closest weight on source*/
436 int ED_vgroup_copy_by_closest_single(Object *ob_dst, const Object *ob_src)
437 {
438         bDeformGroup *dg_src, *dg_dst;
439         MDeformVert **dv_array_src, **dv_array_dst;
440         MDeformWeight *dw_dst, *dw_src;
441         MVert *mv_dst;
442         Mesh *me_dst;
443         BVHTreeFromMesh tree_mesh_src;
444         BVHTreeNearest nearest;
445         DerivedMesh *dmesh_src;
446         int dv_tot_src, dv_tot_dst, i, index_dst, index_src;
447
448         /*TODO: Check if it should be used and return 0 if not*/
449         /*TODO: Bugfix, if position of object center is not similar, the copy will fail*/
450         /*suggested sollution: temporarily set object center to geometry center on both source and target*/
451         /*suggested sollution: temporarily manipulate destination  object center to align with source*/
452         /*suggested solution: user choise*/
453         /*TODO: take scale into account*/
454         /*memory safety TODO make this work.
455         if (tree_mesh_src.tree == NULL)
456         {
457                 OUT_OF_MEMORY();
458                 return;
459         }*/
460
461         /*get source deform group*/
462         dg_src = BLI_findlink(&ob_src->defbase, (ob_src->actdef-1));
463
464         /*Create new and overwrite vertex group on destination without data*/
465         ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
466         ED_vgroup_add_name(ob_dst, dg_src->name);
467
468         /*get destination deformgroup*/
469         dg_dst= defgroup_find_name(ob_dst, dg_src->name);
470
471         /*get meshes*/
472         me_dst= ob_dst->data;
473
474         /*get derived mesh*/
475         dmesh_src= ob_src->derivedDeform;
476
477         /*make node tree*/
478         bvhtree_from_mesh_verts(&tree_mesh_src, dmesh_src, 0.0, 2, 6);
479
480         /*get vertex group arrays*/
481         ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
482         ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, FALSE);
483
484         /*get indexes of vertex groups*/
485         index_src= BLI_findindex(&ob_src->defbase, dg_src);
486         index_dst= BLI_findindex(&ob_dst->defbase, dg_dst);
487
488         /*get vertices*/
489         mv_dst= me_dst->mvert;
490
491         /* Loop through the vertices and copy weight from closest to destination*/
492         for(i=0; i < me_dst->totvert; i++, mv_dst++, dv_array_dst++) {
493                 /*Reset nearest*/
494                 nearest.index= -1;
495                 nearest.dist= FLT_MAX;
496
497                 /*Node tree accelerated search for closest vetex*/
498                 BLI_bvhtree_find_nearest(tree_mesh_src.tree, mv_dst->co, &nearest, tree_mesh_src.nearest_callback, &tree_mesh_src);
499
500                 /*copy weight*/
501                 dw_src= defvert_verify_index(dv_array_src[nearest.index], index_src);
502                 dw_dst= defvert_verify_index(*dv_array_dst, index_dst);
503                 dw_dst->weight = dw_src->weight;
504         }
505
506         free_bvhtree_from_mesh(&tree_mesh_src);
507
508         return 1;
509 }
510
511 /* for Mesh in Object mode */
512 /* allows editmode for Lattice */
513 static void ED_vgroup_nr_vert_add(Object *ob,
514                                   const int def_nr, const int vertnum,
515                                   const float weight, const int assignmode)
516 {
517         /* add the vert to the deform group with the
518          * specified number
519          */
520         MDeformVert *dvert= NULL;
521         int     tot;
522
523         /* get the vert */
524         ED_vgroup_give_array(ob->data, &dvert, &tot);
525         
526         if (dvert==NULL)
527                 return;
528
529         /* check that vertnum is valid before trying to get the relevant dvert */
530         if ((vertnum < 0) || (vertnum >= tot))
531                 return;
532
533
534         if (dvert) {
535                 MDeformVert *dv= &dvert[vertnum];
536                 MDeformWeight *dw;
537
538                 /* Lets first check to see if this vert is
539                  * already in the weight group -- if so
540                  * lets update it
541                  */
542
543                 dw= defvert_find_index(dv, def_nr);
544
545                 if (dw) {
546                         switch(assignmode) {
547                         case WEIGHT_REPLACE:
548                                 dw->weight = weight;
549                                 break;
550                         case WEIGHT_ADD:
551                                 dw->weight += weight;
552                                 if (dw->weight >= 1.0f)
553                                         dw->weight = 1.0f;
554                                 break;
555                         case WEIGHT_SUBTRACT:
556                                 dw->weight -= weight;
557                                 /* if the weight is zero or less then
558                                  * remove the vert from the deform group
559                                  */
560                                 if (dw->weight <= 0.0f) {
561                                         defvert_remove_group(dv, dw);
562                                 }
563                                 break;
564                         }
565                 }
566                 else {
567                         /* if the vert wasn't in the deform group then
568                          * we must take a different form of action ...
569                          */
570
571                         switch(assignmode) {
572                         case WEIGHT_SUBTRACT:
573                                 /* if we are subtracting then we don't
574                                  * need to do anything
575                                  */
576                                 return;
577
578                         case WEIGHT_REPLACE:
579                         case WEIGHT_ADD:
580                                 /* if we are doing an additive assignment, then
581                                  * we need to create the deform weight
582                                  */
583
584                                 /* we checked if the vertex was added before so no need to test again, simply add */
585                                 defvert_add_index_notest(dv, def_nr, weight);
586                         }
587                 }
588         }
589 }
590
591 /* called while not in editmode */
592 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
593 {
594         /* add the vert to the deform group with the
595          * specified assign mode
596          */
597         const int def_nr= BLI_findindex(&ob->defbase, dg);
598
599         MDeformVert *dv= NULL;
600         int tot;
601
602         /* get the deform group number, exit if
603          * it can't be found
604          */
605         if (def_nr < 0) return;
606
607         /* if there's no deform verts then create some,
608          */
609         if (ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
610                 ED_vgroup_data_create(ob->data);
611
612         /* call another function to do the work
613          */
614         ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
615 }
616
617 /* mesh object mode, lattice can be in editmode */
618 void ED_vgroup_vert_remove(Object *ob, bDeformGroup     *dg, int vertnum)
619 {
620         /* This routine removes the vertex from the specified
621          * deform group.
622          */
623
624         /* TODO, this is slow in a loop, better pass def_nr directly, but leave for later... - campbell */
625         const int def_nr= BLI_findindex(&ob->defbase, dg);
626
627         if (def_nr != -1) {
628                 MDeformVert *dvert= NULL;
629                 int tot;
630
631                 /* get the deform vertices corresponding to the
632                  * vertnum
633                  */
634                 ED_vgroup_give_array(ob->data, &dvert, &tot);
635
636                 if (dvert) {
637                         MDeformVert *dv= &dvert[vertnum];
638                         MDeformWeight *dw;
639
640                         dw= defvert_find_index(dv, def_nr);
641                         defvert_remove_group(dv, dw); /* dw can be NULL */
642                 }
643         }
644 }
645
646 static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
647 {
648         MDeformVert *dv= NULL;
649         BMVert *eve;
650         Mesh *me;
651
652         /* get the deform vertices corresponding to the vertnum */
653         if (ob->type==OB_MESH) {
654                 me= ob->data;
655
656                 if (me->edit_btmesh) {
657                         eve= BM_vert_at_index(me->edit_btmesh->bm, vertnum);
658                         if (!eve) {
659                                 return 0.0f;
660                         }
661                         dv= CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT);
662                 }
663                 else {
664                         if (vertnum >= me->totvert) {
665                                 return 0.0f;
666                         }
667                         dv = &me->dvert[vertnum];
668                 }
669         }
670         else if (ob->type==OB_LATTICE) {
671                 Lattice *lt= vgroup_edit_lattice(ob);
672
673                 if (lt->dvert) {
674                         if (vertnum >= lt->pntsu*lt->pntsv*lt->pntsw) {
675                                 return 0.0f;
676                         }
677                         dv = &lt->dvert[vertnum];
678                 }
679         }
680         
681         if (dv) {
682                 MDeformWeight *dw= defvert_find_index(dv, def_nr);
683                 if (dw) {
684                         return dw->weight;
685                 }
686         }
687
688         return -1;
689 }
690
691 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
692 {
693         const int def_nr= BLI_findindex(&ob->defbase, dg);
694
695         if (def_nr == -1) {
696                 return -1;
697         }
698
699         return get_vert_def_nr(ob, def_nr, vertnum);
700 }
701
702 void ED_vgroup_select_by_name(Object *ob, const char *name)
703 {       /* note: ob->actdef==0 signals on painting to create a new one, if a bone in posemode is selected */
704         ob->actdef= defgroup_name_index(ob, name) + 1;
705 }
706
707 /********************** Operator Implementations *********************/
708
709 /* only in editmode */
710 static void vgroup_select_verts(Object *ob, int select)
711 {
712         const int def_nr= ob->actdef-1;
713         MDeformVert *dv;
714
715         if (!BLI_findlink(&ob->defbase, def_nr)) {
716                 return;
717         }
718
719         if (ob->type == OB_MESH) {
720                 Mesh *me= ob->data;
721
722                 if (me->edit_btmesh) {
723                         BMEditMesh *em = me->edit_btmesh;
724                         BMIter iter;
725                         BMVert *eve;
726
727                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
728                                 if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
729                                         dv= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
730                                         if (defvert_find_index(dv, def_nr)) {
731                                                 BM_vert_select_set(em->bm, eve, select);
732                                         }
733                                 }
734                         }
735
736                         /* this has to be called, because this function operates on vertices only */
737                         if (select) EDBM_select_flush(em);      // vertices to edges/faces
738                         else EDBM_deselect_flush(em);
739                 }
740                 else {
741                         if (me->dvert) {
742                                 MVert *mv;
743                                 MDeformVert *dv;
744                                 int i;
745
746                                 mv = me->mvert;
747                                 dv = me->dvert;
748
749                                 for (i=0; i<me->totvert; i++, mv++, dv++) {
750                                         if (!(mv->flag & ME_HIDE)) {
751                                                 if (defvert_find_index(dv, def_nr)) {
752                                                         if (select)  mv->flag |=  SELECT;
753                                                         else         mv->flag &= ~SELECT;
754                                                 }
755                                         }
756                                 }
757
758                                 paintvert_flush_flags(ob);
759                         }
760                 }
761         }
762         else if (ob->type == OB_LATTICE) {
763                 Lattice *lt= vgroup_edit_lattice(ob);
764                 
765                 if (lt->dvert) {
766                         BPoint *bp;
767                         int a, tot;
768                         
769                         dv= lt->dvert;
770
771                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
772                         for (a=0, bp= lt->def; a<tot; a++, bp++, dv++) {
773                                 if (defvert_find_index(dv, def_nr)) {
774                                         if (select)  bp->f1 |=  SELECT;
775                                         else         bp->f1 &= ~SELECT;
776                                 }
777                         }
778                 }
779         }
780 }
781
782 static void vgroup_duplicate(Object *ob)
783 {
784         bDeformGroup *dg, *cdg;
785         char name[sizeof(dg->name)];
786         MDeformWeight *dw_org, *dw_cpy;
787         MDeformVert **dvert_array=NULL;
788         int i, idg, icdg, dvert_tot=0;
789
790         dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
791         if (!dg)
792                 return;
793         
794         if (!strstr(dg->name, "_copy")) {
795                 BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
796         }
797         else {
798                 BLI_snprintf(name, sizeof(name), "%s", dg->name);
799         }
800
801         cdg = defgroup_duplicate(dg);
802         BLI_strncpy(cdg->name, name, sizeof(cdg->name));
803         defgroup_unique_name(cdg, ob);
804
805         BLI_addtail(&ob->defbase, cdg);
806
807         idg = (ob->actdef-1);
808         ob->actdef = BLI_countlist(&ob->defbase);
809         icdg = (ob->actdef-1);
810
811         /* TODO, we might want to allow only copy selected verts here? - campbell */
812         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, FALSE);
813
814         if (dvert_array) {
815                 for (i = 0; i < dvert_tot; i++) {
816                         MDeformVert *dv= dvert_array[i];
817                         dw_org = defvert_find_index(dv, idg);
818                         if (dw_org) {
819                                 /* defvert_verify_index re-allocs org so need to store the weight first */
820                                 dw_cpy = defvert_verify_index(dv, icdg);
821                                 dw_cpy->weight = dw_org->weight;
822                         }
823                 }
824
825                 MEM_freeN(dvert_array);
826         }
827 }
828
829 static void vgroup_normalize(Object *ob)
830 {
831         MDeformWeight *dw;
832         MDeformVert *dv, **dvert_array=NULL;
833         int i, dvert_tot=0;
834         const int def_nr= ob->actdef-1;
835
836         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
837
838         if (!BLI_findlink(&ob->defbase, def_nr)) {
839                 return;
840         }
841
842         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
843
844         if (dvert_array) {
845                 float weight_max = 0.0f;
846
847                 for (i = 0; i < dvert_tot; i++) {
848
849                         /* in case its not selected */
850                         if (!(dv = dvert_array[i])) {
851                                 continue;
852                         }
853
854                         dw = defvert_find_index(dv, def_nr);
855                         if (dw) {
856                                 weight_max = MAX2(dw->weight, weight_max);
857                         }
858                 }
859
860                 if (weight_max > 0.0f) {
861                         for (i = 0; i < dvert_tot; i++) {
862                                 
863                                 /* in case its not selected */
864                                 if (!(dv = dvert_array[i])) {
865                                         continue;
866                                 }
867
868                                 dw = defvert_find_index(dv, def_nr);
869                                 if (dw) {
870                                         dw->weight /= weight_max;
871                                         
872                                         /* in case of division errors with very low weights */
873                                         CLAMP(dw->weight, 0.0f, 1.0f);
874                                 }
875                         }
876                 }
877
878                 MEM_freeN(dvert_array);
879         }
880 }
881
882 /* This finds all of the vertices face-connected to vert by an edge and returns a
883  * MEM_allocated array of indices of size count.
884  * count is an int passed by reference so it can be assigned the value of the length here. */
885 static int* getSurroundingVerts(Mesh *me, int vert, int *count)
886 {
887         MPoly *mp = me->mpoly;
888         int i = me->totpoly;
889         /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
890          * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
891          * many vertices face-linked to another one, even 8 might be too high...). */
892         int *verts = NULL;
893         BLI_array_declare(verts);
894
895         BLI_array_reserve(verts, 8);
896         while (i--) {
897                 int j = mp->totloop;
898                 int first_l = mp->totloop - 1;
899                 MLoop *ml = &me->mloop[mp->loopstart];
900                 while (j--) {
901                         /* XXX This assume a vert can only be once in a poly, even though
902                          *     it seems logical to me, not totally sure of that. */
903                         if (ml->v == vert) {
904                                 int a, b, k;
905                                 if (j == first_l) {
906                                         /* We are on the first corner. */
907                                         a = ml[1].v;
908                                         b = ml[j].v;
909                                 }
910                                 else if (!j) {
911                                         /* We are on the last corner. */
912                                         a = (ml-1)->v;
913                                         b = me->mloop[mp->loopstart].v;
914                                 }
915                                 else {
916                                         a = (ml-1)->v;
917                                         b = (ml+1)->v;
918                                 }
919
920                                 /* Append a and b verts to array, if not yet present. */
921                                 k = BLI_array_count(verts);
922                                 /* XXX Maybe a == b is enough? */
923                                 while (k-- && !(a == b && a == -1)) {
924                                         if (verts[k] == a)
925                                                 a = -1;
926                                         else if (verts[k] == b)
927                                                 b = -1;
928                                 }
929                                 if (a != -1)
930                                         BLI_array_append(verts, a);
931                                 if (b != -1)
932                                         BLI_array_append(verts, b);
933
934                                 /* Vert found in this poly, we can go to next one! */
935                                 break;
936                         }
937                         ml++;
938                 }
939                 mp++;
940         }
941
942         /* Do not free the array! */
943         *count = BLI_array_count(verts);
944         return verts;
945 }
946
947 /* get a single point in space by averaging a point cloud (vectors of size 3)
948  * coord is the place the average is stored, points is the point cloud, count is the number of points in the cloud
949  */
950 static void getSingleCoordinate(MVert *points, int count, float coord[3])
951 {
952         int i;
953         zero_v3(coord);
954         for (i = 0; i < count; i++) {
955                 add_v3_v3(coord, points[i].co);
956         }
957         mul_v3_fl(coord, 1.0f/count);
958 }
959
960 /* given a plane and a start and end position,
961  * compute the amount of vertical distance relative to the plane and store it in dists,
962  * then get the horizontal and vertical change and store them in changes
963  */
964 static void getVerticalAndHorizontalChange(const float norm[3], float d, const float coord[3],
965                                            const float start[3], float distToStart,
966                                            float *end, float (*changes)[2], float *dists, int index)
967 {
968         // A=Q-((Q-P).N)N
969         // D = (a*x0 + b*y0 +c*z0 +d)
970         float projA[3], projB[3];
971
972         closest_to_plane_v3(projA, coord, norm, start);
973         closest_to_plane_v3(projB, coord, norm, end);
974         // (vertical and horizontal refer to the plane's y and xz respectively)
975         // vertical distance
976         dists[index] = dot_v3v3(norm, end) + d;
977         // vertical change
978         changes[index][0] = dists[index] - distToStart;
979         //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]);
980         // horizontal change
981         changes[index][1] = len_v3v3(projA, projB);
982 }
983
984 // I need the derived mesh to be forgotten so the positions are recalculated with weight changes (see dm_deform_recalc)
985 static void dm_deform_clear(DerivedMesh *dm, Object *ob)
986 {
987         if (ob->derivedDeform && (ob->derivedDeform)==dm) {
988                 ob->derivedDeform->needsFree = 1;
989                 ob->derivedDeform->release(ob->derivedDeform);
990                 ob->derivedDeform = NULL;
991         }
992         else if (dm) {
993                 dm->needsFree = 1;
994                 dm->release(dm);
995         }
996 }
997
998 /* recalculate the deformation */
999 static DerivedMesh* dm_deform_recalc(Scene *scene, Object *ob)
1000 {
1001         return mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
1002 }
1003
1004 /* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
1005  * distToBe distance away from the provided plane strength can change distToBe so that it moves
1006  * towards distToBe by that percentage cp changes how much the weights are adjusted
1007  * to check the distance
1008  *
1009  * index is the index of the vertex being moved
1010  * norm and d are the plane's properties for the equation: ax + by + cz + d = 0
1011  * coord is a point on the plane
1012  */
1013 static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
1014                                           float coord[3], float d, float distToBe, float strength, float cp)
1015 {
1016         DerivedMesh *dm;
1017         MDeformWeight *dw;
1018         MVert m;
1019         MDeformVert *dvert = me->dvert+index;
1020         int totweight = dvert->totweight;
1021         float oldw = 0;
1022         float oldPos[3] = {0};
1023         float vc, hc, dist = 0.0f;
1024         int i, k;
1025         float (*changes)[2] = MEM_mallocN(sizeof(float *)*totweight*2, "vertHorzChange");
1026         float *dists = MEM_mallocN(sizeof(float)*totweight, "distance");
1027
1028         /* track if up or down moved it closer for each bone */
1029         int *upDown = MEM_callocN(sizeof(int)*totweight, "upDownTracker");
1030
1031         int *dwIndices = MEM_callocN(sizeof(int)*totweight, "dwIndexTracker");
1032         float distToStart;
1033         int bestIndex = 0;
1034         char wasChange;
1035         char wasUp;
1036         int lastIndex = -1;
1037         float originalDistToBe = distToBe;
1038         do {
1039                 wasChange = FALSE;
1040                 dm = dm_deform_recalc(scene, ob);
1041                 dm->getVert(dm, index, &m);
1042                 copy_v3_v3(oldPos, m.co);
1043                 distToStart = dot_v3v3(norm, oldPos) + d;
1044
1045                 if (distToBe == originalDistToBe) {
1046                         distToBe += distToStart - distToStart*strength;
1047                 }
1048                 for (i = 0; i < totweight; i++) {
1049                         dwIndices[i] = i;
1050                         dw = (dvert->dw+i);
1051                         vc = hc = 0;
1052                         if (!dw->weight) {
1053                                 changes[i][0] = 0;
1054                                 changes[i][1] = 0;
1055                                 dists[i] = distToStart;
1056                                 continue;
1057                         }
1058                         for (k = 0; k < 2; k++) {
1059                                 if (dm) {
1060                                         dm_deform_clear(dm, ob); dm = NULL;
1061                                 }
1062                                 oldw = dw->weight;
1063                                 if (k) {
1064                                         dw->weight *= 1+cp;
1065                                 }
1066                                 else {
1067                                         dw->weight /= 1+cp;
1068                                 }
1069                                 if (dw->weight == oldw) {
1070                                         changes[i][0] = 0;
1071                                         changes[i][1] = 0;
1072                                         dists[i] = distToStart;
1073                                         break;
1074                                 }
1075                                 if (dw->weight > 1) {
1076                                         dw->weight = 1;
1077                                 }
1078                                 dm = dm_deform_recalc(scene, ob);
1079                                 dm->getVert(dm, index, &m);
1080                                 getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
1081                                 dw->weight = oldw;
1082                                 if (!k) {
1083                                         vc = changes[i][0];
1084                                         hc = changes[i][1];
1085                                         dist = dists[i];
1086                                 }
1087                                 else {
1088                                         if (fabs(dist - distToBe) < fabs(dists[i] - distToBe)) {
1089                                                 upDown[i] = 0;
1090                                                 changes[i][0] = vc;
1091                                                 changes[i][1] = hc;
1092                                                 dists[i] = dist;
1093                                         }
1094                                         else {
1095                                                 upDown[i] = 1;
1096                                         }
1097                                         if (fabs(dists[i] - distToBe) > fabs(distToStart - distToBe)) {
1098                                                 changes[i][0] = 0;
1099                                                 changes[i][1] = 0;
1100                                                 dists[i] = distToStart;
1101                                         }
1102                                 }
1103                         }
1104                 }
1105                 // sort the changes by the vertical change
1106                 for (k = 0; k < totweight; k++) {
1107                         float tf;
1108                         int ti;
1109                         bestIndex = k;
1110                         for (i = k+1; i < totweight; i++) {
1111                                 dist = dists[i];
1112
1113                                 if (fabs(dist) > fabs(dists[i])) {
1114                                         bestIndex = i;
1115                                 }
1116                         }
1117                         // switch with k
1118                         if (bestIndex != k) {
1119                                 ti = upDown[k];
1120                                 upDown[k] = upDown[bestIndex];
1121                                 upDown[bestIndex] = ti;
1122
1123                                 ti = dwIndices[k];
1124                                 dwIndices[k] = dwIndices[bestIndex];
1125                                 dwIndices[bestIndex] = ti;
1126
1127                                 tf = changes[k][0];
1128                                 changes[k][0] = changes[bestIndex][0];
1129                                 changes[bestIndex][0] = tf;
1130
1131                                 tf = changes[k][1];
1132                                 changes[k][1] = changes[bestIndex][1];
1133                                 changes[bestIndex][1] = tf;
1134
1135                                 tf = dists[k];
1136                                 dists[k] = dists[bestIndex];
1137                                 dists[bestIndex] = tf;
1138                         }
1139                 }
1140                 bestIndex = -1;
1141                 // find the best change with an acceptable horizontal change
1142                 for (i = 0; i < totweight; i++) {
1143                         if (fabs(changes[i][0]) > fabs(changes[i][1]*2.0f)) {
1144                                 bestIndex = i;
1145                                 break;
1146                         }
1147                 }
1148                 if (bestIndex != -1) {
1149                         wasChange = TRUE;
1150                         // it is a good place to stop if it tries to move the opposite direction
1151                         // (relative to the plane) of last time
1152                         if (lastIndex != -1) {
1153                                 if (wasUp != upDown[bestIndex]) {
1154                                         wasChange = FALSE;
1155                                 }
1156                         }
1157                         lastIndex = bestIndex;
1158                         wasUp = upDown[bestIndex];
1159                         dw = (dvert->dw+dwIndices[bestIndex]);
1160                         oldw = dw->weight;
1161                         if (upDown[bestIndex]) {
1162                                 dw->weight *= 1+cp;
1163                         }
1164                         else {
1165                                 dw->weight /= 1+cp;
1166                         }
1167                         if (dw->weight > 1) {
1168                                 dw->weight = 1;
1169                         }
1170                         if (oldw == dw->weight) {
1171                                 wasChange = FALSE;
1172                         }
1173                         if (dm) {
1174                                 dm_deform_clear(dm, ob); dm = NULL;
1175                         }
1176                 }
1177         } while (wasChange && (distToStart-distToBe)/fabsf(distToStart-distToBe) ==
1178                              (dists[bestIndex]-distToBe)/fabsf(dists[bestIndex]-distToBe));
1179         MEM_freeN(upDown);
1180         MEM_freeN(changes);
1181         MEM_freeN(dists);
1182         MEM_freeN(dwIndices);
1183 }
1184
1185 /* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex 
1186  * but it could be used to raise or lower an existing 'bump.' */
1187 static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength, float cp)
1188 {
1189         int i;
1190
1191         Mesh *me = ob->data;
1192         MVert *mvert = me->mvert;
1193         int *verts = NULL;
1194         if (!(me->editflag & ME_EDIT_VERT_SEL))
1195                 return;
1196         for (i = 0; i < me->totvert && mvert; i++, mvert++) {
1197                 if (mvert->flag & SELECT) {
1198                         int count=0;
1199                         if ((verts = getSurroundingVerts(me, i, &count))) {
1200                                 MVert m;
1201                                 MVert *p = MEM_callocN(sizeof(MVert)*(count), "deformedPoints");
1202                                 int k;
1203
1204                                 DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
1205                                 k = count;
1206                                 while (k--) {
1207                                         dm->getVert(dm, verts[k], &m);
1208                                         p[k] = m;
1209                                 }
1210                                 
1211                                 if (count >= 3) {
1212                                         float d /*, dist */ /* UNUSED */, mag;
1213                                         float coord[3];
1214                                         float norm[3];
1215                                         getSingleCoordinate(p, count, coord);
1216                                         dm->getVert(dm, i, &m);
1217                                         sub_v3_v3v3(norm, m.co, coord);
1218                                         mag= normalize_v3(norm);
1219                                         if (mag) { /* zeros fix */
1220                                                 d = -dot_v3v3(norm, coord);
1221                                                 /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
1222                                                 moveCloserToDistanceFromPlane(scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
1223                                         }
1224                                 }
1225
1226                                 MEM_freeN(verts);
1227                                 MEM_freeN(p);
1228                         }
1229                 }
1230         }
1231 }
1232
1233 static void vgroup_levels(Object *ob, float offset, float gain)
1234 {
1235         MDeformWeight *dw;
1236         MDeformVert *dv, **dvert_array=NULL;
1237         int i, dvert_tot=0;
1238         const int def_nr= ob->actdef-1;
1239
1240         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
1241
1242         if (!BLI_findlink(&ob->defbase, def_nr)) {
1243                 return;
1244         }
1245
1246         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1247
1248         if (dvert_array) {
1249                 for (i = 0; i < dvert_tot; i++) {
1250
1251                         /* in case its not selected */
1252                         if (!(dv = dvert_array[i])) {
1253                                 continue;
1254                         }
1255
1256                         dw = defvert_find_index(dv, def_nr);
1257                         if (dw) {
1258                                 dw->weight = gain * (dw->weight + offset);
1259
1260                                 CLAMP(dw->weight, 0.0f, 1.0f);
1261                         }
1262                 }
1263
1264                 MEM_freeN(dvert_array);
1265         }
1266 }
1267
1268 /* TODO - select between groups */
1269 static void vgroup_normalize_all(Object *ob, int lock_active)
1270 {
1271         MDeformVert *dv, **dvert_array=NULL;
1272         int i, dvert_tot=0;
1273         const int def_nr= ob->actdef-1;
1274
1275         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
1276
1277         if (lock_active && !BLI_findlink(&ob->defbase, def_nr)) {
1278                 return;
1279         }
1280
1281         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1282
1283         if (dvert_array) {
1284                 if (lock_active) {
1285
1286                         for (i = 0; i < dvert_tot; i++) {
1287                                 /* in case its not selected */
1288                                 if (!(dv = dvert_array[i])) {
1289                                         continue;
1290                                 }
1291
1292                                 defvert_normalize_lock(dv, def_nr);
1293                         }
1294                 }
1295                 else {
1296                         for (i = 0; i < dvert_tot; i++) {
1297
1298                                 /* in case its not selected */
1299                                 if (!(dv = dvert_array[i])) {
1300                                         continue;
1301                                 }
1302
1303                                 defvert_normalize(dv);
1304                         }
1305                 }
1306
1307                 MEM_freeN(dvert_array);
1308         }
1309 }
1310
1311 static void vgroup_lock_all(Object *ob, int action)
1312 {
1313         bDeformGroup *dg;
1314
1315         if (action == SEL_TOGGLE) {
1316                 action= SEL_SELECT;
1317                 for (dg= ob->defbase.first; dg; dg= dg->next) {
1318                         if (dg->flag & DG_LOCK_WEIGHT) {
1319                                 action= SEL_DESELECT;
1320                                 break;
1321                         }
1322                 }
1323         }
1324
1325         for (dg= ob->defbase.first; dg; dg= dg->next) {
1326                 switch(action) {
1327                         case SEL_SELECT:
1328                                 dg->flag |= DG_LOCK_WEIGHT;
1329                                 break;
1330                         case SEL_DESELECT:
1331                                 dg->flag &= ~DG_LOCK_WEIGHT;
1332                                 break;
1333                         case SEL_INVERT:
1334                                 dg->flag ^= DG_LOCK_WEIGHT;
1335                                 break;
1336                 }
1337         }
1338 }
1339
1340 static void vgroup_invert(Object *ob, const short auto_assign, const short auto_remove)
1341 {
1342         MDeformWeight *dw;
1343         MDeformVert *dv, **dvert_array=NULL;
1344         int i, dvert_tot=0;
1345         const int def_nr= ob->actdef-1;
1346         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
1347
1348         if (!BLI_findlink(&ob->defbase, def_nr)) {
1349                 return;
1350         }
1351
1352         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1353
1354         if (dvert_array) {
1355                 for (i = 0; i < dvert_tot; i++) {
1356
1357                         /* in case its not selected */
1358                         if (!(dv = dvert_array[i])) {
1359                                 continue;
1360                         }
1361
1362                         if (auto_assign) {
1363                                 dw= defvert_verify_index(dv, def_nr);
1364                         }
1365                         else {
1366                                 dw= defvert_find_index(dv, def_nr);
1367                         }
1368
1369                         if (dw) {
1370                                 dw->weight = 1.0f - dw->weight;
1371
1372                                 if (auto_remove && dw->weight <= 0.0f) {
1373                                         defvert_remove_group(dv, dw);
1374                                 }
1375                         }
1376                 }
1377
1378                 MEM_freeN(dvert_array);
1379         }
1380 }
1381
1382 static void vgroup_blend(Object *ob, const float fac)
1383 {
1384         MDeformVert *dv;
1385         MDeformWeight *dw;
1386         int i, dvert_tot=0;
1387         const int def_nr= ob->actdef - 1;
1388
1389         BLI_assert(fac >= 0.0 && fac <= 1.0f);
1390
1391         if (ob->type != OB_MESH) {
1392                 return;
1393         }
1394
1395         if (BLI_findlink(&ob->defbase, def_nr)) {
1396                 const float ifac = 1.0f - fac;
1397
1398                 BMEditMesh *em = BMEdit_FromObject(ob);
1399                 BMesh *bm = em ? em->bm : NULL;
1400                 Mesh  *me = em ? NULL   : ob->data;
1401
1402                 /* bmesh only*/
1403                 BMEdge *eed;
1404                 BMVert *eve;
1405                 BMIter iter;
1406
1407                 /* mesh only */
1408                 MDeformVert *dvert_array = NULL;
1409
1410
1411                 float *vg_weights;
1412                 float *vg_users;
1413                 int sel1, sel2;
1414
1415                 if (bm) {
1416                         BM_mesh_elem_index_ensure(bm, BM_VERT);
1417                         dvert_tot = bm->totvert;
1418                 }
1419                 else {
1420                         dvert_tot = me->totvert;
1421                         dvert_array = me->dvert;
1422                 }
1423
1424                 vg_weights = MEM_callocN(sizeof(float) * dvert_tot, "vgroup_blend_f");
1425                 vg_users = MEM_callocN(sizeof(int) * dvert_tot, "vgroup_blend_i");
1426
1427                 if (bm) {
1428                         BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1429                                 sel1 = BM_elem_flag_test(eed->v1, BM_ELEM_SELECT);
1430                                 sel2 = BM_elem_flag_test(eed->v2, BM_ELEM_SELECT);
1431
1432                                 if (sel1 != sel2) {
1433                                         int i1 /* , i2 */;
1434                                         /* i1 is always the selected one */
1435                                         if (sel1) {
1436                                                 i1= BM_elem_index_get(eed->v1);
1437                                                 /* i2= BM_elem_index_get(eed->v2); */ /* UNUSED */
1438                                                 eve= eed->v2;
1439                                         }
1440                                         else {
1441                                                 /* i2= BM_elem_index_get(eed->v1); */ /* UNUSED */
1442                                                 i1= BM_elem_index_get(eed->v2);
1443                                                 eve= eed->v1;
1444                                         }
1445
1446                                         dv = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT);
1447                                         dw = defvert_find_index(dv, def_nr);
1448                                         if (dw) {
1449                                                 vg_weights[i1] += dw->weight;
1450                                         }
1451                                         vg_users[i1]++;
1452                                 }
1453                         }
1454
1455                         BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
1456                                 if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && vg_users[i] > 0) {
1457                                         dv = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT);
1458
1459                                         dw = defvert_verify_index(dv, def_nr);
1460                                         dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
1461                                         /* in case of division errors */
1462                                         CLAMP(dw->weight, 0.0f, 1.0f);
1463                                 }
1464                         }
1465                 }
1466                 else {
1467                         MEdge *ed = me->medge;
1468                         MVert *mv;
1469
1470                         for (i = 0; i < me->totedge; i++, ed++) {
1471                                 sel1 = me->mvert[ed->v1].flag & SELECT;
1472                                 sel2 = me->mvert[ed->v2].flag & SELECT;
1473
1474                                 if (sel1 != sel2) {
1475                                         int i1, i2;
1476                                         /* i1 is always the selected one */
1477                                         if (sel1) {
1478                                                 i1 = ed->v1;
1479                                                 i2 = ed->v2;
1480                                         }
1481                                         else {
1482                                                 i2 = ed->v1;
1483                                                 i1 = ed->v2;
1484                                         }
1485
1486                                         dv = &dvert_array[i2];
1487                                         dw = defvert_find_index(dv, def_nr);
1488                                         if (dw) {
1489                                                 vg_weights[i1] += dw->weight;
1490                                         }
1491                                         vg_users[i1]++;
1492                                 }
1493                         }
1494
1495                         mv = me->mvert;
1496                         dv = dvert_array;
1497
1498                         for (i = 0; i < dvert_tot; i++, mv++, dv++) {
1499                                 if ((mv->flag & SELECT) && (vg_users[i] > 0)) {
1500                                         dw = defvert_verify_index(dv, def_nr);
1501                                         dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
1502
1503                                         /* in case of division errors */
1504                                         CLAMP(dw->weight, 0.0f, 1.0f);
1505                                 }
1506                         }
1507                 }
1508
1509                 MEM_freeN(vg_weights);
1510                 MEM_freeN(vg_users);
1511         }
1512 }
1513
1514 static void vgroup_clean(Object *ob, const float epsilon, int keep_single)
1515 {
1516         MDeformWeight *dw;
1517         MDeformVert *dv, **dvert_array=NULL;
1518         int i, dvert_tot=0;
1519         const int def_nr= ob->actdef-1;
1520         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
1521
1522         if (!BLI_findlink(&ob->defbase, def_nr)) {
1523                 return;
1524         }
1525
1526         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1527
1528         if (dvert_array) {
1529                 /* only the active group */
1530                 for (i = 0; i < dvert_tot; i++) {
1531
1532                         /* in case its not selected */
1533                         if (!(dv = dvert_array[i])) {
1534                                 continue;
1535                         }
1536
1537                         dw= defvert_find_index(dv, def_nr);
1538
1539                         if (dw) {
1540                                 if (dw->weight <= epsilon) {
1541                                         if (keep_single==FALSE || dv->totweight > 1) {
1542                                                 defvert_remove_group(dv, dw); /* dw can be NULL */
1543                                         }
1544                                 }
1545                         }
1546                 }
1547
1548                 MEM_freeN(dvert_array);
1549         }
1550 }
1551
1552 static void vgroup_clean_all(Object *ob, const float epsilon, const int keep_single)
1553 {
1554         MDeformVert **dvert_array=NULL;
1555         int i, dvert_tot = 0;
1556         const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0;
1557
1558         ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1559
1560         if (dvert_array) {
1561                 MDeformVert *dv;
1562                 MDeformWeight *dw;
1563
1564                 for (i = 0; i < dvert_tot; i++) {
1565                         int j;
1566
1567                         /* in case its not selected */
1568                         if (!(dv = dvert_array[i])) {
1569                                 continue;
1570                         }
1571
1572                         j= dv->totweight;
1573
1574                         while (j--) {
1575
1576                                 if (keep_single && dv->totweight == 1)
1577                                         break;
1578
1579                                 dw= dv->dw + j;
1580
1581                                 if (dw->weight <= epsilon) {
1582                                         defvert_remove_group(dv, dw);
1583                                 }
1584                         }
1585                 }
1586
1587                 MEM_freeN(dvert_array);
1588         }
1589 }
1590
1591
1592 static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
1593                             const char sel, const char sel_mirr,
1594                             const int *flip_map, const int flip_map_len,
1595                             const short mirror_weights, const short flip_vgroups,
1596                             const short all_vgroups, const int act_vgroup)
1597 {
1598         BLI_assert(sel || sel_mirr);
1599
1600         if (sel_mirr && sel) {
1601                 /* swap */
1602                 if (mirror_weights) {
1603                         if (all_vgroups) {
1604                                 SWAP(MDeformVert, *dvert, *dvert_mirr);
1605                         }
1606                         else {
1607                                 MDeformWeight *dw=      defvert_find_index(dvert, act_vgroup);
1608                                 MDeformWeight *dw_mirr= defvert_find_index(dvert_mirr, act_vgroup);
1609
1610                                 if (dw || dw_mirr) {
1611                                         if (dw_mirr == NULL)
1612                                                 dw_mirr= defvert_verify_index(dvert_mirr, act_vgroup);
1613                                         if (dw == NULL)
1614                                                 dw= defvert_verify_index(dvert, act_vgroup);
1615
1616                                         SWAP(float, dw->weight, dw_mirr->weight);
1617                                 }
1618                         }
1619                 }
1620
1621                 if (flip_vgroups) {
1622                         defvert_flip(dvert, flip_map, flip_map_len);
1623                         defvert_flip(dvert_mirr, flip_map, flip_map_len);
1624                 }
1625         }
1626         else {
1627                 /* dvert should always be the target, only swaps pointer */
1628                 if (sel_mirr) {
1629                         SWAP(MDeformVert *, dvert, dvert_mirr);
1630                 }
1631
1632                 if (mirror_weights) {
1633                         if (all_vgroups) {
1634                                 defvert_copy(dvert, dvert_mirr);
1635                         }
1636                         else {
1637                                 defvert_copy_index(dvert, dvert_mirr, act_vgroup);
1638                         }
1639                 }
1640
1641                 /* flip map already modified for 'all_vgroups' */
1642                 if (flip_vgroups) {
1643                         defvert_flip(dvert, flip_map, flip_map_len);
1644                 }
1645         }
1646 }
1647
1648 /* TODO, vgroup locking */
1649 /* TODO, face masking */
1650 void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups)
1651 {
1652
1653 #define VGROUP_MIRR_OP                                                        \
1654         dvert_mirror_op(dvert, dvert_mirr,                                    \
1655                         sel, sel_mirr,                                        \
1656                         flip_map, flip_map_len,                               \
1657                         mirror_weights, flip_vgroups,                         \
1658                         all_vgroups, def_nr                                   \
1659                         )
1660
1661         BMVert *eve, *eve_mirr;
1662         MDeformVert *dvert, *dvert_mirr;
1663         short sel, sel_mirr;
1664         int     *flip_map, flip_map_len;
1665         const int def_nr= ob->actdef-1;
1666
1667         if ( (mirror_weights==0 && flip_vgroups==0) ||
1668              (BLI_findlink(&ob->defbase, def_nr) == NULL) )
1669         {
1670                 return;
1671         }
1672
1673         if (flip_vgroups) {
1674                 flip_map= all_vgroups ?
1675                                         defgroup_flip_map(ob, &flip_map_len, FALSE) :
1676                                         defgroup_flip_map_single(ob, &flip_map_len, FALSE, def_nr);
1677
1678                 BLI_assert(flip_map != NULL);
1679
1680                 if (flip_map == NULL) {
1681                         /* something went wrong!, possibly no groups */
1682                         return;
1683                 }
1684         }
1685         else {
1686                 flip_map= NULL;
1687                 flip_map_len= 0;
1688         }
1689
1690         /* only the active group */
1691         if (ob->type == OB_MESH) {
1692                 Mesh *me= ob->data;
1693                 BMEditMesh *em = me->edit_btmesh;
1694
1695                 if (em) {
1696                         BMIter iter;
1697
1698                         if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) {
1699                                 goto cleanup;
1700                         }
1701
1702                         EDBM_verts_mirror_cache_begin(em, FALSE);
1703
1704                         /* Go through the list of editverts and assign them */
1705                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1706                                 if ((eve_mirr= EDBM_verts_mirror_get(em, eve))) {
1707                                         sel= BM_elem_flag_test(eve, BM_ELEM_SELECT);
1708                                         sel_mirr= BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
1709
1710                                         if ((sel || sel_mirr) && (eve != eve_mirr)) {
1711                                                 dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1712                                                 dvert_mirr= CustomData_bmesh_get(&em->bm->vdata, eve_mirr->head.data, CD_MDEFORMVERT);
1713                                                 if (dvert && dvert_mirr) {
1714                                                         VGROUP_MIRR_OP;
1715                                                 }
1716                                         }
1717
1718                                         /* don't use these again */
1719                                         EDBM_verts_mirror_cache_clear(em, eve);
1720                                         EDBM_verts_mirror_cache_clear(em, eve_mirr);
1721                                 }
1722                         }
1723                         EDBM_verts_mirror_cache_end(em);
1724                 }
1725                 else {
1726                         /* object mode / weight paint */
1727                         MVert *mv, *mv_mirr;
1728                         int vidx, vidx_mirr;
1729                         const int use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
1730
1731                         if (me->dvert == NULL) {
1732                                 goto cleanup;
1733                         }
1734
1735                         if (!use_vert_sel) {
1736                                 sel= sel_mirr= TRUE;
1737                         }
1738
1739                         /* tag verts we have used */
1740                         for (vidx= 0, mv= me->mvert; vidx < me->totvert; vidx++, mv++) {
1741                                 mv->flag &= ~ME_VERT_TMP_TAG;
1742                         }
1743
1744                         for (vidx= 0, mv= me->mvert; vidx < me->totvert; vidx++, mv++) {
1745                                 if (    ((mv->flag & ME_VERT_TMP_TAG) == 0) &&
1746                                         ((vidx_mirr= mesh_get_x_mirror_vert(ob, vidx)) != -1) &&
1747                                         (vidx != vidx_mirr) &&
1748                                         ((((mv_mirr= me->mvert + vidx_mirr)->flag) & ME_VERT_TMP_TAG) == 0))
1749                                 {
1750
1751                                         if (use_vert_sel) {
1752                                                 sel= mv->flag & SELECT;
1753                                                 sel_mirr= mv_mirr->flag & SELECT;
1754                                         }
1755
1756                                         if (sel || sel_mirr) {
1757                                                 dvert= &me->dvert[vidx];
1758                                                 dvert_mirr= &me->dvert[vidx_mirr];
1759
1760                                                 VGROUP_MIRR_OP;
1761                                         }
1762
1763                                         mv->flag |= ME_VERT_TMP_TAG;
1764                                         mv_mirr->flag |= ME_VERT_TMP_TAG;
1765                                 }
1766                         }
1767                 }
1768         }
1769         else if (ob->type == OB_LATTICE) {
1770                 Lattice *lt= vgroup_edit_lattice(ob);
1771                 int i1, i2;
1772                 int u, v, w;
1773                 int pntsu_half;
1774                 /* half but found up odd value */
1775
1776                 if (lt->pntsu == 1 || lt->dvert == NULL) {
1777                         goto cleanup;
1778                 }
1779
1780                 /* unlike editmesh we know that by only looping over the first half of
1781                  * the 'u' indices it will cover all points except the middle which is
1782                  * ok in this case */
1783                 pntsu_half= lt->pntsu / 2;
1784
1785                 for (w=0; w<lt->pntsw; w++) {
1786                         for (v=0; v<lt->pntsv; v++) {
1787                                 for (u=0; u<pntsu_half; u++) {
1788                                         int u_inv= (lt->pntsu - 1) - u;
1789                                         if (u != u_inv) {
1790                                                 BPoint *bp, *bp_mirr;
1791
1792                                                 i1= LT_INDEX(lt, u, v, w);
1793                                                 i2= LT_INDEX(lt, u_inv, v, w);
1794
1795                                                 bp= &lt->def[i1];
1796                                                 bp_mirr= &lt->def[i2];
1797
1798                                                 sel= bp->f1 & SELECT;
1799                                                 sel_mirr= bp_mirr->f1 & SELECT;
1800
1801                                                 if (sel || sel_mirr) {
1802                                                         dvert= &lt->dvert[i1];
1803                                                         dvert_mirr= &lt->dvert[i2];
1804
1805                                                         VGROUP_MIRR_OP;
1806                                                 }
1807                                         }
1808                                 }
1809                         }
1810                 }
1811         }
1812
1813 cleanup:
1814         if (flip_map) MEM_freeN(flip_map);
1815
1816 #undef VGROUP_MIRR_OP
1817
1818 }
1819
1820 static void vgroup_remap_update_users(Object *ob, int *map)
1821 {
1822         ExplodeModifierData *emd;
1823         ModifierData *md;
1824         ParticleSystem *psys;
1825         ClothModifierData *clmd;
1826         ClothSimSettings *clsim;
1827         int a;
1828
1829         /* these cases don't use names to refer to vertex groups, so when
1830          * they get deleted the numbers get out of sync, this corrects that */
1831
1832         if (ob->soft)
1833                 ob->soft->vertgroup= map[ob->soft->vertgroup];
1834
1835         for (md=ob->modifiers.first; md; md=md->next) {
1836                 if (md->type == eModifierType_Explode) {
1837                         emd= (ExplodeModifierData*)md;
1838                         emd->vgroup= map[emd->vgroup];
1839                 }
1840                 else if (md->type == eModifierType_Cloth) {
1841                         clmd= (ClothModifierData*)md;
1842                         clsim= clmd->sim_parms;
1843
1844                         if (clsim) {
1845                                 clsim->vgroup_mass= map[clsim->vgroup_mass];
1846                                 clsim->vgroup_bend= map[clsim->vgroup_bend];
1847                                 clsim->vgroup_struct= map[clsim->vgroup_struct];
1848                         }
1849                 }
1850         }
1851
1852         for (psys=ob->particlesystem.first; psys; psys=psys->next) {
1853                 for (a=0; a<PSYS_TOT_VG; a++)
1854                         psys->vgroup[a]= map[psys->vgroup[a]];
1855         }
1856 }
1857
1858
1859 static void vgroup_delete_update_users(Object *ob, int id)
1860 {
1861         int i, defbase_tot= BLI_countlist(&ob->defbase) + 1;
1862         int *map= MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del");
1863
1864         map[id]= map[0]= 0;
1865         for (i=1; i<id; i++) map[i]=i;
1866         for (i=id+1; i<defbase_tot; i++) map[i]=i-1;
1867
1868         vgroup_remap_update_users(ob, map);
1869         MEM_freeN(map);
1870 }
1871
1872
1873 static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg)
1874 {
1875         MDeformVert *dvert_array=NULL;
1876         int dvert_tot=0;
1877         const int def_nr= BLI_findindex(&ob->defbase, dg);
1878
1879         assert(def_nr > -1);
1880
1881         ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
1882
1883         if (dvert_array) {
1884                 int i, j;
1885                 MDeformVert *dv;
1886                 for (i= 0, dv= dvert_array; i < dvert_tot; i++, dv++) {
1887                         MDeformWeight *dw;
1888
1889                         dw= defvert_find_index(dv, def_nr);
1890                         defvert_remove_group(dv, dw); /* dw can be NULL */
1891
1892                         /* inline, make into a function if anything else needs to do this */
1893                         for (j = 0; j < dv->totweight; j++) {
1894                                 if (dv->dw[j].def_nr > def_nr) {
1895                                         dv->dw[j].def_nr--;
1896                                 }
1897                         }
1898                         /* done */
1899                 }
1900         }
1901
1902         vgroup_delete_update_users(ob, def_nr + 1);
1903
1904         /* Remove the group */
1905         BLI_freelinkN(&ob->defbase, dg);
1906
1907         /* Update the active deform index if necessary */
1908         if (ob->actdef > def_nr)
1909                 ob->actdef--;
1910         if (ob->actdef < 1 && ob->defbase.first)
1911                 ob->actdef= 1;
1912
1913 }
1914
1915 /* only in editmode */
1916 /* removes from active defgroup, if allverts==0 only selected vertices */
1917 static void vgroup_active_remove_verts(Object *ob, const int allverts, bDeformGroup *dg)
1918 {
1919         MDeformVert *dv;
1920         const int def_nr= BLI_findindex(&ob->defbase, dg);
1921
1922         if (ob->type == OB_MESH) {
1923                 Mesh *me= ob->data;
1924
1925                 if (me->edit_btmesh) {
1926                         BMEditMesh *em = me->edit_btmesh;
1927                         BMVert *eve;
1928                         BMIter iter;
1929
1930                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1931                                 dv= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
1932
1933                                 if (dv && dv->dw && (allverts || BM_elem_flag_test(eve, BM_ELEM_SELECT))) {
1934                                         MDeformWeight *dw = defvert_find_index(dv, def_nr);
1935                                         defvert_remove_group(dv, dw); /* dw can be NULL */
1936                                 }
1937                         }
1938                 }
1939                 else {
1940                         MVert *mv;
1941                         MDeformVert *dv;
1942                         int i;
1943
1944                         if (!me->dvert) {
1945                                 ED_vgroup_data_create(&me->id);
1946                         }
1947
1948                         mv = me->mvert;
1949                         dv = me->dvert;
1950
1951                         for (i=0; i<me->totvert; i++, mv++, dv++) {
1952                                 if (mv->flag & SELECT) {
1953                                         if (dv->dw && (allverts || (mv->flag & SELECT))) {
1954                                                 MDeformWeight *dw = defvert_find_index(dv, def_nr);
1955                                                 defvert_remove_group(dv, dw); /* dw can be NULL */
1956                                         }
1957                                 }
1958                         }
1959                 }
1960         }
1961         else if (ob->type == OB_LATTICE) {
1962                 Lattice *lt= vgroup_edit_lattice(ob);
1963                 
1964                 if (lt->dvert) {
1965                         BPoint *bp;
1966                         int i, tot= lt->pntsu*lt->pntsv*lt->pntsw;
1967                                 
1968                         for (i=0, bp= lt->def; i<tot; i++, bp++) {
1969                                 if (allverts || (bp->f1 & SELECT)) {
1970                                         MDeformWeight *dw;
1971
1972                                         dv= &lt->dvert[i];
1973
1974                                         dw = defvert_find_index(dv, def_nr);
1975                                         defvert_remove_group(dv, dw); /* dw can be NULL */
1976                                 }
1977                         }
1978                 }
1979         }
1980 }
1981
1982 static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *dg)
1983 {
1984         int i;
1985         const int dg_index= BLI_findindex(&ob->defbase, dg);
1986
1987         assert(dg_index > -1);
1988
1989         /* Make sure that no verts are using this group */
1990         vgroup_active_remove_verts(ob, TRUE, dg);
1991
1992         /* Make sure that any verts with higher indices are adjusted accordingly */
1993         if (ob->type==OB_MESH) {
1994                 Mesh *me= ob->data;
1995                 BMEditMesh *em = me->edit_btmesh;
1996                 BMIter iter;
1997                 BMVert *eve;
1998                 MDeformVert *dvert;
1999                 
2000                 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2001                         dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
2002
2003                         if (dvert)
2004                                 for (i=0; i<dvert->totweight; i++)
2005                                         if (dvert->dw[i].def_nr > dg_index)
2006                                                 dvert->dw[i].def_nr--;
2007                 }
2008         }
2009         else if (ob->type==OB_LATTICE) {
2010                 Lattice *lt= vgroup_edit_lattice(ob);
2011                 BPoint *bp;
2012                 MDeformVert *dvert= lt->dvert;
2013                 int a, tot;
2014                 
2015                 if (dvert) {
2016                         tot= lt->pntsu*lt->pntsv*lt->pntsw;
2017                         for (a=0, bp= lt->def; a<tot; a++, bp++, dvert++) {
2018                                 for (i=0; i<dvert->totweight; i++) {
2019                                         if (dvert->dw[i].def_nr > dg_index)
2020                                                 dvert->dw[i].def_nr--;
2021                                 }
2022                         }
2023                 }
2024         }
2025
2026         vgroup_delete_update_users(ob, dg_index + 1);
2027
2028         /* Remove the group */
2029         BLI_freelinkN (&ob->defbase, dg);
2030
2031         /* Update the active deform index if necessary */
2032         if (ob->actdef > dg_index)
2033                 ob->actdef--;
2034         if (ob->actdef < 1 && ob->defbase.first)
2035                 ob->actdef= 1;
2036
2037         /* remove all dverts */
2038         if (ob->defbase.first == NULL) {
2039                 if (ob->type==OB_MESH) {
2040                         Mesh *me= ob->data;
2041                         CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
2042                         me->dvert= NULL;
2043                 }
2044                 else if (ob->type==OB_LATTICE) {
2045                         Lattice *lt= vgroup_edit_lattice(ob);
2046                         if (lt->dvert) {
2047                                 MEM_freeN(lt->dvert);
2048                                 lt->dvert= NULL;
2049                         }
2050                 }
2051         }
2052 }
2053
2054 static int vgroup_object_in_edit_mode(Object *ob)
2055 {
2056         if (ob->type == OB_MESH)
2057                 return (BMEdit_FromObject(ob) != NULL);
2058         else if (ob->type == OB_LATTICE)
2059                 return (((Lattice*)ob->data)->editlatt != NULL);
2060         
2061         return 0;
2062 }
2063
2064 static int vgroup_object_in_wpaint_vert_select(Object *ob)
2065 {
2066         if (ob->type == OB_MESH) {
2067                 Mesh *me = ob->data;
2068                 return ( (ob->mode & OB_MODE_WEIGHT_PAINT) &&
2069                          (me->edit_btmesh == NULL) &&
2070                          (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX) );
2071         }
2072
2073         return 0;
2074 }
2075
2076 static void vgroup_delete(Object *ob)
2077 {
2078         bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef-1);
2079         if (!dg)
2080                 return;
2081
2082         if (vgroup_object_in_edit_mode(ob))
2083                 vgroup_delete_edit_mode(ob, dg);
2084         else
2085                 vgroup_delete_object_mode(ob, dg);
2086 }
2087
2088 static void vgroup_delete_all(Object *ob)
2089 {
2090         /* Remove all DVerts */
2091         if (ob->type==OB_MESH) {
2092                 Mesh *me= ob->data;
2093                 CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert);
2094                 me->dvert= NULL;
2095         }
2096         else if (ob->type==OB_LATTICE) {
2097                 Lattice *lt= vgroup_edit_lattice(ob);
2098                 if (lt->dvert) {
2099                         MEM_freeN(lt->dvert);
2100                         lt->dvert= NULL;
2101                 }
2102         }
2103         
2104         /* Remove all DefGroups */
2105         BLI_freelistN(&ob->defbase);
2106         
2107         /* Fix counters/indices */
2108         ob->actdef= 0;
2109 }
2110
2111 /* only in editmode */
2112 static void vgroup_assign_verts(Object *ob, const float weight)
2113 {
2114         MDeformVert *dv;
2115         const int def_nr= ob->actdef-1;
2116
2117         if (!BLI_findlink(&ob->defbase, def_nr))
2118                 return;
2119
2120         if (ob->type == OB_MESH) {
2121                 Mesh *me= ob->data;
2122
2123                 if (me->edit_btmesh) {
2124                         BMEditMesh *em = me->edit_btmesh;
2125                         BMIter iter;
2126                         BMVert *eve;
2127
2128                         if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
2129                                 BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
2130
2131                         /* Go through the list of editverts and assign them */
2132                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2133                                 if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2134                                         MDeformWeight *dw;
2135                                         dv= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); /* can be NULL */
2136                                         dw= defvert_verify_index(dv, def_nr);
2137                                         if (dw) {
2138                                                 dw->weight= weight;
2139                                         }
2140                                 }
2141                         }
2142                 }
2143                 else {
2144                         MVert *mv;
2145                         MDeformVert *dv;
2146                         int i;
2147
2148                         if (!me->dvert) {
2149                                 ED_vgroup_data_create(&me->id);
2150                         }
2151
2152                         mv = me->mvert;
2153                         dv = me->dvert;
2154
2155                         for (i=0; i<me->totvert; i++, mv++, dv++) {
2156                                 if (mv->flag & SELECT) {
2157                                         MDeformWeight *dw;
2158                                         dw= defvert_verify_index(dv, def_nr);
2159                                         if (dw) {
2160                                                 dw->weight= weight;
2161                                         }
2162                                 }
2163                         }
2164                 }
2165         }
2166         else if (ob->type == OB_LATTICE) {
2167                 Lattice *lt= vgroup_edit_lattice(ob);
2168                 BPoint *bp;
2169                 int a, tot;
2170
2171                 if (lt->dvert==NULL)
2172                         ED_vgroup_data_create(&lt->id);
2173
2174                 dv= lt->dvert;
2175
2176                 tot= lt->pntsu*lt->pntsv*lt->pntsw;
2177                 for (a=0, bp= lt->def; a<tot; a++, bp++, dv++) {
2178                         if (bp->f1 & SELECT) {
2179                                 MDeformWeight *dw;
2180
2181                                 dw= defvert_verify_index(dv, def_nr);
2182                                 if (dw) {
2183                                         dw->weight= weight;
2184                                 }
2185                         }
2186                 }
2187         }
2188 }
2189
2190 /* only in editmode */
2191 /* removes from all defgroup, if allverts==0 only selected vertices */
2192 static void vgroup_remove_verts(Object *ob, int allverts)
2193 {
2194         /* To prevent code redundancy, we just use vgroup_active_remove_verts, but that
2195          * only operates on the active vgroup. So we iterate through all groups, by changing
2196          * active group index
2197          */
2198         bDeformGroup *dg;
2199         for (dg= ob->defbase.first; dg; dg= dg->next) {
2200                 vgroup_active_remove_verts(ob, allverts, dg);
2201         }
2202 }
2203
2204 /********************** vertex group operators *********************/
2205
2206 static int vertex_group_poll(bContext *C)
2207 {
2208         Object *ob= ED_object_context(C);
2209         ID *data= (ob)? ob->data: NULL;
2210         return (ob && !ob->id.lib && OB_TYPE_SUPPORT_VGROUP(ob->type) && data && !data->lib);
2211 }
2212
2213 static int UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C)
2214 {
2215         Object *ob= ED_object_context(C);
2216         ID *data= (ob)? ob->data: NULL;
2217
2218         if (!(ob && !ob->id.lib && data && !data->lib))
2219                 return 0;
2220
2221         return vgroup_object_in_edit_mode(ob);
2222 }
2223
2224 /* editmode _or_ weight paint vertex sel */
2225 static int vertex_group_poll_edit_or_wpaint_vert_select(bContext *C)
2226 {
2227         Object *ob= ED_object_context(C);
2228         ID *data= (ob)? ob->data: NULL;
2229
2230         if (!(ob && !ob->id.lib && data && !data->lib))
2231                 return 0;
2232
2233         return ( vgroup_object_in_edit_mode(ob) ||
2234                  vgroup_object_in_wpaint_vert_select(ob) );
2235 }
2236
2237 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
2238 {
2239         Object *ob= ED_object_context(C);
2240
2241         ED_vgroup_add(ob);
2242         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2243         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2244         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2245         
2246         return OPERATOR_FINISHED;
2247 }
2248
2249 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
2250 {
2251         /* identifiers */
2252         ot->name = "Add Vertex Group";
2253         ot->idname = "OBJECT_OT_vertex_group_add";
2254         
2255         /* api callbacks */
2256         ot->poll = vertex_group_poll;
2257         ot->exec = vertex_group_add_exec;
2258
2259         /* flags */
2260         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2261 }
2262
2263 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
2264 {
2265         Object *ob= ED_object_context(C);
2266
2267         if (RNA_boolean_get(op->ptr, "all"))
2268                 vgroup_delete_all(ob);
2269         else
2270                 vgroup_delete(ob);
2271
2272         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2273         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2274         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2275         
2276         return OPERATOR_FINISHED;
2277 }
2278
2279 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
2280 {
2281         /* identifiers */
2282         ot->name = "Remove Vertex Group";
2283         ot->idname = "OBJECT_OT_vertex_group_remove";
2284         
2285         /* api callbacks */
2286         ot->poll = vertex_group_poll;
2287         ot->exec = vertex_group_remove_exec;
2288
2289         /* flags */
2290         /* redo operator will fail in this case because vertex groups aren't stored
2291          * in local edit mode stack and toggling "all" property will lead to
2292          * all groups deleted without way to restore them (see [#29527], sergey) */
2293         ot->flag = /*OPTYPE_REGISTER|*/OPTYPE_UNDO;
2294
2295         /* properties */
2296         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups");
2297 }
2298
2299 static int vertex_group_assign_exec(bContext *C, wmOperator *op)
2300 {
2301         ToolSettings *ts= CTX_data_tool_settings(C);
2302         Object *ob= ED_object_context(C);
2303
2304         if (RNA_boolean_get(op->ptr, "new"))
2305                 ED_vgroup_add(ob);
2306
2307         vgroup_assign_verts(ob, ts->vgroup_weight);
2308         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2309         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2310         
2311         return OPERATOR_FINISHED;
2312 }
2313
2314 void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
2315 {
2316         /* identifiers */
2317         ot->name = "Assign Vertex Group";
2318         ot->idname = "OBJECT_OT_vertex_group_assign";
2319         
2320         /* api callbacks */
2321         ot->poll = vertex_group_poll_edit_or_wpaint_vert_select;
2322         ot->exec = vertex_group_assign_exec;
2323
2324         /* flags */
2325         /* redo operator will fail in this case because vertex group assignment
2326          * isn't stored in local edit mode stack and toggling "new" property will
2327          * lead to creating plenty of new vertex groups (see [#29527], sergey) */
2328         ot->flag = /*OPTYPE_REGISTER|*/OPTYPE_UNDO;
2329
2330         /* properties */
2331         RNA_def_boolean(ot->srna, "new", 0, "New", "Assign vertex to new vertex group");
2332 }
2333
2334 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
2335 {
2336         Object *ob= ED_object_context(C);
2337
2338         if (RNA_boolean_get(op->ptr, "all"))
2339                 vgroup_remove_verts(ob, 0);
2340         else {
2341                 bDeformGroup *dg= BLI_findlink(&ob->defbase, ob->actdef - 1);
2342
2343                 if (dg == NULL) {
2344                         return OPERATOR_CANCELLED;
2345                 }
2346
2347                 vgroup_active_remove_verts(ob, FALSE, dg);
2348         }
2349
2350         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2351         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2352
2353         return OPERATOR_FINISHED;
2354 }
2355
2356 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
2357 {
2358         /* identifiers */
2359         ot->name = "Remove from Vertex Group";
2360         ot->idname = "OBJECT_OT_vertex_group_remove_from";
2361
2362         /* api callbacks */
2363         ot->poll = vertex_group_poll_edit_or_wpaint_vert_select;
2364         ot->exec = vertex_group_remove_from_exec;
2365
2366         /* flags */
2367         /* redo operator will fail in this case because vertex groups assignment
2368          * isn't stored in local edit mode stack and toggling "all" property will lead to
2369          * removing vertices from all groups (see [#29527], sergey) */
2370         ot->flag = /*OPTYPE_REGISTER|*/OPTYPE_UNDO;
2371
2372         /* properties */
2373         RNA_def_boolean(ot->srna, "all", 0, "All", "Remove from all vertex groups");
2374 }
2375
2376 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
2377 {
2378         Object *ob= ED_object_context(C);
2379
2380         if (!ob || ob->id.lib)
2381                 return OPERATOR_CANCELLED;
2382
2383         vgroup_select_verts(ob, 1);
2384         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2385
2386         return OPERATOR_FINISHED;
2387 }
2388
2389 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
2390 {
2391         /* identifiers */
2392         ot->name = "Select Vertex Group";
2393         ot->idname = "OBJECT_OT_vertex_group_select";
2394
2395         /* api callbacks */
2396         ot->poll = vertex_group_poll_edit_or_wpaint_vert_select;
2397         ot->exec = vertex_group_select_exec;
2398
2399         /* flags */
2400         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2401 }
2402
2403 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
2404 {
2405         Object *ob= ED_object_context(C);
2406
2407         vgroup_select_verts(ob, 0);
2408         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
2409
2410         return OPERATOR_FINISHED;
2411 }
2412
2413 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
2414 {
2415         /* identifiers */
2416         ot->name = "Deselect Vertex Group";
2417         ot->idname = "OBJECT_OT_vertex_group_deselect";
2418
2419         /* api callbacks */
2420         ot->poll = vertex_group_poll_edit_or_wpaint_vert_select;
2421         ot->exec = vertex_group_deselect_exec;
2422
2423         /* flags */
2424         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2425 }
2426
2427 /*Adds a copy of selected vertex group from source object to source object*/
2428 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
2429 {
2430         Object *ob= ED_object_context(C);
2431
2432         vgroup_duplicate(ob);
2433         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2434         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2435         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2436
2437         return OPERATOR_FINISHED;
2438 }
2439
2440 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
2441 {
2442         /* identifiers */
2443         ot->name = "Copy Vertex Group";
2444         ot->idname = "OBJECT_OT_vertex_group_copy";
2445
2446         /* api callbacks */
2447         ot->poll = vertex_group_poll;
2448         ot->exec = vertex_group_copy_exec;
2449
2450         /* flags */
2451         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2452 }
2453
2454 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
2455 {
2456         Object *ob= ED_object_context(C);
2457         
2458         float offset= RNA_float_get(op->ptr,"offset");
2459         float gain= RNA_float_get(op->ptr,"gain");
2460         
2461         vgroup_levels(ob, offset, gain);
2462         
2463         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2464         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2465         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2466         
2467         return OPERATOR_FINISHED;
2468 }
2469
2470 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
2471 {
2472         /* identifiers */
2473         ot->name = "Vertex Group Levels";
2474         ot->idname = "OBJECT_OT_vertex_group_levels";
2475         
2476         /* api callbacks */
2477         ot->poll = vertex_group_poll;
2478         ot->exec = vertex_group_levels_exec;
2479         
2480         /* flags */
2481         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2482         
2483         RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
2484         RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
2485 }
2486
2487 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
2488 {
2489         Object *ob= ED_object_context(C);
2490
2491         vgroup_normalize(ob);
2492
2493         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2494         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2495         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2496
2497         return OPERATOR_FINISHED;
2498 }
2499
2500 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
2501 {
2502         /* identifiers */
2503         ot->name = "Normalize Vertex Group";
2504         ot->idname = "OBJECT_OT_vertex_group_normalize";
2505
2506         /* api callbacks */
2507         ot->poll = vertex_group_poll;
2508         ot->exec = vertex_group_normalize_exec;
2509
2510         /* flags */
2511         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2512 }
2513
2514 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
2515 {
2516         Object *ob= ED_object_context(C);
2517         int lock_active= RNA_boolean_get(op->ptr,"lock_active");
2518
2519         vgroup_normalize_all(ob, lock_active);
2520
2521         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2522         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2523         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2524
2525         return OPERATOR_FINISHED;
2526 }
2527
2528 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
2529 {
2530         /* identifiers */
2531         ot->name = "Normalize All Vertex Groups";
2532         ot->idname = "OBJECT_OT_vertex_group_normalize_all";
2533
2534         /* api callbacks */
2535         ot->poll = vertex_group_poll;
2536         ot->exec = vertex_group_normalize_all_exec;
2537
2538         /* flags */
2539         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2540
2541         RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active",
2542                         "Keep the values of the active group while normalizing others");
2543 }
2544
2545 static int vertex_group_fix_exec(bContext *C, wmOperator *op)
2546 {
2547         Object *ob= CTX_data_active_object(C);
2548         Scene *scene= CTX_data_scene(C);
2549         
2550         float distToBe= RNA_float_get(op->ptr, "dist");
2551         float strength= RNA_float_get(op->ptr, "strength");
2552         float cp= RNA_float_get(op->ptr, "accuracy");
2553         ModifierData *md= ob->modifiers.first;
2554
2555         while (md) {
2556                 if (md->type == eModifierType_Mirror && (md->mode&eModifierMode_Realtime)) {
2557                         break;
2558                 }
2559                 md = md->next;
2560         }
2561         
2562         if (md && md->type == eModifierType_Mirror) {
2563                 BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
2564                 return OPERATOR_CANCELLED;
2565         }
2566         vgroup_fix(scene, ob, distToBe, strength, cp);
2567         
2568         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2569         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2570         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2571         
2572         return OPERATOR_FINISHED;
2573 }
2574
2575 void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
2576 {
2577         /* identifiers */
2578         ot->name = "Fix Vertex Group Deform";
2579         ot->idname = "OBJECT_OT_vertex_group_fix";
2580         ot->description = "Modify the position of selected vertices by changing only their respective "
2581                          "groups' weights (this tool may be slow for many vertices)";
2582         
2583         /* api callbacks */
2584         ot->poll = vertex_group_poll;
2585         ot->exec = vertex_group_fix_exec;
2586         
2587         /* flags */
2588         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2589         RNA_def_float(ot->srna, "dist", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "The distance to move to", -10.0f, 10.0f);
2590         RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength",
2591                       "The distance moved can be changed by this multiplier", -2.0f, 2.0f);
2592         RNA_def_float(ot->srna, "accuracy", 1.0f, 0.05f, FLT_MAX, "Change Sensitivity",
2593                       "Change the amount weights are altered with each iteration: lower values are slower", 0.05f, 1.f);
2594 }
2595
2596
2597 static int vertex_group_lock_exec(bContext *C, wmOperator *op)
2598 {
2599         Object *ob= CTX_data_active_object(C);
2600
2601         int action = RNA_enum_get(op->ptr, "action");
2602
2603         vgroup_lock_all(ob, action);
2604
2605         return OPERATOR_FINISHED;
2606 }
2607
2608 void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
2609 {
2610         /* identifiers */
2611         ot->name = "Change the Lock On Vertex Groups";
2612         ot->idname = "OBJECT_OT_vertex_group_lock";
2613
2614         /* api callbacks */
2615         ot->poll = vertex_group_poll;
2616         ot->exec = vertex_group_lock_exec;
2617
2618         /* flags */
2619         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2620
2621         WM_operator_properties_select_all(ot);
2622 }
2623
2624 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
2625 {
2626         Object *ob= ED_object_context(C);
2627         int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
2628         int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
2629
2630         vgroup_invert(ob, auto_assign, auto_remove);
2631         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2632         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2633         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2634
2635         return OPERATOR_FINISHED;
2636 }
2637
2638 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
2639 {
2640         /* identifiers */
2641         ot->name = "Invert Vertex Group";
2642         ot->idname = "OBJECT_OT_vertex_group_invert";
2643
2644         /* api callbacks */
2645         ot->poll = vertex_group_poll;
2646         ot->exec = vertex_group_invert_exec;
2647
2648         /* flags */
2649         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2650
2651         RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights",
2652                         "Add verts from groups that have zero weight before inverting");
2653         RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights",
2654                         "Remove verts from groups that have zero weight after inverting");
2655 }
2656
2657
2658 static int vertex_group_blend_exec(bContext *C, wmOperator *op)
2659 {
2660         Object *ob = ED_object_context(C);
2661         float fac = RNA_float_get(op->ptr, "factor");
2662
2663         vgroup_blend(ob, fac);
2664
2665         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2666         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2667         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2668
2669         return OPERATOR_FINISHED;
2670 }
2671
2672 /* check we have a vertex selection, either in weight paint or editmode */
2673 static int vertex_group_blend_poll(bContext *C)
2674 {
2675         Object *ob = ED_object_context(C);
2676         ID *data = (ob) ? ob->data: NULL;
2677
2678         if (!(ob && !ob->id.lib && data && !data->lib))
2679                 return FALSE;
2680
2681         if (vgroup_object_in_edit_mode(ob)) {
2682                 return TRUE;
2683         }
2684         else if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
2685                 if (ME_EDIT_PAINT_SEL_MODE(((Mesh *)data)) == SCE_SELECT_VERTEX) {
2686                         return TRUE;
2687                 }
2688                 else {
2689                         CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
2690                         return FALSE;
2691                 }
2692
2693         }
2694         else {
2695                 return FALSE;
2696         }
2697 }
2698
2699 void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
2700 {
2701         PropertyRNA *prop;
2702
2703         /* identifiers */
2704         ot->name = "Blend Vertex Group";
2705         ot->idname = "OBJECT_OT_vertex_group_blend";
2706         ot->description = "Blend selected vertex weights with unselected for the active group";
2707
2708         /* api callbacks */
2709         ot->poll = vertex_group_blend_poll;
2710         ot->exec = vertex_group_blend_exec;
2711
2712         /* flags */
2713         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2714
2715         prop = RNA_def_property(ot->srna, "factor", PROP_FLOAT, PROP_FACTOR);
2716         RNA_def_property_ui_text(prop, "Factor", "");
2717         RNA_def_property_range(prop, 0.0f, 1.0f);
2718         RNA_def_property_float_default(prop, 1.0f);
2719 }
2720
2721
2722 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
2723 {
2724         Object *ob= ED_object_context(C);
2725
2726         float limit= RNA_float_get(op->ptr,"limit");
2727         int all_groups= RNA_boolean_get(op->ptr,"all_groups");
2728         int keep_single= RNA_boolean_get(op->ptr,"keep_single");
2729
2730         if (all_groups) vgroup_clean_all(ob, limit, keep_single);
2731         else                    vgroup_clean(ob, limit, keep_single);
2732
2733         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2734         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2735         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2736
2737         return OPERATOR_FINISHED;
2738 }
2739
2740 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
2741 {
2742         /* identifiers */
2743         ot->name = "Clean Vertex Group";
2744         ot->idname = "OBJECT_OT_vertex_group_clean";
2745         ot->description = "Remove Vertex Group assignments which aren't required";
2746
2747         /* api callbacks */
2748         ot->poll = vertex_group_poll;
2749         ot->exec = vertex_group_clean_exec;
2750
2751         /* flags */
2752         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2753
2754         RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit", 0.001f, 0.99f);
2755         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups");
2756         RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single",
2757                         "Keep verts assigned to at least one group when cleaning");
2758 }
2759
2760
2761 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
2762 {
2763         Object *ob= ED_object_context(C);
2764
2765         ED_vgroup_mirror(ob,
2766                          RNA_boolean_get(op->ptr,"mirror_weights"),
2767                          RNA_boolean_get(op->ptr,"flip_group_names"),
2768                          RNA_boolean_get(op->ptr,"all_groups"));
2769
2770         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2771         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
2772         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
2773
2774         return OPERATOR_FINISHED;
2775 }
2776
2777 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
2778 {
2779         /* identifiers */
2780         ot->name = "Mirror Vertex Group";
2781         ot->idname = "OBJECT_OT_vertex_group_mirror";
2782         ot->description = "Mirror all vertex groups, flip weights and/or names, editing only selected vertices, "
2783                          "flipping when both sides are selected otherwise copy from unselected";
2784
2785         /* api callbacks */
2786         ot->poll = vertex_group_poll;
2787         ot->exec = vertex_group_mirror_exec;
2788
2789         /* flags */
2790         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2791
2792         /* properties */
2793         RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights");
2794         RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names");
2795         RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Mirror all vertex groups weights");
2796
2797 }
2798
2799 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
2800 {
2801         Scene *scene= CTX_data_scene(C);
2802         Object *ob= ED_object_context(C);
2803         Base *base;
2804         int retval= OPERATOR_CANCELLED;
2805
2806         for (base=scene->base.first; base; base= base->next) {
2807                 if (base->object->type==ob->type) {
2808                         if (base->object!=ob && base->object->data==ob->data) {
2809                                 BLI_freelistN(&base->object->defbase);
2810                                 BLI_duplicatelist(&base->object->defbase, &ob->defbase);
2811                                 base->object->actdef= ob->actdef;
2812
2813                                 DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
2814                                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, base->object);
2815                                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
2816
2817                                 retval = OPERATOR_FINISHED;
2818                         }
2819                 }
2820         }
2821
2822         return retval;
2823 }
2824
2825 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
2826 {
2827         /* identifiers */
2828         ot->name = "Copy Vertex Groups to Linked";
2829         ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
2830         ot->description = "Copy Vertex Groups to all users of the same Geometry data";
2831
2832         /* api callbacks */
2833         ot->poll = vertex_group_poll;
2834         ot->exec = vertex_group_copy_to_linked_exec;
2835
2836         /* flags */
2837         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2838 }
2839
2840 /*Copy vertex groups from source to target*/ /*warning! overwrites list*/
2841 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
2842 {
2843         Object *obact= ED_object_context(C);
2844         int change= 0;
2845         int fail= 0;
2846
2847         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
2848         {
2849                 if (obact != ob) {
2850                         if (ED_vgroup_copy_array(ob, obact)) change++;
2851                         else                                fail++;
2852                 }
2853         }
2854         CTX_DATA_END;
2855
2856         if ((change == 0 && fail == 0) || fail) {
2857                 BKE_reportf(op->reports, RPT_ERROR,
2858                             "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indices",
2859                             change, fail);
2860         }
2861
2862         return OPERATOR_FINISHED;
2863 }
2864
2865 /* Transfer all vertex groups with weight to selected*/
2866 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
2867 {
2868         /* identifiers */
2869         ot->name = "Copy Vertex Group to Selected";
2870         ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
2871         ot->description = "Copy Vertex Groups to other selected objects with matching indices";
2872
2873         /* api callbacks */
2874         ot->poll = vertex_group_poll;
2875         ot->exec = vertex_group_copy_to_selected_exec;
2876
2877         /* flags */
2878         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2879 }
2880
2881 static int vertex_group_copy_to_selected_single_exec(bContext *C, wmOperator *op)
2882 {
2883         Object *obact= CTX_data_active_object(C);
2884         int change= 0;
2885         int fail= 0;
2886
2887         /*Macro to loop through selected objects and perform operation*/
2888         CTX_DATA_BEGIN(C, Object*, obslc, selected_editable_objects)
2889         {
2890                 if(obact != obslc) {
2891                         /*Try function for matching number of vertices*/
2892                         if(ED_vgroup_copy_single(obslc, obact)) change++;
2893                         /*Try function for get weight from closest vertex*/
2894                         else if(ED_vgroup_copy_by_closest_single(obslc, obact)) change++;
2895                         /*Trigger error message*/
2896                         else fail++;
2897                         /*Event notifiers for correct display of data*/
2898                         DAG_id_tag_update(&obslc->id, OB_RECALC_DATA);
2899                         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obslc);
2900                         WM_event_add_notifier(C, NC_GEOM|ND_DATA, obslc->data);
2901                 }
2902         }
2903         CTX_DATA_END;
2904
2905         /*Report error when task could not be completed.*/
2906         if((change == 0 && fail == 0) || fail) {
2907                 BKE_reportf(op->reports, RPT_ERROR,
2908                             "Copy to VGroups to Selected warning done %d, failed %d, All functions failed!",
2909                             change, fail);
2910         }
2911
2912         return OPERATOR_FINISHED;
2913 }
2914
2915 /*Transfer vertex group with weight to selected*/
2916 void OBJECT_OT_vertex_group_copy_to_selected_single(wmOperatorType *ot)
2917 {
2918         /* identifiers */
2919         ot->name= "Copy a Vertex Group to Selected";
2920         ot->idname= "OBJECT_OT_vertex_group_copy_to_selected_single";
2921         ot->description= "Copy a vertex group to other selected objects with matching indices";
2922
2923         /* api callbacks */
2924         ot->poll= vertex_group_poll;
2925         ot->exec= vertex_group_copy_to_selected_single_exec;
2926
2927         /* flags */
2928         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2929 }
2930
2931 static EnumPropertyItem vgroup_items[]= {
2932         {0, NULL, 0, NULL, NULL}};
2933
2934 static int set_active_group_exec(bContext *C, wmOperator *op)
2935 {
2936         Object *ob= ED_object_context(C);
2937         int nr= RNA_enum_get(op->ptr, "group");
2938
2939         BLI_assert(nr+1 >= 0);
2940         ob->actdef= nr+1;
2941
2942         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2943         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob);
2944
2945         return OPERATOR_FINISHED;
2946 }
2947
2948 static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
2949 {       
2950         Object *ob= ED_object_context(C);
2951         EnumPropertyItem tmp = {0, "", 0, "", ""};
2952         EnumPropertyItem *item= NULL;
2953         bDeformGroup *def;
2954         int a, totitem= 0;
2955         
2956         if (!ob)
2957                 return vgroup_items;
2958         
2959         for (a=0, def=ob->defbase.first; def; def=def->next, a++) {
2960                 tmp.value= a;
2961                 tmp.icon= ICON_GROUP_VERTEX;
2962                 tmp.identifier= def->name;
2963                 tmp.name= def->name;
2964                 RNA_enum_item_add(&item, &totitem, &tmp);
2965         }
2966
2967         RNA_enum_item_end(&item, &totitem);
2968         *free= 1;
2969
2970         return item;
2971 }
2972
2973 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
2974 {
2975         PropertyRNA *prop;
2976
2977         /* identifiers */
2978         ot->name = "Set Active Vertex Group";
2979         ot->idname = "OBJECT_OT_vertex_group_set_active";
2980         ot->description = "Set the active vertex group";
2981
2982         /* api callbacks */
2983         ot->poll = vertex_group_poll;
2984         ot->exec = set_active_group_exec;
2985         ot->invoke = WM_menu_invoke;
2986
2987         /* flags */
2988         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
2989
2990         /* properties */
2991         prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active");
2992         RNA_def_enum_funcs(prop, vgroup_itemf);
2993         ot->prop = prop;
2994 }
2995
2996 /* creates the name_array parameter for vgroup_do_remap, call this before fiddling
2997  * with the order of vgroups then call vgroup_do_remap after*/
2998 static char *vgroup_init_remap(Object *ob)
2999 {
3000         bDeformGroup *def;
3001         int defbase_tot = BLI_countlist(&ob->defbase);
3002         char *name_array= MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
3003         char *name;
3004
3005         name= name_array;
3006         for (def = ob->defbase.first; def; def=def->next) {
3007                 BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
3008                 name += MAX_VGROUP_NAME;
3009         }
3010
3011         return name_array;
3012 }
3013
3014 static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op)
3015 {
3016         MDeformVert *dvert= NULL;
3017         bDeformGroup *def;
3018         int defbase_tot = BLI_countlist(&ob->defbase);
3019
3020         /* needs a dummy index at the start*/
3021         int *sort_map_update= MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
3022         int *sort_map= sort_map_update + 1;
3023
3024         char *name;
3025         int i;
3026
3027         name= name_array;
3028         for (def= ob->defbase.first, i=0; def; def=def->next, i++) {
3029                 sort_map[i]= BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
3030                 name += MAX_VGROUP_NAME;
3031
3032                 BLI_assert(sort_map[i] != -1);
3033         }
3034
3035         if (ob->mode == OB_MODE_EDIT) {
3036                 if (ob->type==OB_MESH) {
3037                         BMEditMesh *em = BMEdit_FromObject(ob);
3038                         BMIter iter;
3039                         BMVert *eve;
3040
3041                         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
3042                                 dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
3043                                 if (dvert && dvert->totweight) {
3044                                         defvert_remap(dvert, sort_map, defbase_tot);
3045                                 }
3046                         }
3047                 }
3048                 else {
3049                         BKE_report(op->reports, RPT_ERROR, "Editmode lattice isn't supported yet");
3050                         MEM_freeN(sort_map_update);
3051                         return OPERATOR_CANCELLED;
3052                 }
3053         }
3054         else {
3055                 int dvert_tot=0;
3056
3057                 ED_vgroup_give_array(ob->data, &dvert, &dvert_tot);
3058
3059                 /*create as necessary*/
3060                 while (dvert && dvert_tot--) {
3061                         if (dvert->totweight)
3062                                 defvert_remap(dvert, sort_map, defbase_tot);
3063                         dvert++;
3064                 }
3065         }
3066
3067         /* update users */
3068         for (i=0; i<defbase_tot; i++)
3069                 sort_map[i]++;
3070
3071         sort_map_update[0]= 0;
3072         vgroup_remap_update_users(ob, sort_map_update);
3073
3074         BLI_assert(sort_map_update[ob->actdef] >= 0);
3075         ob->actdef= sort_map_update[ob->actdef];
3076         
3077         MEM_freeN(sort_map_update);
3078
3079         return OPERATOR_FINISHED;
3080 }
3081
3082 static int vgroup_sort(void *def_a_ptr, void *def_b_ptr)
3083 {
3084         bDeformGroup *def_a= (bDeformGroup *)def_a_ptr;
3085         bDeformGroup *def_b= (bDeformGroup *)def_b_ptr;
3086
3087         return BLI_natstrcmp(def_a->name, def_b->name);
3088 }
3089
3090 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
3091 {
3092         Object *ob= ED_object_context(C);
3093         char *name_array;
3094         int ret;
3095
3096         /*init remapping*/
3097         name_array = vgroup_init_remap(ob);
3098
3099         /*sort vgroup names*/
3100         BLI_sortlist(&ob->defbase, vgroup_sort);
3101
3102         /*remap vgroup data to map to correct names*/
3103         ret = vgroup_do_remap(ob, name_array, op);
3104
3105         if (ret != OPERATOR_CANCELLED) {
3106                 DAG_id_tag