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