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