GPencil: Change trace tooltip for Threshold
[blender.git] / source / blender / editors / object / object_vgroup.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edobj
22  */
23
24 #include <math.h>
25 #include <stddef.h>
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_curve_types.h"
31 #include "DNA_lattice_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_modifier_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_workspace_types.h"
38
39 #include "BLI_alloca.h"
40 #include "BLI_array.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_math.h"
43 #include "BLI_utildefines.h"
44 #include "BLI_utildefines_stack.h"
45
46 #include "BKE_context.h"
47 #include "BKE_customdata.h"
48 #include "BKE_deform.h"
49 #include "BKE_editmesh.h"
50 #include "BKE_lattice.h"
51 #include "BKE_layer.h"
52 #include "BKE_mesh.h"
53 #include "BKE_mesh_mapping.h"
54 #include "BKE_mesh_runtime.h"
55 #include "BKE_modifier.h"
56 #include "BKE_object.h"
57 #include "BKE_object_deform.h"
58 #include "BKE_report.h"
59
60 #include "DEG_depsgraph.h"
61 #include "DEG_depsgraph_build.h"
62 #include "DEG_depsgraph_query.h"
63
64 #include "DNA_armature_types.h"
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67 #include "RNA_enum_types.h"
68
69 #include "WM_api.h"
70 #include "WM_types.h"
71
72 #include "ED_mesh.h"
73 #include "ED_object.h"
74 #include "ED_screen.h"
75
76 #include "UI_resources.h"
77
78 #include "object_intern.h"
79
80 static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob);
81
82 /* -------------------------------------------------------------------- */
83 /** \name Local Utility Functions
84  * \{ */
85
86 static bool object_array_for_wpaint_filter(Object *ob, void *user_data)
87 {
88   bContext *C = user_data;
89   if (vertex_group_supported_poll_ex(C, ob)) {
90     return true;
91   }
92   return false;
93 }
94
95 static Object **object_array_for_wpaint(bContext *C, uint *r_objects_len)
96 {
97   return ED_object_array_in_mode_or_selected(C, object_array_for_wpaint_filter, C, r_objects_len);
98 }
99
100 static bool vertex_group_use_vert_sel(Object *ob)
101 {
102   if (ob->mode == OB_MODE_EDIT) {
103     return true;
104   }
105   if ((ob->type == OB_MESH) &&
106       ((Mesh *)ob->data)->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) {
107     return true;
108   }
109   return false;
110 }
111
112 static Lattice *vgroup_edit_lattice(Object *ob)
113 {
114   Lattice *lt = ob->data;
115   BLI_assert(ob->type == OB_LATTICE);
116   return (lt->editlatt) ? lt->editlatt->latt : lt;
117 }
118
119 /** \} */
120
121 /* -------------------------------------------------------------------- */
122 /** \name Public Utility Functions
123  * \{ */
124
125 bool ED_vgroup_sync_from_pose(Object *ob)
126 {
127   Object *armobj = BKE_object_pose_armature_get(ob);
128   if (armobj && (armobj->mode & OB_MODE_POSE)) {
129     struct bArmature *arm = armobj->data;
130     if (arm->act_bone) {
131       int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name);
132       if (def_num != -1) {
133         ob->actdef = def_num + 1;
134         return true;
135       }
136     }
137   }
138   return false;
139 }
140
141 /**
142  * Removes out of range MDeformWeights
143  */
144 void ED_vgroup_data_clamp_range(ID *id, const int total)
145 {
146   MDeformVert **dvert_arr;
147   int dvert_tot;
148
149   if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
150     for (int i = 0; i < dvert_tot; i++) {
151       MDeformVert *dv = dvert_arr[i];
152       for (int j = 0; j < dv->totweight; j++) {
153         if (dv->dw[j].def_nr >= total) {
154           BKE_defvert_remove_group(dv, &dv->dw[j]);
155           j--;
156         }
157       }
158     }
159   }
160 }
161
162 bool ED_vgroup_parray_alloc(ID *id,
163                             MDeformVert ***dvert_arr,
164                             int *dvert_tot,
165                             const bool use_vert_sel)
166 {
167   *dvert_tot = 0;
168   *dvert_arr = NULL;
169
170   if (id) {
171     switch (GS(id->name)) {
172       case ID_ME: {
173         Mesh *me = (Mesh *)id;
174
175         if (me->edit_mesh) {
176           BMEditMesh *em = me->edit_mesh;
177           BMesh *bm = em->bm;
178           const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
179           BMIter iter;
180           BMVert *eve;
181           int i;
182
183           if (cd_dvert_offset == -1) {
184             return false;
185           }
186
187           i = em->bm->totvert;
188
189           *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me");
190           *dvert_tot = i;
191
192           i = 0;
193           if (use_vert_sel) {
194             BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
195               (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
196                                     BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) :
197                                     NULL;
198               i++;
199             }
200           }
201           else {
202             BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
203               (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
204               i++;
205             }
206           }
207
208           return true;
209         }
210         if (me->dvert) {
211           MVert *mvert = me->mvert;
212           MDeformVert *dvert = me->dvert;
213
214           *dvert_tot = me->totvert;
215           *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me");
216
217           if (use_vert_sel) {
218             for (int i = 0; i < me->totvert; i++) {
219               (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : NULL;
220             }
221           }
222           else {
223             for (int i = 0; i < me->totvert; i++) {
224               (*dvert_arr)[i] = me->dvert + i;
225             }
226           }
227
228           return true;
229         }
230         return false;
231       }
232       case ID_LT: {
233         Lattice *lt = (Lattice *)id;
234         lt = (lt->editlatt) ? lt->editlatt->latt : lt;
235
236         if (lt->dvert) {
237           BPoint *def = lt->def;
238           *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
239           *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me");
240
241           if (use_vert_sel) {
242             for (int i = 0; i < *dvert_tot; i++) {
243               (*dvert_arr)[i] = (def->f1 & SELECT) ? &lt->dvert[i] : NULL;
244             }
245           }
246           else {
247             for (int i = 0; i < *dvert_tot; i++) {
248               (*dvert_arr)[i] = lt->dvert + i;
249             }
250           }
251
252           return true;
253         }
254         return false;
255       }
256
257       default:
258         break;
259     }
260   }
261
262   return false;
263 }
264
265 /**
266  * For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
267  * This finds the unselected mirror deform verts and copies the weights to them from the selected.
268  *
269  * \note \a dvert_array has mirrored weights filled in,
270  * in case cleanup operations are needed on both.
271  */
272 void ED_vgroup_parray_mirror_sync(Object *ob,
273                                   MDeformVert **dvert_array,
274                                   const int dvert_tot,
275                                   const bool *vgroup_validmap,
276                                   const int vgroup_tot)
277 {
278   BMEditMesh *em = BKE_editmesh_from_object(ob);
279   MDeformVert **dvert_array_all = NULL;
280   int dvert_tot_all;
281
282   /* get an array of all verts, not only selected */
283   if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
284     BLI_assert(0);
285     return;
286   }
287   if (em) {
288     BM_mesh_elem_table_ensure(em->bm, BM_VERT);
289   }
290
291   int flip_map_len;
292   const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true);
293
294   for (int i_src = 0; i_src < dvert_tot; i_src++) {
295     if (dvert_array[i_src] != NULL) {
296       /* its selected, check if its mirror exists */
297       int i_dst = ED_mesh_mirror_get_vert(ob, i_src);
298       if (i_dst != -1 && dvert_array_all[i_dst] != NULL) {
299         /* we found a match! */
300         const MDeformVert *dv_src = dvert_array[i_src];
301         MDeformVert *dv_dst = dvert_array_all[i_dst];
302
303         BKE_defvert_mirror_subset(
304             dv_dst, dv_src, vgroup_validmap, vgroup_tot, flip_map, flip_map_len);
305
306         dvert_array[i_dst] = dvert_array_all[i_dst];
307       }
308     }
309   }
310
311   MEM_freeN((void *)flip_map);
312   MEM_freeN(dvert_array_all);
313 }
314
315 /**
316  * Fill in the pointers for mirror verts (as if all mirror verts were selected too).
317  *
318  * similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
319  */
320 void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot)
321 {
322   BMEditMesh *em = BKE_editmesh_from_object(ob);
323   MDeformVert **dvert_array_all = NULL;
324   int dvert_tot_all;
325
326   /* get an array of all verts, not only selected */
327   if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
328     BLI_assert(0);
329     return;
330   }
331   BLI_assert(dvert_tot == dvert_tot_all);
332   if (em) {
333     BM_mesh_elem_table_ensure(em->bm, BM_VERT);
334   }
335
336   for (int i = 0; i < dvert_tot; i++) {
337     if (dvert_array[i] == NULL) {
338       /* its unselected, check if its mirror is */
339       int i_sel = ED_mesh_mirror_get_vert(ob, i);
340       if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
341         /* we found a match! */
342         dvert_array[i] = dvert_array_all[i];
343       }
344     }
345   }
346
347   MEM_freeN(dvert_array_all);
348 }
349
350 void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array,
351                                   const int dvert_tot,
352                                   const bool *vgroup_validmap,
353                                   const int vgroup_tot,
354                                   const float epsilon,
355                                   const bool keep_single)
356 {
357   MDeformVert *dv;
358
359   for (int i = 0; i < dvert_tot; i++) {
360     /* in case its not selected */
361     if (!(dv = dvert_array[i])) {
362       continue;
363     }
364
365     int j = dv->totweight;
366
367     while (j--) {
368       MDeformWeight *dw;
369
370       if (keep_single && dv->totweight == 1) {
371         break;
372       }
373
374       dw = dv->dw + j;
375       if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
376         if (dw->weight <= epsilon) {
377           BKE_defvert_remove_group(dv, dw);
378         }
379       }
380     }
381   }
382 }
383
384 /* matching index only */
385 bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
386 {
387   MDeformVert **dvert_array_from = NULL, **dvf;
388   MDeformVert **dvert_array = NULL, **dv;
389   int dvert_tot_from;
390   int dvert_tot;
391   int i;
392   int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
393   int defbase_tot = BLI_listbase_count(&ob->defbase);
394   bool new_vgroup = false;
395
396   if (ob == ob_from) {
397     return true;
398   }
399
400   /* In case we copy vgroup between two objects using same data,
401    * we only have to care about object side of things. */
402   if (ob->data != ob_from->data) {
403     ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
404     ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
405
406     if ((dvert_array == NULL) && (dvert_array_from != NULL) &&
407         BKE_object_defgroup_data_create(ob->data)) {
408       ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
409       new_vgroup = true;
410     }
411
412     if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL ||
413         dvert_array == NULL) {
414       if (dvert_array) {
415         MEM_freeN(dvert_array);
416       }
417       if (dvert_array_from) {
418         MEM_freeN(dvert_array_from);
419       }
420
421       if (new_vgroup == true) {
422         /* free the newly added vgroup since it wasn't compatible */
423         BKE_object_defgroup_remove_all(ob);
424       }
425
426       /* if true: both are 0 and nothing needs changing, consider this a success */
427       return (dvert_tot == dvert_tot_from);
428     }
429   }
430
431   /* do the copy */
432   BLI_freelistN(&ob->defbase);
433   BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
434   ob->actdef = ob_from->actdef;
435
436   if (defbase_tot_from < defbase_tot) {
437     /* correct vgroup indices because the number of vgroups is being reduced. */
438     int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
439     for (i = 0; i <= defbase_tot_from; i++) {
440       remap[i] = i;
441     }
442     for (; i <= defbase_tot; i++) {
443       remap[i] = 0; /* can't use these, so disable */
444     }
445
446     BKE_object_defgroup_remap_update_users(ob, remap);
447     MEM_freeN(remap);
448   }
449
450   if (dvert_array_from != NULL && dvert_array != NULL) {
451     dvf = dvert_array_from;
452     dv = dvert_array;
453
454     for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
455       MEM_SAFE_FREE((*dv)->dw);
456       *(*dv) = *(*dvf);
457
458       if ((*dv)->dw) {
459         (*dv)->dw = MEM_dupallocN((*dv)->dw);
460       }
461     }
462
463     MEM_freeN(dvert_array);
464     MEM_freeN(dvert_array_from);
465   }
466
467   return true;
468 }
469
470 void ED_vgroup_parray_to_weight_array(const MDeformVert **dvert_array,
471                                       const int dvert_tot,
472                                       float *dvert_weights,
473                                       const int def_nr)
474 {
475   for (int i = 0; i < dvert_tot; i++) {
476     const MDeformVert *dv = dvert_array[i];
477     dvert_weights[i] = dv ? BKE_defvert_find_weight(dv, def_nr) : 0.0f;
478   }
479 }
480
481 void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array,
482                                         const int dvert_tot,
483                                         const float *dvert_weights,
484                                         const int def_nr,
485                                         const bool remove_zero)
486 {
487   int i;
488
489   for (i = 0; i < dvert_tot; i++) {
490     MDeformVert *dv = dvert_array[i];
491     if (dv) {
492       if (dvert_weights[i] > 0.0f) {
493         MDeformWeight *dw = BKE_defvert_ensure_index(dv, def_nr);
494         BLI_assert(IN_RANGE_INCL(dvert_weights[i], 0.0f, 1.0f));
495         dw->weight = dvert_weights[i];
496       }
497       else {
498         MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
499         if (dw) {
500           if (remove_zero) {
501             BKE_defvert_remove_group(dv, dw);
502           }
503           else {
504             dw->weight = 0.0f;
505           }
506         }
507       }
508     }
509   }
510 }
511
512 /* TODO, cache flip data to speedup calls within a loop. */
513 static void mesh_defvert_mirror_update_internal(Object *ob,
514                                                 MDeformVert *dvert_dst,
515                                                 MDeformVert *dvert_src,
516                                                 const int def_nr)
517 {
518   if (def_nr == -1) {
519     /* all vgroups, add groups where needed  */
520     int flip_map_len;
521     int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true);
522     BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
523     MEM_freeN(flip_map);
524   }
525   else {
526     /* single vgroup */
527     MDeformWeight *dw = BKE_defvert_ensure_index(dvert_dst,
528                                                  BKE_object_defgroup_flip_index(ob, def_nr, 1));
529     if (dw) {
530       dw->weight = BKE_defvert_find_weight(dvert_src, def_nr);
531     }
532   }
533 }
534
535 static void ED_mesh_defvert_mirror_update_em(
536     Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset)
537 {
538   Mesh *me = ob->data;
539   BMEditMesh *em = me->edit_mesh;
540   BMVert *eve_mirr;
541   bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
542
543   eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
544
545   if (eve_mirr && eve_mirr != eve) {
546     MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
547     MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
548     mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
549   }
550 }
551
552 static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
553 {
554   int vidx_mirr;
555   Mesh *me = ob->data;
556   bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
557
558   if (vidx == -1) {
559     return;
560   }
561
562   vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
563
564   if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
565     MDeformVert *dvert_src = &me->dvert[vidx];
566     MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
567     mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
568   }
569 }
570
571 /**
572  * Use when adjusting the active vertex weight and apply to mirror vertices.
573  */
574 void ED_vgroup_vert_active_mirror(Object *ob, int def_nr)
575 {
576   Mesh *me = ob->data;
577   BMEditMesh *em = me->edit_mesh;
578   MDeformVert *dvert_act;
579
580   if (me->symmetry & ME_SYMMETRY_X) {
581     if (em) {
582       BMVert *eve_act;
583       dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
584       if (dvert_act) {
585         const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
586         ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
587       }
588     }
589     else {
590       int v_act;
591       dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
592       if (dvert_act) {
593         ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
594       }
595     }
596   }
597 }
598
599 static void vgroup_remove_weight(Object *ob, const int def_nr)
600 {
601   MDeformVert *dvert_act;
602   MDeformWeight *dw;
603
604   dvert_act = ED_mesh_active_dvert_get_only(ob);
605
606   dw = BKE_defvert_find_index(dvert_act, def_nr);
607   BKE_defvert_remove_group(dvert_act, dw);
608 }
609
610 static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
611 {
612   Mesh *me = ob->data;
613   BMEditMesh *em = me->edit_mesh;
614   BMVert *eve_act;
615   int v_act;
616   MDeformVert *dvert_act;
617   int subset_count, vgroup_tot;
618   const bool *vgroup_validmap;
619
620   if (em) {
621     dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
622   }
623   else {
624     dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
625   }
626
627   if (dvert_act == NULL) {
628     return false;
629   }
630
631   vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
632       ob, subset_type, &vgroup_tot, &subset_count);
633   BKE_defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
634   MEM_freeN((void *)vgroup_validmap);
635
636   if (me->symmetry & ME_SYMMETRY_X) {
637     if (em) {
638       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
639       ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
640     }
641     else {
642       ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
643     }
644   }
645
646   return true;
647 }
648
649 static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
650 {
651   Mesh *me = ob->data;
652   BMEditMesh *em = me->edit_mesh;
653   MDeformVert *dvert_act;
654   int i, vgroup_tot, subset_count;
655   const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
656       ob, subset_type, &vgroup_tot, &subset_count);
657
658   if (em) {
659     BMIter iter;
660     BMVert *eve, *eve_act;
661     const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
662
663     dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
664     if (dvert_act) {
665       BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
666         if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
667           MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
668           BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
669           if (me->symmetry & ME_SYMMETRY_X) {
670             ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
671           }
672         }
673       }
674     }
675   }
676   else {
677     MDeformVert *dv;
678     int v_act;
679
680     dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
681     if (dvert_act) {
682       dv = me->dvert;
683       for (i = 0; i < me->totvert; i++, dv++) {
684         if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
685           BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
686           if (me->symmetry & ME_SYMMETRY_X) {
687             ED_mesh_defvert_mirror_update_ob(ob, -1, i);
688           }
689         }
690       }
691     }
692   }
693
694   MEM_freeN((void *)vgroup_validmap);
695 }
696
697 /** \} */
698
699 /* -------------------------------------------------------------------- */
700 /** \name Shared Weight Transfer Operator Properties
701  * \{ */
702
703 static const EnumPropertyItem WT_vertex_group_select_item[] = {
704     {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"},
705     {WT_VGROUP_BONE_SELECT,
706      "BONE_SELECT",
707      0,
708      "Selected Pose Bones",
709      "All Vertex Groups assigned to Selection"},
710     {WT_VGROUP_BONE_DEFORM,
711      "BONE_DEFORM",
712      0,
713      "Deform Pose Bones",
714      "All Vertex Groups assigned to Deform Bones"},
715     {WT_VGROUP_ALL, "ALL", 0, "All Groups", "All Vertex Groups"},
716     {0, NULL, 0, NULL, NULL},
717 };
718
719 const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *C,
720                                                                 PointerRNA *UNUSED(ptr),
721                                                                 PropertyRNA *UNUSED(prop),
722                                                                 bool *r_free,
723                                                                 const uint selection_mask)
724 {
725   Object *ob;
726   EnumPropertyItem *item = NULL;
727   int totitem = 0;
728
729   if (C == NULL) {
730     /* needed for docs and i18n tools */
731     return WT_vertex_group_select_item;
732   }
733
734   ob = CTX_data_active_object(C);
735   if (selection_mask & (1 << WT_VGROUP_ACTIVE)) {
736     RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
737   }
738
739   if (BKE_object_pose_armature_get(ob)) {
740     if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) {
741       RNA_enum_items_add_value(
742           &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
743     }
744     if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) {
745       RNA_enum_items_add_value(
746           &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
747     }
748   }
749
750   if (selection_mask & (1 << WT_VGROUP_ALL)) {
751     RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL);
752   }
753
754   RNA_enum_item_end(&item, &totitem);
755   *r_free = true;
756
757   return item;
758 }
759
760 static const EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C,
761                                                                   PointerRNA *ptr,
762                                                                   PropertyRNA *prop,
763                                                                   bool *r_free)
764 {
765   return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
766 }
767
768 static const EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C,
769                                                              PointerRNA *ptr,
770                                                              PropertyRNA *prop,
771                                                              bool *r_free)
772 {
773   return ED_object_vgroup_selection_itemf_helper(
774       C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
775 }
776
777 static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
778 {
779   PropertyRNA *prop;
780
781   prop = RNA_def_enum(ot->srna,
782                       "group_select_mode",
783                       DummyRNA_NULL_items,
784                       use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL,
785                       "Subset",
786                       "Define which subset of Groups shall be used");
787
788   if (use_active) {
789     RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
790   }
791   else {
792     RNA_def_enum_funcs(prop, rna_vertex_group_select_itemf);
793   }
794   RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
795   ot->prop = prop;
796 }
797
798 /** \} */
799
800 /* -------------------------------------------------------------------- */
801 /** \name High Level Vertex Group Add/Remove
802  *
803  * Wrap lower level `BKE` functions.
804  *
805  * \note that operations on many vertices should use #ED_vgroup_parray_alloc.
806  * \{ */
807
808 /* for Mesh in Object mode */
809 /* allows editmode for Lattice */
810 static void ED_vgroup_nr_vert_add(
811     Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode)
812 {
813   /* Add the vert to the deform group with the specified number. */
814   MDeformVert *dvert = NULL;
815   int tot;
816
817   /* Get the vert. */
818   BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
819
820   if (dvert == NULL) {
821     return;
822   }
823
824   /* Check that vertnum is valid before trying to get the relevant dvert. */
825   if ((vertnum < 0) || (vertnum >= tot)) {
826     return;
827   }
828
829   MDeformVert *dv = &dvert[vertnum];
830   MDeformWeight *dw;
831
832   /* Lets first check to see if this vert is already in the weight group - if so lets update it. */
833   dw = BKE_defvert_find_index(dv, def_nr);
834
835   if (dw) {
836     switch (assignmode) {
837       case WEIGHT_REPLACE:
838         dw->weight = weight;
839         break;
840       case WEIGHT_ADD:
841         dw->weight += weight;
842         if (dw->weight >= 1.0f) {
843           dw->weight = 1.0f;
844         }
845         break;
846       case WEIGHT_SUBTRACT:
847         dw->weight -= weight;
848         /* If the weight is zero or less than remove the vert from the deform group. */
849         if (dw->weight <= 0.0f) {
850           BKE_defvert_remove_group(dv, dw);
851         }
852         break;
853     }
854   }
855   else {
856     /* If the vert wasn't in the deform group then we must take a different form of action. */
857
858     switch (assignmode) {
859       case WEIGHT_SUBTRACT:
860         /* If we are subtracting then we don't need to do anything. */
861         return;
862
863       case WEIGHT_REPLACE:
864       case WEIGHT_ADD:
865         /* If we are doing an additive assignment, then we need to create the deform weight. */
866
867         /* We checked if the vertex was added before so no need to test again, simply add. */
868         BKE_defvert_add_index_notest(dv, def_nr, weight);
869         break;
870     }
871   }
872 }
873
874 /* called while not in editmode */
875 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
876 {
877   /* add the vert to the deform group with the
878    * specified assign mode
879    */
880   const int def_nr = BLI_findindex(&ob->defbase, dg);
881
882   MDeformVert *dv = NULL;
883   int tot;
884
885   /* get the deform group number, exit if
886    * it can't be found
887    */
888   if (def_nr != -1) {
889
890     /* if there's no deform verts then create some,
891      */
892     if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL) {
893       BKE_object_defgroup_data_create(ob->data);
894     }
895
896     /* call another function to do the work
897      */
898     ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
899   }
900 }
901
902 /* mesh object mode, lattice can be in editmode */
903 void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
904 {
905   /* This routine removes the vertex from the specified
906    * deform group.
907    */
908
909   /* TODO(campbell): This is slow in a loop, better pass def_nr directly,
910    * but leave for later. */
911   const int def_nr = BLI_findindex(&ob->defbase, dg);
912
913   if (def_nr != -1) {
914     MDeformVert *dvert = NULL;
915     int tot;
916
917     /* get the deform vertices corresponding to the
918      * vertnum
919      */
920     BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
921
922     if (dvert) {
923       MDeformVert *dv = &dvert[vertnum];
924       MDeformWeight *dw;
925
926       dw = BKE_defvert_find_index(dv, def_nr);
927       BKE_defvert_remove_group(dv, dw); /* dw can be NULL */
928     }
929   }
930 }
931
932 static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
933 {
934   MDeformVert *dv = NULL;
935
936   /* get the deform vertices corresponding to the vertnum */
937   if (ob->type == OB_MESH) {
938     Mesh *me = ob->data;
939
940     if (me->edit_mesh) {
941       BMEditMesh *em = me->edit_mesh;
942       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
943       /* warning, this lookup is _not_ fast */
944
945       if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
946         BMVert *eve;
947         BM_mesh_elem_table_ensure(em->bm, BM_VERT);
948         eve = BM_vert_at_index(em->bm, vertnum);
949         dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
950       }
951       else {
952         return 0.0f;
953       }
954     }
955     else {
956       if (me->dvert) {
957         if (vertnum >= me->totvert) {
958           return 0.0f;
959         }
960         dv = &me->dvert[vertnum];
961       }
962     }
963   }
964   else if (ob->type == OB_LATTICE) {
965     Lattice *lt = vgroup_edit_lattice(ob);
966
967     if (lt->dvert) {
968       if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
969         return 0.0f;
970       }
971       dv = &lt->dvert[vertnum];
972     }
973   }
974
975   if (dv) {
976     MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
977     if (dw) {
978       return dw->weight;
979     }
980   }
981
982   return -1;
983 }
984
985 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
986 {
987   const int def_nr = BLI_findindex(&ob->defbase, dg);
988
989   if (def_nr == -1) {
990     return -1;
991   }
992
993   return get_vert_def_nr(ob, def_nr, vertnum);
994 }
995
996 void ED_vgroup_select_by_name(Object *ob, const char *name)
997 {
998   /* note: ob->actdef==0 signals on painting to create a new one,
999    * if a bone in posemode is selected */
1000   ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1;
1001 }
1002
1003 /** \} */
1004
1005 /* -------------------------------------------------------------------- */
1006 /** \name Operator Function Implementations
1007  * \{ */
1008
1009 /* only in editmode */
1010 static void vgroup_select_verts(Object *ob, int select)
1011 {
1012   const int def_nr = ob->actdef - 1;
1013
1014   if (!BLI_findlink(&ob->defbase, def_nr)) {
1015     return;
1016   }
1017
1018   if (ob->type == OB_MESH) {
1019     Mesh *me = ob->data;
1020
1021     if (me->edit_mesh) {
1022       BMEditMesh *em = me->edit_mesh;
1023       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
1024
1025       if (cd_dvert_offset != -1) {
1026         BMIter iter;
1027         BMVert *eve;
1028
1029         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1030           if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
1031             MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
1032             if (BKE_defvert_find_index(dv, def_nr)) {
1033               BM_vert_select_set(em->bm, eve, select);
1034             }
1035           }
1036         }
1037
1038         /* this has to be called, because this function operates on vertices only */
1039         if (select) {
1040           EDBM_select_flush(em); /* vertices to edges/faces */
1041         }
1042         else {
1043           EDBM_deselect_flush(em);
1044         }
1045       }
1046     }
1047     else {
1048       if (me->dvert) {
1049         MVert *mv;
1050         MDeformVert *dv;
1051         int i;
1052
1053         mv = me->mvert;
1054         dv = me->dvert;
1055
1056         for (i = 0; i < me->totvert; i++, mv++, dv++) {
1057           if (!(mv->flag & ME_HIDE)) {
1058             if (BKE_defvert_find_index(dv, def_nr)) {
1059               if (select) {
1060                 mv->flag |= SELECT;
1061               }
1062               else {
1063                 mv->flag &= ~SELECT;
1064               }
1065             }
1066           }
1067         }
1068
1069         paintvert_flush_flags(ob);
1070       }
1071     }
1072   }
1073   else if (ob->type == OB_LATTICE) {
1074     Lattice *lt = vgroup_edit_lattice(ob);
1075
1076     if (lt->dvert) {
1077       MDeformVert *dv;
1078       BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
1079       int a, tot;
1080
1081       dv = lt->dvert;
1082
1083       tot = lt->pntsu * lt->pntsv * lt->pntsw;
1084       for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
1085         if (BKE_defvert_find_index(dv, def_nr)) {
1086           if (select) {
1087             bp->f1 |= SELECT;
1088           }
1089           else {
1090             bp->f1 &= ~SELECT;
1091             if (actbp && bp == actbp) {
1092               lt->actbp = LT_ACTBP_NONE;
1093             }
1094           }
1095         }
1096       }
1097     }
1098   }
1099 }
1100
1101 static void vgroup_duplicate(Object *ob)
1102 {
1103   bDeformGroup *dg, *cdg;
1104   char name[sizeof(dg->name)];
1105   MDeformWeight *dw_org, *dw_cpy;
1106   MDeformVert **dvert_array = NULL;
1107   int i, idg, icdg, dvert_tot = 0;
1108
1109   dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
1110   if (!dg) {
1111     return;
1112   }
1113
1114   if (!strstr(dg->name, "_copy")) {
1115     BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
1116   }
1117   else {
1118     BLI_strncpy(name, dg->name, sizeof(name));
1119   }
1120
1121   cdg = BKE_defgroup_duplicate(dg);
1122   BLI_strncpy(cdg->name, name, sizeof(cdg->name));
1123   BKE_object_defgroup_unique_name(cdg, ob);
1124
1125   BLI_addtail(&ob->defbase, cdg);
1126
1127   idg = (ob->actdef - 1);
1128   ob->actdef = BLI_listbase_count(&ob->defbase);
1129   icdg = (ob->actdef - 1);
1130
1131   /* TODO, we might want to allow only copy selected verts here? - campbell */
1132   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
1133
1134   if (dvert_array) {
1135     for (i = 0; i < dvert_tot; i++) {
1136       MDeformVert *dv = dvert_array[i];
1137       dw_org = BKE_defvert_find_index(dv, idg);
1138       if (dw_org) {
1139         /* BKE_defvert_ensure_index re-allocs org so need to store the weight first */
1140         const float weight = dw_org->weight;
1141         dw_cpy = BKE_defvert_ensure_index(dv, icdg);
1142         dw_cpy->weight = weight;
1143       }
1144     }
1145
1146     MEM_freeN(dvert_array);
1147   }
1148 }
1149
1150 static bool vgroup_normalize(Object *ob)
1151 {
1152   MDeformWeight *dw;
1153   MDeformVert *dv, **dvert_array = NULL;
1154   int dvert_tot = 0;
1155   const int def_nr = ob->actdef - 1;
1156
1157   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1158
1159   if (!BLI_findlink(&ob->defbase, def_nr)) {
1160     return false;
1161   }
1162
1163   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1164
1165   if (dvert_array) {
1166     float weight_max = 0.0f;
1167
1168     for (int i = 0; i < dvert_tot; i++) {
1169
1170       /* in case its not selected */
1171       if (!(dv = dvert_array[i])) {
1172         continue;
1173       }
1174
1175       dw = BKE_defvert_find_index(dv, def_nr);
1176       if (dw) {
1177         weight_max = max_ff(dw->weight, weight_max);
1178       }
1179     }
1180
1181     if (weight_max > 0.0f) {
1182       for (int i = 0; i < dvert_tot; i++) {
1183
1184         /* in case its not selected */
1185         if (!(dv = dvert_array[i])) {
1186           continue;
1187         }
1188
1189         dw = BKE_defvert_find_index(dv, def_nr);
1190         if (dw) {
1191           dw->weight /= weight_max;
1192
1193           /* in case of division errors with very low weights */
1194           CLAMP(dw->weight, 0.0f, 1.0f);
1195         }
1196       }
1197     }
1198
1199     MEM_freeN(dvert_array);
1200
1201     return true;
1202   }
1203
1204   return false;
1205 }
1206
1207 /* This finds all of the vertices face-connected to vert by an edge and returns a
1208  * MEM_allocated array of indices of size count.
1209  * count is an int passed by reference so it can be assigned the value of the length here. */
1210 static int *getSurroundingVerts(Mesh *me, int vert, int *count)
1211 {
1212   MPoly *mp = me->mpoly;
1213   int i = me->totpoly;
1214   /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
1215    * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
1216    * many vertices face-linked to another one, even 8 might be too high...). */
1217   int *verts = NULL;
1218   BLI_array_declare(verts);
1219
1220   BLI_array_reserve(verts, 8);
1221   while (i--) {
1222     int j = mp->totloop;
1223     int first_l = mp->totloop - 1;
1224     MLoop *ml = &me->mloop[mp->loopstart];
1225     while (j--) {
1226       /* XXX This assume a vert can only be once in a poly, even though
1227        *     it seems logical to me, not totally sure of that. */
1228       if (ml->v == vert) {
1229         int a, b, k;
1230         if (j == first_l) {
1231           /* We are on the first corner. */
1232           a = ml[1].v;
1233           b = ml[j].v;
1234         }
1235         else if (!j) {
1236           /* We are on the last corner. */
1237           a = (ml - 1)->v;
1238           b = me->mloop[mp->loopstart].v;
1239         }
1240         else {
1241           a = (ml - 1)->v;
1242           b = (ml + 1)->v;
1243         }
1244
1245         /* Append a and b verts to array, if not yet present. */
1246         k = BLI_array_len(verts);
1247         /* XXX Maybe a == b is enough? */
1248         while (k-- && !(a == b && a == -1)) {
1249           if (verts[k] == a) {
1250             a = -1;
1251           }
1252           else if (verts[k] == b) {
1253             b = -1;
1254           }
1255         }
1256         if (a != -1) {
1257           BLI_array_append(verts, a);
1258         }
1259         if (b != -1) {
1260           BLI_array_append(verts, b);
1261         }
1262
1263         /* Vert found in this poly, we can go to next one! */
1264         break;
1265       }
1266       ml++;
1267     }
1268     mp++;
1269   }
1270
1271   /* Do not free the array! */
1272   *count = BLI_array_len(verts);
1273   return verts;
1274 }
1275
1276 /* Get a single point in space by averaging a point cloud (vectors of size 3)
1277  * coord is the place the average is stored,
1278  * points is the point cloud, count is the number of points in the cloud.
1279  */
1280 static void getSingleCoordinate(MVert *points, int count, float coord[3])
1281 {
1282   int i;
1283   zero_v3(coord);
1284   for (i = 0; i < count; i++) {
1285     add_v3_v3(coord, points[i].co);
1286   }
1287   mul_v3_fl(coord, 1.0f / count);
1288 }
1289
1290 /* given a plane and a start and end position,
1291  * compute the amount of vertical distance relative to the plane and store it in dists,
1292  * then get the horizontal and vertical change and store them in changes
1293  */
1294 static void getVerticalAndHorizontalChange(const float norm[3],
1295                                            float d,
1296                                            const float coord[3],
1297                                            const float start[3],
1298                                            float distToStart,
1299                                            float *end,
1300                                            float (*changes)[2],
1301                                            float *dists,
1302                                            int index)
1303 {
1304   /* A = Q - ((Q - P).N)N
1305    * D = (a * x0 + b * y0 +c * z0 + d) */
1306   float projA[3], projB[3];
1307   float plane[4];
1308
1309   plane_from_point_normal_v3(plane, coord, norm);
1310
1311   closest_to_plane_normalized_v3(projA, plane, start);
1312   closest_to_plane_normalized_v3(projB, plane, end);
1313   /* (vertical and horizontal refer to the plane's y and xz respectively)
1314    * vertical distance */
1315   dists[index] = dot_v3v3(norm, end) + d;
1316   /* vertical change */
1317   changes[index][0] = dists[index] - distToStart;
1318   // printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
1319   /* horizontal change */
1320   changes[index][1] = len_v3v3(projA, projB);
1321 }
1322
1323 /* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
1324  * distToBe distance away from the provided plane strength can change distToBe so that it moves
1325  * towards distToBe by that percentage cp changes how much the weights are adjusted
1326  * to check the distance
1327  *
1328  * index is the index of the vertex being moved
1329  * norm and d are the plane's properties for the equation: ax + by + cz + d = 0
1330  * coord is a point on the plane
1331  */
1332 static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph,
1333                                           Scene *UNUSED(scene),
1334                                           Object *ob,
1335                                           Mesh *me,
1336                                           int index,
1337                                           const float norm[3],
1338                                           const float coord[3],
1339                                           float d,
1340                                           float distToBe,
1341                                           float strength,
1342                                           float cp)
1343 {
1344   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
1345   Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1346   Mesh *mesh_eval = (Mesh *)object_eval->data;
1347
1348   Mesh *me_deform;
1349   MDeformWeight *dw, *dw_eval;
1350   MVert m;
1351   MDeformVert *dvert = me->dvert + index;
1352   MDeformVert *dvert_eval = mesh_eval->dvert + index;
1353   int totweight = dvert->totweight;
1354   float oldw = 0;
1355   float oldPos[3] = {0};
1356   float vc, hc, dist = 0.0f;
1357   int i, k;
1358   float(*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
1359   float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
1360
1361   /* track if up or down moved it closer for each bone */
1362   int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
1363
1364   int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
1365   float distToStart;
1366   int bestIndex = 0;
1367   bool wasChange;
1368   char wasUp;
1369   int lastIndex = -1;
1370   float originalDistToBe = distToBe;
1371   do {
1372     wasChange = false;
1373     me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1374     m = me_deform->mvert[index];
1375     copy_v3_v3(oldPos, m.co);
1376     distToStart = dot_v3v3(norm, oldPos) + d;
1377
1378     if (distToBe == originalDistToBe) {
1379       distToBe += distToStart - distToStart * strength;
1380     }
1381     for (i = 0; i < totweight; i++) {
1382       dwIndices[i] = i;
1383       dw = (dvert->dw + i);
1384       dw_eval = (dvert_eval->dw + i);
1385       vc = hc = 0;
1386       if (!dw->weight) {
1387         changes[i][0] = 0;
1388         changes[i][1] = 0;
1389         dists[i] = distToStart;
1390         continue;
1391       }
1392       for (k = 0; k < 2; k++) {
1393         if (me_deform) {
1394           /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
1395            * Better to over-free and recompute a bit. */
1396           BKE_object_free_derived_caches(object_eval);
1397         }
1398         oldw = dw->weight;
1399         if (k) {
1400           dw->weight *= 1 + cp;
1401         }
1402         else {
1403           dw->weight /= 1 + cp;
1404         }
1405         if (dw->weight == oldw) {
1406           changes[i][0] = 0;
1407           changes[i][1] = 0;
1408           dists[i] = distToStart;
1409           break;
1410         }
1411         if (dw->weight > 1) {
1412           dw->weight = 1;
1413         }
1414         dw_eval->weight = dw->weight;
1415         me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1416         m = me_deform->mvert[index];
1417         getVerticalAndHorizontalChange(
1418             norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
1419         dw->weight = oldw;
1420         dw_eval->weight = oldw;
1421         if (!k) {
1422           vc = changes[i][0];
1423           hc = changes[i][1];
1424           dist = dists[i];
1425         }
1426         else {
1427           if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
1428             upDown[i] = 0;
1429             changes[i][0] = vc;
1430             changes[i][1] = hc;
1431             dists[i] = dist;
1432           }
1433           else {
1434             upDown[i] = 1;
1435           }
1436           if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
1437             changes[i][0] = 0;
1438             changes[i][1] = 0;
1439             dists[i] = distToStart;
1440           }
1441         }
1442       }
1443     }
1444     /* sort the changes by the vertical change */
1445     for (k = 0; k < totweight; k++) {
1446       float tf;
1447       int ti;
1448       bestIndex = k;
1449       for (i = k + 1; i < totweight; i++) {
1450         dist = dists[i];
1451
1452         if (fabsf(dist) > fabsf(dists[i])) {
1453           bestIndex = i;
1454         }
1455       }
1456       /* switch with k */
1457       if (bestIndex != k) {
1458         ti = upDown[k];
1459         upDown[k] = upDown[bestIndex];
1460         upDown[bestIndex] = ti;
1461
1462         ti = dwIndices[k];
1463         dwIndices[k] = dwIndices[bestIndex];
1464         dwIndices[bestIndex] = ti;
1465
1466         tf = changes[k][0];
1467         changes[k][0] = changes[bestIndex][0];
1468         changes[bestIndex][0] = tf;
1469
1470         tf = changes[k][1];
1471         changes[k][1] = changes[bestIndex][1];
1472         changes[bestIndex][1] = tf;
1473
1474         tf = dists[k];
1475         dists[k] = dists[bestIndex];
1476         dists[bestIndex] = tf;
1477       }
1478     }
1479     bestIndex = -1;
1480     /* find the best change with an acceptable horizontal change */
1481     for (i = 0; i < totweight; i++) {
1482       if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
1483         bestIndex = i;
1484         break;
1485       }
1486     }
1487     if (bestIndex != -1) {
1488       wasChange = true;
1489       /* it is a good place to stop if it tries to move the opposite direction
1490        * (relative to the plane) of last time */
1491       if (lastIndex != -1) {
1492         if (wasUp != upDown[bestIndex]) {
1493           wasChange = false;
1494         }
1495       }
1496       lastIndex = bestIndex;
1497       wasUp = upDown[bestIndex];
1498       dw = (dvert->dw + dwIndices[bestIndex]);
1499       oldw = dw->weight;
1500       if (upDown[bestIndex]) {
1501         dw->weight *= 1 + cp;
1502       }
1503       else {
1504         dw->weight /= 1 + cp;
1505       }
1506       if (dw->weight > 1) {
1507         dw->weight = 1;
1508       }
1509       if (oldw == dw->weight) {
1510         wasChange = false;
1511       }
1512       if (me_deform) {
1513         /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
1514          * Better to over-free and recompute a bit. */
1515         BKE_object_free_derived_caches(object_eval);
1516       }
1517     }
1518   } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
1519                          (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
1520
1521   MEM_freeN(upDown);
1522   MEM_freeN(changes);
1523   MEM_freeN(dists);
1524   MEM_freeN(dwIndices);
1525 }
1526
1527 /* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
1528  * but it could be used to raise or lower an existing 'bump.' */
1529 static void vgroup_fix(
1530     const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp)
1531 {
1532   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
1533   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
1534   Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1535   int i;
1536
1537   Mesh *me = ob->data;
1538   MVert *mvert = me->mvert;
1539   int *verts = NULL;
1540   if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL)) {
1541     return;
1542   }
1543   for (i = 0; i < me->totvert && mvert; i++, mvert++) {
1544     if (mvert->flag & SELECT) {
1545       int count = 0;
1546       if ((verts = getSurroundingVerts(me, i, &count))) {
1547         MVert m;
1548         MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
1549         int k;
1550
1551         Mesh *me_deform = mesh_get_eval_deform(
1552             depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1553         k = count;
1554         while (k--) {
1555           p[k] = me_deform->mvert[verts[k]];
1556         }
1557
1558         if (count >= 3) {
1559           float d /*, dist */ /* UNUSED */, mag;
1560           float coord[3];
1561           float norm[3];
1562           getSingleCoordinate(p, count, coord);
1563           m = me_deform->mvert[i];
1564           sub_v3_v3v3(norm, m.co, coord);
1565           mag = normalize_v3(norm);
1566           if (mag) { /* zeros fix */
1567             d = -dot_v3v3(norm, coord);
1568             /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
1569             moveCloserToDistanceFromPlane(
1570                 depsgraph, scene_eval, object_eval, me, i, norm, coord, d, distToBe, strength, cp);
1571           }
1572         }
1573
1574         MEM_freeN(verts);
1575         MEM_freeN(p);
1576       }
1577     }
1578   }
1579 }
1580
1581 static void vgroup_levels_subset(Object *ob,
1582                                  const bool *vgroup_validmap,
1583                                  const int vgroup_tot,
1584                                  const int UNUSED(subset_count),
1585                                  const float offset,
1586                                  const float gain)
1587 {
1588   MDeformWeight *dw;
1589   MDeformVert *dv, **dvert_array = NULL;
1590   int dvert_tot = 0;
1591
1592   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1593   const bool use_mirror = (ob->type == OB_MESH) ?
1594                               (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1595                               false;
1596
1597   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1598
1599   if (dvert_array) {
1600
1601     for (int i = 0; i < dvert_tot; i++) {
1602       /* in case its not selected */
1603       if (!(dv = dvert_array[i])) {
1604         continue;
1605       }
1606
1607       int j = vgroup_tot;
1608       while (j--) {
1609         if (vgroup_validmap[j]) {
1610           dw = BKE_defvert_find_index(dv, j);
1611           if (dw) {
1612             dw->weight = gain * (dw->weight + offset);
1613
1614             CLAMP(dw->weight, 0.0f, 1.0f);
1615           }
1616         }
1617       }
1618     }
1619
1620     if (use_mirror && use_vert_sel) {
1621       ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
1622     }
1623
1624     MEM_freeN(dvert_array);
1625   }
1626 }
1627
1628 static bool vgroup_normalize_all(Object *ob,
1629                                  const bool *vgroup_validmap,
1630                                  const int vgroup_tot,
1631                                  const int subset_count,
1632                                  const bool lock_active,
1633                                  ReportList *reports)
1634 {
1635   MDeformVert *dv, **dvert_array = NULL;
1636   int i, dvert_tot = 0;
1637   const int def_nr = ob->actdef - 1;
1638
1639   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1640
1641   if (subset_count == 0) {
1642     BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
1643     return false;
1644   }
1645
1646   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1647
1648   if (dvert_array) {
1649     const int defbase_tot = BLI_listbase_count(&ob->defbase);
1650     bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
1651     bool changed = false;
1652
1653     if ((lock_active == true) && (lock_flags != NULL) && (def_nr < defbase_tot)) {
1654       lock_flags[def_nr] = true;
1655     }
1656
1657     if (lock_flags) {
1658       for (i = 0; i < defbase_tot; i++) {
1659         if (lock_flags[i] == false) {
1660           break;
1661         }
1662       }
1663
1664       if (i == defbase_tot) {
1665         BKE_report(reports, RPT_ERROR, "All groups are locked");
1666         goto finally;
1667       }
1668     }
1669
1670     for (i = 0; i < dvert_tot; i++) {
1671       /* in case its not selected */
1672       if ((dv = dvert_array[i])) {
1673         if (lock_flags) {
1674           BKE_defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, lock_flags, defbase_tot);
1675         }
1676         else if (lock_active) {
1677           BKE_defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
1678         }
1679         else {
1680           BKE_defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
1681         }
1682       }
1683     }
1684
1685     changed = true;
1686
1687   finally:
1688     if (lock_flags) {
1689       MEM_freeN(lock_flags);
1690     }
1691
1692     MEM_freeN(dvert_array);
1693
1694     return changed;
1695   }
1696
1697   return false;
1698 }
1699
1700 enum {
1701   VGROUP_TOGGLE,
1702   VGROUP_LOCK,
1703   VGROUP_UNLOCK,
1704   VGROUP_INVERT,
1705 };
1706
1707 static const EnumPropertyItem vgroup_lock_actions[] = {
1708     {VGROUP_TOGGLE,
1709      "TOGGLE",
1710      0,
1711      "Toggle",
1712      "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
1713     {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
1714     {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
1715     {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
1716     {0, NULL, 0, NULL, NULL},
1717 };
1718
1719 enum {
1720   VGROUP_MASK_ALL,
1721   VGROUP_MASK_SELECTED,
1722   VGROUP_MASK_UNSELECTED,
1723   VGROUP_MASK_INVERT_UNSELECTED,
1724 };
1725
1726 static const EnumPropertyItem vgroup_lock_mask[] = {
1727     {VGROUP_MASK_ALL, "ALL", 0, "All", "Apply action to all vertex groups"},
1728     {VGROUP_MASK_SELECTED, "SELECTED", 0, "Selected", "Apply to selected vertex groups"},
1729     {VGROUP_MASK_UNSELECTED, "UNSELECTED", 0, "Unselected", "Apply to unselected vertex groups"},
1730     {VGROUP_MASK_INVERT_UNSELECTED,
1731      "INVERT_UNSELECTED",
1732      0,
1733      "Invert Unselected",
1734      "Apply the opposite of Lock/Unlock to unselected vertex groups"},
1735     {0, NULL, 0, NULL, NULL},
1736 };
1737
1738 static bool *vgroup_selected_get(Object *ob)
1739 {
1740   int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase);
1741   bool *mask;
1742
1743   if (ob->mode & OB_MODE_WEIGHT_PAINT) {
1744     mask = BKE_object_defgroup_selected_get(ob, defbase_tot, &sel_count);
1745
1746     /* Mirror the selection if X Mirror is enabled. */
1747     Mesh *me = BKE_mesh_from_object(ob);
1748
1749     if (me && (me->symmetry & ME_SYMMETRY_X) != 0) {
1750       BKE_object_defgroup_mirror_selection(ob, defbase_tot, mask, mask, &sel_count);
1751     }
1752   }
1753   else {
1754     mask = MEM_callocN(defbase_tot * sizeof(bool), __func__);
1755   }
1756
1757   if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) {
1758     mask[ob->actdef - 1] = true;
1759   }
1760
1761   return mask;
1762 }
1763
1764 static void vgroup_lock_all(Object *ob, int action, int mask)
1765 {
1766   bDeformGroup *dg;
1767   bool *selected = NULL;
1768   int i;
1769
1770   if (mask != VGROUP_MASK_ALL) {
1771     selected = vgroup_selected_get(ob);
1772   }
1773
1774   if (action == VGROUP_TOGGLE) {
1775     action = VGROUP_LOCK;
1776
1777     for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
1778       switch (mask) {
1779         case VGROUP_MASK_INVERT_UNSELECTED:
1780         case VGROUP_MASK_SELECTED:
1781           if (!selected[i]) {
1782             continue;
1783           }
1784           break;
1785         case VGROUP_MASK_UNSELECTED:
1786           if (selected[i]) {
1787             continue;
1788           }
1789           break;
1790         default:;
1791       }
1792
1793       if (dg->flag & DG_LOCK_WEIGHT) {
1794         action = VGROUP_UNLOCK;
1795         break;
1796       }
1797     }
1798   }
1799
1800   for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
1801     switch (mask) {
1802       case VGROUP_MASK_SELECTED:
1803         if (!selected[i]) {
1804           continue;
1805         }
1806         break;
1807       case VGROUP_MASK_UNSELECTED:
1808         if (selected[i]) {
1809           continue;
1810         }
1811         break;
1812       default:;
1813     }
1814
1815     switch (action) {
1816       case VGROUP_LOCK:
1817         dg->flag |= DG_LOCK_WEIGHT;
1818         break;
1819       case VGROUP_UNLOCK:
1820         dg->flag &= ~DG_LOCK_WEIGHT;
1821         break;
1822       case VGROUP_INVERT:
1823         dg->flag ^= DG_LOCK_WEIGHT;
1824         break;
1825     }
1826
1827     if (mask == VGROUP_MASK_INVERT_UNSELECTED && !selected[i]) {
1828       dg->flag ^= DG_LOCK_WEIGHT;
1829     }
1830   }
1831
1832   if (selected) {
1833     MEM_freeN(selected);
1834   }
1835 }
1836
1837 static void vgroup_invert_subset(Object *ob,
1838                                  const bool *vgroup_validmap,
1839                                  const int vgroup_tot,
1840                                  const int UNUSED(subset_count),
1841                                  const bool auto_assign,
1842                                  const bool auto_remove)
1843 {
1844   MDeformWeight *dw;
1845   MDeformVert *dv, **dvert_array = NULL;
1846   int dvert_tot = 0;
1847   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1848   const bool use_mirror = (ob->type == OB_MESH) ?
1849                               (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1850                               false;
1851
1852   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1853
1854   if (dvert_array) {
1855     for (int i = 0; i < dvert_tot; i++) {
1856       /* in case its not selected */
1857       if (!(dv = dvert_array[i])) {
1858         continue;
1859       }
1860
1861       int j = vgroup_tot;
1862       while (j--) {
1863
1864         if (vgroup_validmap[j]) {
1865           if (auto_assign) {
1866             dw = BKE_defvert_ensure_index(dv, j);
1867           }
1868           else {
1869             dw = BKE_defvert_find_index(dv, j);
1870           }
1871
1872           if (dw) {
1873             dw->weight = 1.0f - dw->weight;
1874             CLAMP(dw->weight, 0.0f, 1.0f);
1875           }
1876         }
1877       }
1878     }
1879
1880     if (use_mirror && use_vert_sel) {
1881       ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
1882     }
1883
1884     if (auto_remove) {
1885       ED_vgroup_parray_remove_zero(
1886           dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, 0.0f, false);
1887     }
1888
1889     MEM_freeN(dvert_array);
1890   }
1891 }
1892
1893 static void vgroup_smooth_subset(Object *ob,
1894                                  const bool *vgroup_validmap,
1895                                  const int vgroup_tot,
1896                                  const int subset_count,
1897                                  const float fac,
1898                                  const int repeat,
1899                                  const float fac_expand)
1900 {
1901   const float ifac = 1.0f - fac;
1902   MDeformVert **dvert_array = NULL;
1903   int dvert_tot = 0;
1904   int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
1905   float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
1906   const bool use_mirror = (ob->type == OB_MESH) ?
1907                               (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1908                               false;
1909   const bool use_select = vertex_group_use_vert_sel(ob);
1910   const bool use_hide = use_select;
1911
1912   const int expand_sign = signum_i(fac_expand);
1913   const float expand = fabsf(fac_expand);
1914   const float iexpand = 1.0f - expand;
1915
1916   BMEditMesh *em = BKE_editmesh_from_object(ob);
1917   BMesh *bm = em ? em->bm : NULL;
1918   Mesh *me = em ? NULL : ob->data;
1919
1920   MeshElemMap *emap;
1921   int *emap_mem;
1922
1923   float *weight_accum_prev;
1924   float *weight_accum_curr;
1925
1926   uint subset_index;
1927
1928   /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
1929   uint *verts_used;
1930   STACK_DECLARE(verts_used);
1931
1932   BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
1933   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
1934   memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
1935
1936   if (bm) {
1937     BM_mesh_elem_table_ensure(bm, BM_VERT);
1938     BM_mesh_elem_index_ensure(bm, BM_VERT);
1939
1940     emap = NULL;
1941     emap_mem = NULL;
1942   }
1943   else {
1944     BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
1945   }
1946
1947   weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
1948   weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
1949
1950   verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
1951   STACK_INIT(verts_used, dvert_tot);
1952
1953 #define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
1954 #define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
1955
1956 #define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
1957 #define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true)
1958
1959   /* initialize used verts */
1960   if (bm) {
1961     for (int i = 0; i < dvert_tot; i++) {
1962       BMVert *v = BM_vert_at_index(bm, i);
1963       if (IS_BM_VERT_WRITE(v)) {
1964         BMIter eiter;
1965         BMEdge *e;
1966         BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
1967           BMVert *v_other = BM_edge_other_vert(e, v);
1968           if (IS_BM_VERT_READ(v_other)) {
1969             STACK_PUSH(verts_used, i);
1970             break;
1971           }
1972         }
1973       }
1974     }
1975   }
1976   else {
1977     for (int i = 0; i < dvert_tot; i++) {
1978       const MVert *v = &me->mvert[i];
1979       if (IS_ME_VERT_WRITE(v)) {
1980         for (int j = 0; j < emap[i].count; j++) {
1981           const MEdge *e = &me->medge[emap[i].indices[j]];
1982           const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
1983           if (IS_ME_VERT_READ(v_other)) {
1984             STACK_PUSH(verts_used, i);
1985             break;
1986           }
1987         }
1988       }
1989     }
1990   }
1991
1992   for (subset_index = 0; subset_index < subset_count; subset_index++) {
1993     const int def_nr = vgroup_subset_map[subset_index];
1994     int iter;
1995
1996     ED_vgroup_parray_to_weight_array(
1997         (const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
1998     memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
1999
2000     for (iter = 0; iter < repeat; iter++) {
2001       uint *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
2002
2003       /* avoid looping over all verts */
2004       // for (i = 0; i < dvert_tot; i++)
2005       for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
2006         const uint i = *vi_step;
2007         float weight_tot = 0.0f;
2008         float weight = 0.0f;
2009
2010 #define WEIGHT_ACCUMULATE \
2011   { \
2012     float weight_other = weight_accum_prev[i_other]; \
2013     float tot_factor = 1.0f; \
2014     if (expand_sign == 1) { /* expand */ \
2015       if (weight_other < weight_accum_prev[i]) { \
2016         weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
2017         tot_factor = iexpand; \
2018       } \
2019     } \
2020     else if (expand_sign == -1) { /* contract */ \
2021       if (weight_other > weight_accum_prev[i]) { \
2022         weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
2023         tot_factor = iexpand; \
2024       } \
2025     } \
2026     weight += tot_factor * weight_other; \
2027     weight_tot += tot_factor; \
2028   } \
2029   ((void)0)
2030
2031         if (bm) {
2032           BMVert *v = BM_vert_at_index(bm, i);
2033           BMIter eiter;
2034           BMEdge *e;
2035
2036           /* checked already */
2037           BLI_assert(IS_BM_VERT_WRITE(v));
2038
2039           BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
2040             BMVert *v_other = BM_edge_other_vert(e, v);
2041             if (IS_BM_VERT_READ(v_other)) {
2042               const int i_other = BM_elem_index_get(v_other);
2043
2044               WEIGHT_ACCUMULATE;
2045             }
2046           }
2047         }
2048         else {
2049           int j;
2050
2051           /* checked already */
2052           BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
2053
2054           for (j = 0; j < emap[i].count; j++) {
2055             MEdge *e = &me->medge[emap[i].indices[j]];
2056             const int i_other = (e->v1 == i ? e->v2 : e->v1);
2057             MVert *v_other = &me->mvert[i_other];
2058
2059             if (IS_ME_VERT_READ(v_other)) {
2060               WEIGHT_ACCUMULATE;
2061             }
2062           }
2063         }
2064
2065 #undef WEIGHT_ACCUMULATE
2066
2067         if (weight_tot != 0.0f) {
2068           weight /= weight_tot;
2069           weight = (weight_accum_prev[i] * ifac) + (weight * fac);
2070
2071           /* should be within range, just clamp because of float precision */
2072           CLAMP(weight, 0.0f, 1.0f);
2073           weight_accum_curr[i] = weight;
2074         }
2075       }
2076
2077       SWAP(float *, weight_accum_curr, weight_accum_prev);
2078     }
2079
2080     ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
2081   }
2082
2083 #undef IS_BM_VERT_READ
2084 #undef IS_BM_VERT_WRITE
2085 #undef IS_ME_VERT_READ
2086 #undef IS_ME_VERT_WRITE
2087
2088   MEM_freeN(weight_accum_curr);
2089   MEM_freeN(weight_accum_prev);
2090   MEM_freeN(verts_used);
2091
2092   if (bm) {
2093     /* pass */
2094   }
2095   else {
2096     MEM_freeN(emap);
2097     MEM_freeN(emap_mem);
2098   }
2099
2100   if (dvert_array) {
2101     MEM_freeN(dvert_array);
2102   }
2103
2104   /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
2105   if (use_mirror) {
2106     ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
2107     ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
2108     if (dvert_array) {
2109       MEM_freeN(dvert_array);
2110     }
2111   }
2112 }
2113
2114 static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
2115 {
2116   /* qsort sorts in ascending order.  We want descending order to save a memcopy
2117    * so this compare function is inverted from the standard greater than comparison qsort needs.
2118    * A normal compare function is called with two pointer arguments and should return an integer
2119    * less than, equal to, or greater than zero corresponding to whether its first argument is
2120    * considered less than, equal to, or greater than its second argument.
2121    * This does the opposite. */
2122   const struct MDeformWeight *dw1 = a1, *dw2 = a2;
2123
2124   if (dw1->weight < dw2->weight) {
2125     return 1;
2126   }
2127   if (dw1->weight > dw2->weight) {
2128     return -1;
2129   }
2130   if (&dw1 < &dw2) {
2131     return 1; /* compare address for stable sort algorithm */
2132   }
2133   return -1;
2134 }
2135
2136 /* Used for limiting the number of influencing bones per vertex when exporting
2137  * skinned meshes.  if all_deform_weights is True, limit all deform modifiers
2138  * to max_weights regardless of type, otherwise,
2139  * only limit the number of influencing bones per vertex. */
2140 static int vgroup_limit_total_subset(Object *ob,
2141                                      const bool *vgroup_validmap,
2142                                      const int vgroup_tot,
2143                                      const int subset_count,
2144                                      const int max_weights)
2145 {
2146   MDeformVert *dv, **dvert_array = NULL;
2147   int i, dvert_tot = 0;
2148   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2149   int remove_tot = 0;
2150
2151   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2152
2153   if (dvert_array) {
2154     int num_to_drop = 0;
2155
2156     for (i = 0; i < dvert_tot; i++) {
2157
2158       MDeformWeight *dw_temp;
2159       int bone_count = 0, non_bone_count = 0;
2160       int j;
2161
2162       /* in case its not selected */
2163       if (!(dv = dvert_array[i])) {
2164         continue;
2165       }
2166
2167       num_to_drop = subset_count - max_weights;
2168
2169       /* first check if we even need to test further */
2170       if (num_to_drop > 0) {
2171         /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
2172          * sort the tail, then copy only the truncated array back to dv->dw */
2173         dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
2174         bone_count = 0;
2175         non_bone_count = 0;
2176         for (j = 0; j < dv->totweight; j++) {
2177           if (LIKELY(dv->dw[j].def_nr < vgroup_tot) && vgroup_validmap[dv->dw[j].def_nr]) {
2178             dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
2179             bone_count += 1;
2180           }
2181           else {
2182             dw_temp[non_bone_count] = dv->dw[j];
2183             non_bone_count += 1;
2184           }
2185         }
2186         BLI_assert(bone_count + non_bone_count == dv->totweight);
2187         num_to_drop = bone_count - max_weights;
2188         if (num_to_drop > 0) {
2189           qsort(&dw_temp[non_bone_count],
2190                 bone_count,
2191                 sizeof(MDeformWeight),
2192                 inv_cmp_mdef_vert_weights);
2193           dv->totweight -= num_to_drop;
2194           /* Do we want to clean/normalize here? */
2195           MEM_freeN(dv->dw);
2196           dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
2197           remove_tot += num_to_drop;
2198         }
2199         else {
2200           MEM_freeN(dw_temp);
2201         }
2202       }
2203     }
2204     MEM_freeN(dvert_array);
2205   }
2206
2207   return remove_tot;
2208 }
2209
2210 static void vgroup_clean_subset(Object *ob,
2211                                 const bool *vgroup_validmap,
2212                                 const int vgroup_tot,
2213                                 const int UNUSED(subset_count),
2214                                 const float epsilon,
2215                                 const bool keep_single)
2216 {
2217   MDeformVert **dvert_array = NULL;
2218   int dvert_tot = 0;
2219   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2220   const bool use_mirror = (ob->type == OB_MESH) ?
2221                               (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
2222                               false;
2223
2224   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2225
2226   if (dvert_array) {
2227     if (use_mirror && use_vert_sel) {
2228       /* correct behavior in this case isn't well defined
2229        * for now assume both sides are mirrored correctly,
2230        * so cleaning one side also cleans the other */
2231       ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
2232     }
2233
2234     ED_vgroup_parray_remove_zero(
2235         dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, epsilon, keep_single);
2236
2237     MEM_freeN(dvert_array);
2238   }
2239 }
2240
2241 static void vgroup_quantize_subset(Object *ob,
2242                                    const bool *vgroup_validmap,
2243                                    const int vgroup_tot,
2244                                    const int UNUSED(subset_count),
2245                                    const int steps)
2246 {
2247   MDeformVert **dvert_array = NULL;
2248   int dvert_tot = 0;
2249   const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2250   const bool use_mirror = (ob->type == OB_MESH) ?
2251                               (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
2252                               false;
2253   ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2254
2255   if (dvert_array) {
2256     const float steps_fl = steps;
2257     MDeformVert *dv;
2258
2259     if (use_mirror && use_vert_sel) {
2260       ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
2261     }
2262
2263     for (int i = 0; i < dvert_tot; i++) {
2264       MDeformWeight *dw;
2265
2266       /* in case its not selected */
2267       if (!(dv = dvert_array[i])) {
2268         continue;
2269       }
2270
2271       int j;
2272       for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
2273         if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
2274           dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
2275           CLAMP(dw->weight, 0.0f, 1.0f);
2276         }
2277       }
2278     }
2279
2280     MEM_freeN(dvert_array);
2281   }
2282 }
2283
2284 static void dvert_mirror_op(MDeformVert *dvert,
2285                             MDeformVert *dvert_mirr,
2286                             const char sel,
2287                             const char sel_mirr,
2288                             const int *flip_map,
2289                             const int flip_map_len,
2290                             const bool mirror_weights,
2291                             const bool flip_vgroups,
2292                             const bool all_vgroups,
2293                             const int act_vgroup)
2294 {
2295   BLI_assert(sel || sel_mirr);
2296
2297   if (sel_mirr && sel) {
2298     /* swap */
2299     if (mirror_weights) {
2300       if (all_vgroups) {
2301         SWAP(MDeformVert, *dvert, *dvert_mirr);
2302       }
2303       else {
2304         MDeformWeight *dw = BKE_defvert_find_index(dvert, act_vgroup);
2305         MDeformWeight *dw_mirr = BKE_defvert_find_index(dvert_mirr, act_vgroup);
2306
2307         if (dw && dw_mirr) {
2308           SWAP(float, dw->weight, dw_mirr->weight);
2309         }
2310         else if (dw) {
2311           dw_mirr = BKE_defvert_ensure_index(dvert_mirr, act_vgroup);
2312           dw_mirr->weight = dw->weight;
2313           BKE_defvert_remove_group(dvert, dw);
2314         }
2315         else if (dw_mirr) {
2316           dw = BKE_defvert_ensure_index(dvert, act_vgroup);
2317           dw->weight = dw_mirr->weight;
2318           BKE_defvert_remove_group(dvert_mirr, dw_mirr);
2319         }
2320       }
2321     }
2322
2323     if (flip_vgroups) {
2324       BKE_defvert_flip(dvert, flip_map, flip_map_len);
2325       BKE_defvert_flip(dvert_mirr, flip_map, flip_map_len);
2326     }
2327   }
2328   else {
2329     /* dvert should always be the target, only swaps pointer */
2330     if (sel_mirr) {
2331       SWAP(MDeformVert *, dvert, dvert_mirr);
2332     }
2333
2334     if (mirror_weights) {
2335       if (all_vgroups) {
2336         BKE_defvert_copy(dvert, dvert_mirr);
2337       }
2338       else {
2339         BKE_defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
2340       }
2341     }
2342
2343     /* flip map already modified for 'all_vgroups' */
2344     if (flip_vgroups) {
2345       BKE_defvert_flip(dvert, flip_map, flip_map_len);
2346     }
2347   }
2348 }
2349
2350 /* TODO, vgroup locking */
2351 /* TODO, face masking */
2352 void ED_vgroup_mirror(Object *ob,
2353                       const bool mirror_weights,
2354                       const bool flip_vgroups,
2355                       const bool all_vgroups,
2356                       const bool use_topology,
2357                       int *r_totmirr,
2358                       int *r_totfail)
2359 {
2360
2361 #define VGROUP_MIRR_OP \
2362   dvert_mirror_op(dvert, \
2363                   dvert_mirr, \
2364                   sel, \
2365                   sel_mirr, \
2366                   flip_map, \
2367                   flip_map_len, \
2368                   mirror_weights, \
2369                   flip_vgroups, \
2370                   all_vgroups, \
2371                   def_nr)
2372
2373   BMVert *eve, *eve_mirr;
2374   MDeformVert *dvert, *dvert_mirr;
2375   char sel, sel_mirr;
2376   int *flip_map = NULL, flip_map_len;
2377   const int def_nr = ob->actdef - 1;
2378   int totmirr = 0, totfail = 0;
2379
2380   *r_totmirr = *r_totfail = 0;
2381
2382   if ((mirror_weights == false && flip_vgroups == false) ||
2383       (BLI_findlink(&ob->defbase, def_nr) == NULL)) {
2384     return;
2385   }
2386
2387   if (flip_vgroups) {
2388     flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) :
2389                              BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
2390
2391     BLI_assert(flip_map != NULL);
2392
2393     if (flip_map == NULL) {
2394       /* something went wrong!, possibly no groups */
2395       return;
2396     }
2397   }
2398   else {
2399     flip_map = NULL;
2400     flip_map_len = 0;
2401   }
2402
2403   /* only the active group */
2404   if (ob->type == OB_MESH) {
2405     Mesh *me = ob->data;
2406     BMEditMesh *em = me->edit_mesh;
2407
2408     if (em) {
2409       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
2410       BMIter iter;
2411
2412       if (cd_dvert_offset == -1) {
2413         goto cleanup;
2414       }
2415
2416       EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology);
2417
2418       BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
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_TAG)) {
2423           if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
2424             if (eve_mirr != eve) {
2425               if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
2426                 sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
2427                 sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
2428
2429                 if ((sel || sel_mirr) && (eve != eve_mirr)) {
2430                   dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
2431                   dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
2432
2433                   VGROUP_MIRR_OP;
2434                   totmirr++;
2435                 }
2436
2437                 /* don't use these again */
2438                 BM_elem_flag_enable(eve, BM_ELEM_TAG);
2439                 BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
2440               }
2441             }
2442           }
2443           else {
2444             totfail++;
2445           }
2446         }
2447       }
2448       EDBM_verts_mirror_cache_end(em);
2449     }
2450     else {
2451       /* object mode / weight paint */
2452       MVert *mv, *mv_mirr;
2453       int vidx, vidx_mirr;
2454       const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
2455
2456       if (me->dvert == NULL) {
2457         goto cleanup;
2458       }
2459
2460       if (!use_vert_sel) {
2461         sel = sel_mirr = true;
2462       }
2463
2464       /* tag verts we have used */
2465       for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
2466         mv->flag &= ~ME_VERT_TMP_TAG;
2467       }
2468
2469       for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
2470         if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
2471           if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
2472             if (vidx != vidx_mirr) {
2473               mv_mirr = &me->mvert[vidx_mirr];
2474               if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
2475
2476                 if (use_vert_sel) {
2477                   sel = mv->flag & SELECT;
2478                   sel_mirr = mv_mirr->flag & SELECT;
2479                 }
2480
2481                 if (sel || sel_mirr) {
2482                   dvert = &me->dvert[vidx];
2483                   dvert_mirr = &me->dvert[vidx_mirr];
2484
2485                   VGROUP_MIRR_OP;
2486                   totmirr++;
2487                 }
2488
2489                 mv->flag |= ME_VERT_TMP_TAG;
2490                 mv_mirr->flag |= ME_VERT_TMP_TAG;
2491               }
2492             }
2493           }
2494           else {
2495             totfail++;
2496           }
2497         }
2498       }
2499     }
2500   }
2501   else if (ob->type == OB_LATTICE) {
2502     Lattice *lt = vgroup_edit_lattice(ob);
2503     int i1, i2;
2504     int u, v, w;
2505     int pntsu_half;
2506     /* half but found up odd value */
2507
2508     if (lt->pntsu == 1 || lt->dvert == NULL) {
2509       goto cleanup;
2510     }
2511
2512     /* unlike editmesh we know that by only looping over the first half of
2513      * the 'u' indices it will cover all points except the middle which is
2514      * ok in this case */
2515     pntsu_half = lt->pntsu / 2;
2516
2517     for (w = 0; w < lt->pntsw; w++) {
2518       for (v = 0; v < lt->pntsv; v++) {
2519         for (u = 0; u < pntsu_half; u++) {
2520           int u_inv = (lt->pntsu - 1) - u;
2521           if (u != u_inv) {
2522             BPoint *bp, *bp_mirr;
2523
2524             i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
2525             i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
2526
2527             bp = &lt->def[i1];
2528             bp_mirr = &lt->def[i2];
2529
2530             sel = bp->f1 & SELECT;
2531             sel_mirr = bp_mirr->f1 & SELECT;
2532
2533             if (sel || sel_mirr) {
2534               dvert = &lt->dvert[i1];
2535               dvert_mirr = &lt->dvert[i2];
2536
2537               VGROUP_MIRR_OP;
2538               totmirr++;
2539             }
2540           }
2541         }
2542       }
2543     }
2544   }
2545
2546   /* disabled, confusing when you have an active pose bone */
2547 #if 0
2548   /* flip active group index */
2549   if (flip_vgroups && flip_map[def_nr] >= 0) {
2550     ob->actdef = flip_map[def_nr] + 1;
2551   }
2552 #endif
2553
2554 cleanup:
2555   *r_totmirr = totmirr;
2556   *r_totfail = totfail;
2557
2558   if (flip_map) {
2559     MEM_freeN(flip_map);
2560   }
2561
2562 #undef VGROUP_MIRR_OP
2563 }
2564
2565 static void vgroup_delete_active(Object *ob)
2566 {
2567   bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
2568   if (!dg) {
2569     return;
2570   }
2571
2572   BKE_object_defgroup_remove(ob, dg);
2573 }
2574
2575 /* only in editmode */
2576 static void vgroup_assign_verts(Object *ob, const float weight)
2577 {
2578   const int def_nr = ob->actdef - 1;
2579
2580   if (!BLI_findlink(&ob->defbase, def_nr)) {
2581     return;
2582   }
2583
2584   if (ob->type == OB_MESH) {
2585     Mesh *me = ob->data;
2586
2587     if (me->edit_mesh) {
2588       BMEditMesh *em = me->edit_mesh;
2589       int cd_dvert_offset;
2590
2591       BMIter iter;
2592       BMVert *eve;
2593
2594       if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) {
2595         BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
2596       }
2597
2598       cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
2599
2600       /* Go through the list of editverts and assign them */
2601       BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2602         if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2603           MDeformVert *dv;
2604           MDeformWeight *dw;
2605           dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */
2606           dw = BKE_defvert_ensure_index(dv, def_nr);
2607           if (dw) {
2608             dw->weight = weight;
2609           }
2610         }
2611       }
2612     }
2613     else {
2614       if (!me->dvert) {
2615         BKE_object_defgroup_data_create(&me->id);
2616       }
2617
2618       MVert *mv = me->mvert;
2619       MDeformVert *dv = me->dvert;
2620
2621       for (int i = 0; i < me->totvert; i++, mv++, dv++) {
2622         if (mv->flag & SELECT) {
2623           MDeformWeight *dw;
2624           dw = BKE_defvert_ensure_index(dv, def_nr);
2625           if (dw) {
2626             dw->weight = weight;
2627           }
2628         }
2629       }
2630     }
2631   }
2632   else if (ob->type == OB_LATTICE) {
2633     Lattice *lt = vgroup_edit_lattice(ob);
2634     MDeformVert *dv;
2635     BPoint *bp;
2636     int a, tot;
2637
2638     if (lt->dvert == NULL) {
2639       BKE_object_defgroup_data_create(&lt->id);
2640     }
2641
2642     dv = lt->dvert;
2643
2644     tot = lt->pntsu * lt->pntsv * lt->pntsw;
2645     for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
2646       if (bp->f1 & SELECT) {
2647         MDeformWeight *dw;
2648
2649         dw = BKE_defvert_ensure_index(dv, def_nr);
2650         if (dw) {
2651           dw->weight = weight;
2652         }
2653       }
2654     }
2655   }
2656 }
2657
2658 /** \} */
2659
2660 /* -------------------------------------------------------------------- */
2661 /** \name Shared Operator Poll Functions
2662  * \{ */
2663
2664 static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob)
2665 {
2666   if (!ED_operator_object_active_local_editable_ex(C, ob)) {
2667     return false;
2668   }
2669   const ID *data = ob->data;
2670   return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
2671           /* Data checks. */
2672           (data != NULL) && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
2673 }
2674
2675 static bool vertex_group_supported_poll(bContext *C)
2676 {
2677   Object *ob = ED_object_context(C);
2678   return vertex_group_supported_poll_ex(C, ob);
2679 }
2680
2681 static bool vertex_group_poll(bContext *C)
2682 {
2683   Object *ob = ED_object_context(C);
2684
2685   return (vertex_group_supported_poll(C) && ob->defbase.first);
2686 }
2687
2688 static bool vertex_group_mesh_poll(bContext *C)
2689 {
2690   Object *ob = ED_object_context(C);
2691
2692   return (vertex_group_poll(C) && ob->type == OB_MESH);
2693 }
2694
2695 static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C)
2696 {
2697   Object *ob = ED_object_context(C);
2698
2699   return (vertex_group_supported_poll(C) && ob->type == OB_MESH);
2700 }
2701
2702 static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C)
2703 {
2704   Object *ob = ED_object_context(C);
2705
2706   if (!vertex_group_supported_poll(C)) {
2707     return false;
2708   }
2709
2710   return BKE_object_is_in_editmode_vgroup(ob);
2711 }
2712
2713 /* editmode _or_ weight paint vertex sel */
2714 static bool vertex_group_vert_poll_ex(bContext *C,
2715                                       const bool needs_select,
2716                                       const short ob_type_flag)
2717 {
2718   Object *ob = ED_object_context(C);
2719
2720   if (!vertex_group_supported_poll(C)) {
2721     return false;
2722   }
2723
2724   if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
2725     return false;
2726   }
2727
2728   if (BKE_object_is_in_editmode_vgroup(ob)) {
2729     return true;
2730   }
2731   if (ob->mode & OB_MODE_WEIGHT_PAINT) {
2732     if (needs_select) {
2733       if (BKE_object_is_in_wpaint_select_vert(ob)) {
2734         return true;
2735       }
2736       CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
2737       return false;
2738     }
2739     return true;
2740   }
2741   return false;
2742 }
2743
2744 #if 0
2745 static bool vertex_group_vert_poll(bContext *C)
2746 {
2747   return vertex_group_vert_poll_ex(C, false, 0);
2748 }
2749 #endif
2750
2751 static bool vertex_group_mesh_vert_poll(bContext *C)
2752 {
2753   return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
2754 }
2755
2756 static bool vertex_group_vert_select_poll(bContext *C)
2757 {
2758   return vertex_group_vert_poll_ex(C, true, 0);
2759 }
2760
2761 #if 0
2762 static bool vertex_group_mesh_vert_select_poll(bContext *C)
2763 {
2764   return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
2765 }
2766 #endif
2767
2768 /* editmode _or_ weight paint vertex sel and active group unlocked */
2769 static bool vertex_group_vert_select_unlocked_poll(bContext *C)
2770 {
2771   Object *ob = ED_object_context(C);
2772
2773   if (!vertex_group_supported_poll(C)) {
2774     return false;
2775   }
2776
2777   if (!(BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) {
2778     return false;
2779   }
2780
2781   if (ob->actdef != 0) {
2782     bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
2783     if (dg) {
2784       return !(dg->flag & DG_LOCK_WEIGHT);
2785     }
2786   }
2787   return true;
2788 }
2789
2790 static bool vertex_group_vert_select_mesh_poll(bContext *C)
2791 {
2792   Object *ob = ED_object_context(C);
2793
2794   if (!vertex_group_supported_poll(C)) {
2795     return false;
2796   }
2797
2798   /* only difference to #vertex_group_vert_select_poll */
2799   if (ob->type != OB_MESH) {
2800     return false;
2801   }
2802
2803   return (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob));
2804 }
2805
2806 /** \} */
2807
2808 /* -------------------------------------------------------------------- */
2809 /** \name Vertex Group Add Operator
2810  * \{ */
2811
2812 static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
2813 {
2814   Object *ob = ED_object_context(C);
2815
2816   BKE_object_defgroup_add(ob);
2817   DEG_relations_tag_update(CTX_data_main(C));
2818   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2819   WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
2820   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
2821
2822   return OPERATOR_FINISHED;
2823 }
2824
2825 void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
2826 {
2827   /* identifiers */
2828   ot->name = "Add Vertex Group";
2829   ot->idname = "OBJECT_OT_vertex_group_add";
2830   ot->description = "Add a new vertex group to the active object";
2831
2832   /* api callbacks */
2833   ot->poll = vertex_group_supported_poll;
2834   ot->exec = vertex_group_add_exec;
2835
2836   /* flags */
2837   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2838 }
2839
2840 /** \} */
2841
2842 /* -------------------------------------------------------------------- */
2843 /** \name Vertex Group Remove Operator
2844  * \{ */
2845
2846 static int vertex_group_remove_exec(bContext *C, wmOperator *op)
2847 {
2848   Object *ob = ED_object_context(C);
2849
2850   if (RNA_boolean_get(op->ptr, "all")) {
2851     BKE_object_defgroup_remove_all(ob);
2852   }
2853   else if (RNA_boolean_get(op->ptr, "all_unlocked")) {
2854     BKE_object_defgroup_remove_all_ex(ob, true);
2855   }
2856   else {
2857     vgroup_delete_active(ob);
2858   }
2859
2860   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2861   DEG_relations_tag_update(CTX_data_main(C));
2862   WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
2863   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
2864
2865   return OPERATOR_FINISHED;
2866 }
2867
2868 void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
2869 {
2870   /* identifiers */
2871   ot->name = "Remove Vertex Group";
2872   ot->idname = "OBJECT_OT_vertex_group_remove";
2873   ot->description = "Delete the active or all vertex groups from the active object";
2874
2875   /* api callbacks */
2876   ot->poll = vertex_group_poll;
2877   ot->exec = vertex_group_remove_exec;
2878
2879   /* flags */
2880   /* redo operator will fail in this case because vertex groups aren't stored
2881    * in local edit mode stack and toggling "all" property will lead to
2882    * all groups deleted without way to restore them (see T29527, sergey) */
2883   ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
2884
2885   /* properties */
2886   PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
2887   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2888   prop = RNA_def_boolean(
2889       ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
2890   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2891 }
2892
2893 /** \} */
2894
2895 /* -------------------------------------------------------------------- */
2896 /** \name Vertex Group Assign Operator
2897  * \{ */
2898
2899 static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
2900 {
2901   ToolSettings *ts = CTX_data_tool_settings(C);
2902   Object *ob = ED_object_context(C);
2903
2904   vgroup_assign_verts(ob, ts->vgroup_weight);
2905   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
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_assign(wmOperatorType *ot)
2912 {
2913   /* identifiers */
2914   ot->name = "Assign to Vertex Group";
2915   ot->idname = "OBJECT_OT_vertex_group_assign";
2916   ot->description = "Assign the selected vertices to the active vertex group";
2917
2918   /* api callbacks */
2919   ot->poll = vertex_group_vert_select_unlocked_poll;
2920   ot->exec = vertex_group_assign_exec;
2921
2922   /* flags */
2923   /* redo operator will fail in this case because vertex group assignment
2924    * isn't stored in local edit mode stack and toggling "new" property will
2925    * lead to creating plenty of new vertex groups (see T29527, sergey) */
2926   ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
2927 }
2928
2929 /** \} */
2930
2931 /* -------------------------------------------------------------------- */
2932 /** \name Vertex Group Assign New Operator
2933  * \{ */
2934
2935 /* NOTE: just a wrapper around vertex_group_assign_exec(), except we add these to a new group */
2936 static int vertex_group_assign_new_exec(bContext *C, wmOperator *op)
2937 {
2938   /* create new group... */
2939   Object *ob = ED_object_context(C);
2940   BKE_object_defgroup_add(ob);
2941
2942   /* assign selection to new group */
2943   return vertex_group_assign_exec(C, op);
2944 }
2945
2946 void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot)
2947 {
2948   /* identifiers */
2949   ot->name = "Assign to New Group";
2950   ot->idname = "OBJECT_OT_vertex_group_assign_new";
2951   ot->description = "Assign the selected vertices to a new vertex group";
2952
2953   /* api callbacks */
2954   ot->poll = vertex_group_vert_select_poll;
2955   ot->exec = vertex_group_assign_new_exec;
2956
2957   /* flags */
2958   /* redo operator will fail in this case because vertex group assignment
2959    * isn't stored in local edit mode stack and toggling "new" property will
2960    * lead to creating plenty of new vertex groups (see T29527, sergey) */
2961   ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
2962 }
2963
2964 /** \} */
2965
2966 /* -------------------------------------------------------------------- */
2967 /** \name Vertex Group Remove From Operator
2968  * \{ */
2969
2970 static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
2971 {
2972   const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
2973   const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
2974
2975   Object *ob = ED_object_context(C);
2976
2977   if (use_all_groups) {
2978     if (BKE_object_defgroup_clear_all(ob, true) == false) {
2979       return OPERATOR_CANCELLED;
2980     }
2981   }
2982   else {
2983     bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
2984
2985     if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
2986       return OPERATOR_CANCELLED;
2987     }
2988   }
2989
2990   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
2991   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
2992
2993   return OPERATOR_FINISHED;
2994 }
2995
2996 void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
2997 {
2998   PropertyRNA *prop;
2999   /* identifiers */
3000   ot->name = "Remove from Vertex Group";
3001   ot->idname = "OBJECT_OT_vertex_group_remove_from";
3002   ot->description = "Remove the selected vertices from active or all vertex group(s)";
3003
3004   /* api callbacks */
3005   ot->poll = vertex_group_vert_select_unlocked_poll;
3006   ot->exec = vertex_group_remove_from_exec;
3007
3008   /* flags */
3009   /* redo operator will fail in this case because vertex groups assignment
3010    * isn't stored in local edit mode stack and toggling "all" property will lead to
3011    * removing vertices from all groups (see T29527, sergey) */
3012   ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
3013
3014   /* properties */
3015   prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
3016   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
3017   prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Vertices", "Clear the active group");
3018   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
3019 }
3020
3021 /** \} */
3022
3023 /* -------------------------------------------------------------------- */
3024 /** \name Vertex Group Select Operator
3025  * \{ */
3026
3027 static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
3028 {
3029   Object *ob = ED_object_context(C);
3030
3031   if (!ob || ID_IS_LINKED(ob)) {
3032     return OPERATOR_CANCELLED;
3033   }
3034
3035   vgroup_select_verts(ob, 1);
3036   DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
3037   WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
3038
3039   return OPERATOR_FINISHED;
3040 }
3041
3042 void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
3043 {
3044   /* identifiers */
3045   ot->name = "Select Vertex Group";
3046   ot->idname = "OBJECT_OT_vertex_group_select";
3047   ot->description = "Select all the vertices assigned to the active vertex group";
3048
3049   /* api callbacks */
3050   ot->poll = vertex_group_vert_select_poll;
3051   ot->exec = vertex_group_select_exec;
3052
3053   /* flags */
3054   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3055 }
3056
3057 /** \} */
3058
3059 /* -------------------------------------------------------------------- */
3060 /** \name Vertex Group Deselect Operator
3061  * \{ */
3062
3063 static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
3064 {
3065   Object *ob = ED_object_context(C);
3066
3067   vgroup_select_verts(ob, 0);
3068   DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
3069   WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
3070
3071   return OPERATOR_FINISHED;
3072 }
3073
3074 void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
3075 {
3076   /* identifiers */
3077   ot->name = "Deselect Vertex Group";
3078   ot->idname = "OBJECT_OT_vertex_group_deselect";
3079   ot->description = "Deselect all selected vertices assigned to the active vertex group";
3080
3081   /* api callbacks */
3082   ot->poll = vertex_group_vert_select_poll;
3083   ot->exec = vertex_group_deselect_exec;
3084
3085   /* flags */
3086   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3087 }
3088
3089 /** \} */
3090
3091 /* -------------------------------------------------------------------- */
3092 /** \name Vertex Group Copy Operator
3093  * \{ */
3094
3095 static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
3096 {
3097   Object *ob = ED_object_context(C);
3098
3099   vgroup_duplicate(ob);
3100   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3101   DEG_relations_tag_update(CTX_data_main(C));
3102   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3103   WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
3104
3105   return OPERATOR_FINISHED;
3106 }
3107
3108 void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
3109 {
3110   /* identifiers */
3111   ot->name = "Copy Vertex Group";
3112   ot->idname = "OBJECT_OT_vertex_group_copy";
3113   ot->description = "Make a copy of the active vertex group";
3114
3115   /* api callbacks */
3116   ot->poll = vertex_group_poll;
3117   ot->exec = vertex_group_copy_exec;
3118
3119   /* flags */
3120   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3121 }
3122
3123 /** \} */
3124
3125 /* -------------------------------------------------------------------- */
3126 /** \name Vertex Group Levels Operator
3127  * \{ */
3128
3129 static int vertex_group_levels_exec(bContext *C, wmOperator *op)
3130 {
3131   Object *ob = ED_object_context(C);
3132
3133   float offset = RNA_float_get(op->ptr, "offset");
3134   float gain = RNA_float_get(op->ptr, "gain");
3135   eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3136
3137   int subset_count, vgroup_tot;
3138
3139   const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3140       ob, subset_type, &vgroup_tot, &subset_count);
3141   vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
3142   MEM_freeN((void *)vgroup_validmap);
3143
3144   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3145   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3146   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3147
3148   return OPERATOR_FINISHED;
3149 }
3150
3151 void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
3152 {
3153   /* identifiers */
3154   ot->name = "Vertex Group Levels";
3155   ot->idname = "OBJECT_OT_vertex_group_levels";
3156   ot->description =
3157       "Add some offset and multiply with some gain the weights of the active vertex group";
3158
3159   /* api callbacks */
3160   ot->poll = vertex_group_poll;
3161   ot->exec = vertex_group_levels_exec;
3162
3163   /* flags */
3164   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3165
3166   vgroup_operator_subset_select_props(ot, true);
3167   RNA_def_float(
3168       ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
3169   RNA_def_float(
3170       ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
3171 }
3172
3173 /** \} */
3174
3175 /* -------------------------------------------------------------------- */
3176 /** \name Vertex Group Normalize Operator
3177  * \{ */
3178
3179 static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
3180 {
3181   Object *ob = ED_object_context(C);
3182   bool changed;
3183
3184   changed = vgroup_normalize(ob);
3185
3186   if (changed) {
3187     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3188     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3189     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3190
3191     return OPERATOR_FINISHED;
3192   }
3193   return OPERATOR_CANCELLED;
3194 }
3195
3196 void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
3197 {
3198   /* identifiers */
3199   ot->name = "Normalize Vertex Group";
3200   ot->idname = "OBJECT_OT_vertex_group_normalize";
3201   ot->description =
3202       "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
3203
3204   /* api callbacks */
3205   ot->poll = vertex_group_poll;
3206   ot->exec = vertex_group_normalize_exec;
3207
3208   /* flags */
3209   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3210 }
3211
3212 /** \} */
3213
3214 /* -------------------------------------------------------------------- */
3215 /** \name Vertex Group Normalize All Operator
3216  * \{ */
3217
3218 static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
3219 {
3220   Object *ob = ED_object_context(C);
3221   bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
3222   eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3223   bool changed;
3224   int subset_count, vgroup_tot;
3225   const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3226       ob, subset_type, &vgroup_tot, &subset_count);
3227
3228   changed = vgroup_normalize_all(
3229       ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
3230   MEM_freeN((void *)vgroup_validmap);
3231
3232   if (changed) {
3233     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3234     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3235     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3236
3237     return OPERATOR_FINISHED;
3238   }
3239
3240   /* allow to adjust settings */
3241   return OPERATOR_FINISHED;
3242 }
3243
3244 void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
3245 {
3246   /* identifiers */
3247   ot->name = "Normalize All Vertex Groups";
3248   ot->idname = "OBJECT_OT_vertex_group_normalize_all";
3249   ot->description =
3250       "Normalize all weights of all vertex groups, "
3251       "so that for each vertex, the sum of all weights is 1.0";
3252
3253   /* api callbacks */
3254   ot->poll = vertex_group_poll;
3255   ot->exec = vertex_group_normalize_all_exec;
3256
3257   /* flags */
3258   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3259
3260   vgroup_operator_subset_select_props(ot, false);
3261   RNA_def_boolean(ot->srna,
3262                   "lock_active",
3263                   true,
3264                   "Lock Active",
3265                   "Keep the values of the active group while normalizing others");
3266 }
3267
3268 /** \} */
3269
3270 /* -------------------------------------------------------------------- */
3271 /** \name Vertex Group Fix Position Operator
3272  * \{ */
3273
3274 static int vertex_group_fix_exec(bContext *C, wmOperator *op)
3275 {
3276   Object *ob = CTX_data_active_object(C);
3277   Scene *scene = CTX_data_scene(C);
3278
3279   float distToBe = RNA_float_get(op->ptr, "dist");
3280   float strength = RNA_float_get(op->ptr, "strength");
3281   float cp = RNA_float_get(op->ptr, "accuracy");
3282   ModifierData *md = ob->modifiers.first;
3283
3284   while (md) {
3285     if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
3286       break;
3287     }
3288     md = md->next;
3289   }
3290
3291   if (md && md->type == eModifierType_Mirror) {
3292     BKE_report(op->reports,
3293                RPT_ERROR_INVALID_CONTEXT,
3294                "This operator does not support an active mirror modifier");
3295     return OPERATOR_CANCELLED;
3296   }
3297   vgroup_fix(C, scene, ob, distToBe, strength, cp);
3298
3299   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3300   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3301   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3302
3303   return OPERATOR_FINISHED;
3304 }
3305
3306 void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
3307 {
3308   /* identifiers */
3309   ot->name = "Fix Vertex Group Deform";
3310   ot->idname = "OBJECT_OT_vertex_group_fix";
3311   ot->description =
3312       "Modify the position of selected vertices by changing only their respective "
3313       "groups' weights (this tool may be slow for many vertices)";
3314
3315   /* api callbacks */
3316   ot->poll = vertex_group_mesh_poll;
3317   ot->exec = vertex_group_fix_exec;
3318
3319   /* flags */
3320   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3321   RNA_def_float(ot->srna,
3322                 "dist",
3323                 0.0f,
3324                 -FLT_MAX,
3325                 FLT_MAX,
3326                 "Distance",
3327                 "The distance to move to",
3328                 -10.0f,
3329                 10.0f);
3330   RNA_def_float(ot->srna,
3331                 "strength",
3332                 1.f,
3333                 -2.0f,
3334                 FLT_MAX,
3335                 "Strength",
3336                 "The distance moved can be changed by this multiplier",
3337                 -2.0f,
3338                 2.0f);
3339   RNA_def_float(
3340       ot->srna,
3341       "accuracy",
3342       1.0f,
3343       0.05f,
3344       FLT_MAX,
3345       "Change Sensitivity",
3346       "Change the amount weights are altered with each iteration: lower values are slower",
3347       0.05f,
3348       1.f);
3349 }
3350
3351 /** \} */
3352
3353 /* -------------------------------------------------------------------- */
3354 /** \name Vertex Group Lock Operator
3355  * \{ */
3356
3357 static int vertex_group_lock_exec(bContext *C, wmOperator *op)
3358 {
3359   Object *ob = CTX_data_active_object(C);
3360
3361   int action = RNA_enum_get(op->ptr, "action");
3362   int mask = RNA_enum_get(op->ptr, "mask");
3363
3364   vgroup_lock_all(ob, action, mask);
3365
3366   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3367
3368   return OPERATOR_FINISHED;
3369 }
3370
3371 static char *vertex_group_lock_description(struct bContext *UNUSED(C),
3372                                            struct wmOperatorType *UNUSED(op),
3373                                            struct PointerRNA *params)
3374 {
3375   int action = RNA_enum_get(params, "action");
3376   int mask = RNA_enum_get(params, "mask");
3377
3378   const char *action_str, *target_str;
3379
3380   switch (action) {
3381     case VGROUP_LOCK:
3382       action_str = "Lock";
3383       break;
3384     case VGROUP_UNLOCK:
3385       action_str = "Unlock";
3386       break;
3387     case VGROUP_TOGGLE:
3388       action_str = "Toggle locks of";
3389       break;
3390     case VGROUP_INVERT:
3391       action_str = "Invert locks of";
3392       break;
3393     default:
3394       return NULL;
3395   }
3396
3397   switch (mask) {
3398     case VGROUP_MASK_ALL:
3399       target_str = "all";
3400       break;
3401     case VGROUP_MASK_SELECTED:
3402       target_str = "selected";
3403       break;
3404     case VGROUP_MASK_UNSELECTED:
3405       target_str = "unselected";
3406       break;
3407     case VGROUP_MASK_INVERT_UNSELECTED:
3408       switch (action) {
3409         case VGROUP_INVERT:
3410           target_str = "selected";
3411           break;
3412         case VGROUP_LOCK:
3413           target_str = "selected and unlock unselected";
3414           break;
3415         case VGROUP_UNLOCK:
3416           target_str = "selected and lock unselected";
3417           break;
3418         default:
3419           target_str = "all and invert unselected";
3420       }
3421       break;
3422     default:
3423       return NULL;
3424   }
3425
3426   return BLI_sprintfN("%s %s vertex groups of the active object", action_str, target_str);
3427 }
3428
3429 void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
3430 {
3431   /* identifiers */
3432   ot->name = "Change the Lock On Vertex Groups";
3433   ot->idname = "OBJECT_OT_vertex_group_lock";
3434   ot->description = "Change the lock state of all or some vertex groups of active object";
3435
3436   /* api callbacks */
3437   ot->poll = vertex_group_poll;
3438   ot->exec = vertex_group_lock_exec;
3439   ot->get_description = vertex_group_lock_description;
3440
3441   /* flags */
3442   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3443
3444   RNA_def_enum(ot->srna,
3445                "action",
3446                vgroup_lock_actions,
3447                VGROUP_TOGGLE,
3448                "Action",
3449                "Lock action to execute on vertex groups");
3450
3451   RNA_def_enum(ot->srna,
3452                "mask",
3453                vgroup_lock_mask,
3454                VGROUP_MASK_ALL,
3455                "Mask",
3456                "Apply the action based on vertex group selection");
3457 }
3458
3459 /** \} */
3460
3461 /* -------------------------------------------------------------------- */
3462 /** \name Vertex Group Invert Operator
3463  * \{ */
3464
3465 static int vertex_group_invert_exec(bContext *C, wmOperator *op)
3466 {
3467   Object *ob = ED_object_context(C);
3468   bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
3469   bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
3470
3471   eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3472
3473   int subset_count, vgroup_tot;
3474
3475   const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3476       ob, subset_type, &vgroup_tot, &subset_count);
3477   vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
3478   MEM_freeN((void *)vgroup_validmap);
3479
3480   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3481   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3482   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3483
3484   return OPERATOR_FINISHED;
3485 }
3486
3487 void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
3488 {
3489   /* identifiers */
3490   ot->name = "Invert Vertex Group";
3491   ot->idname = "OBJECT_OT_vertex_group_invert";
3492   ot->description = "Invert active vertex group's weights";
3493
3494   /* api callbacks */
3495   ot->poll = vertex_group_poll;
3496   ot->exec = vertex_group_invert_exec;
3497
3498   /* flags */
3499   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3500
3501   vgroup_operator_subset_select_props(ot, true);
3502   RNA_def_boolean(ot->srna,
3503                   "auto_assign",
3504                   true,
3505                   "Add Weights",
3506                   "Add vertices from groups that have zero weight before inverting");
3507   RNA_def_boolean(ot->srna,
3508                   "auto_remove",
3509                   true,
3510                   "Remove Weights",
3511                   "Remove vertices from groups that have zero weight after inverting");
3512 }
3513
3514 /** \} */
3515
3516 /* -------------------------------------------------------------------- */
3517 /** \name Vertex Group Invert Operator
3518  * \{ */
3519
3520 static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
3521 {
3522   const float fac = RNA_float_get(op->ptr, "factor");
3523   const int repeat = RNA_int_get(op->ptr, "repeat");
3524   const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3525   const float fac_expand = RNA_float_get(op->ptr, "expand");
3526
3527   uint objects_len;
3528   Object **objects = object_array_for_wpaint(C, &objects_len);
3529
3530   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3531     Object *ob = objects[ob_index];
3532
3533     int subset_count, vgroup_tot;
3534
3535     const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3536         ob, subset_type, &vgroup_tot, &subset_count);
3537
3538     vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
3539     MEM_freeN((void *)vgroup_validmap);
3540
3541     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3542     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3543     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3544   }
3545   MEM_freeN(objects);
3546
3547   return OPERATOR_FINISHED;
3548 }
3549
3550 void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
3551 {
3552   /* identifiers */
3553   ot->name = "Smooth Vertex Weights";
3554   ot->idname = "OBJECT_OT_vertex_group_smooth";
3555   ot->description = "Smooth weights for selected vertices";
3556
3557   /* api callbacks */
3558   ot->poll = vertex_group_mesh_vert_poll;
3559   ot->exec = vertex_group_smooth_exec;
3560
3561   /* flags */
3562   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3563
3564   vgroup_operator_subset_select_props(ot, true);
3565   RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
3566   RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
3567
3568   RNA_def_float(ot->srna,
3569                 "expand",
3570                 0.0f,
3571                 -1.0f,
3572                 1.0,
3573                 "Expand/Contract",
3574                 "Expand/contract weights",
3575                 -1.0f,
3576                 1.0f);
3577 }
3578
3579 /** \} */
3580
3581 /* -------------------------------------------------------------------- */
3582 /** \name Vertex Group Clean Operator
3583  * \{ */
3584
3585 static int vertex_group_clean_exec(bContext *C, wmOperator *op)
3586 {
3587   const float limit = RNA_float_get(op->ptr, "limit");
3588   const bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
3589   const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3590
3591   uint objects_len;
3592   Object **objects = object_array_for_wpaint(C, &objects_len);
3593
3594   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3595     Object *ob = objects[ob_index];
3596
3597     int subset_count, vgroup_tot;
3598
3599     const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3600         ob, subset_type, &vgroup_tot, &subset_count);
3601
3602     vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
3603     MEM_freeN((void *)vgroup_validmap);
3604
3605     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3606     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3607     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3608   }
3609   MEM_freeN(objects);
3610
3611   return OPERATOR_FINISHED;
3612 }
3613
3614 void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
3615 {
3616   /* identifiers */
3617   ot->name = "Clean Vertex Group Weights";
3618   ot->idname = "OBJECT_OT_vertex_group_clean";
3619   ot->description = "Remove vertex group assignments which are not required";
3620
3621   /* api callbacks */
3622   ot->poll = vertex_group_poll;
3623   ot->exec = vertex_group_clean_exec;
3624
3625   /* flags */
3626   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3627
3628   vgroup_operator_subset_select_props(ot, true);
3629   RNA_def_float(ot->srna,
3630                 "limit",
3631                 0.0f,
3632                 0.0f,
3633                 1.0,
3634                 "Limit",
3635                 "Remove vertices which weight is below or equal to this limit",
3636                 0.0f,
3637                 0.99f);
3638   RNA_def_boolean(ot->srna,
3639                   "keep_single",
3640                   false,
3641                   "Keep Single",
3642                   "Keep verts assigned to at least one group when cleaning");
3643 }
3644
3645 /** \} */
3646
3647 /* -------------------------------------------------------------------- */
3648 /** \name Vertex Group Quantize Operator
3649  * \{ */
3650
3651 static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
3652 {
3653   Object *ob = ED_object_context(C);
3654
3655   const int steps = RNA_int_get(op->ptr, "steps");
3656   eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3657
3658   int subset_count, vgroup_tot;
3659
3660   const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3661       ob, subset_type, &vgroup_tot, &subset_count);
3662   vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
3663   MEM_freeN((void *)vgroup_validmap);
3664
3665   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3666   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3667   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3668
3669   return OPERATOR_FINISHED;
3670 }
3671
3672 void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot)
3673 {
3674   /* identifiers */
3675   ot->name = "Quantize Vertex Weights";
3676   ot->idname = "OBJECT_OT_vertex_group_quantize";
3677   ot->description = "Set weights to a fixed number of steps";
3678
3679   /* api callbacks */
3680   ot->poll = vertex_group_poll;
3681   ot->exec = vertex_group_quantize_exec;
3682
3683   /* flags */
3684   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3685
3686   vgroup_operator_subset_select_props(ot, true);
3687   RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
3688 }
3689
3690 /** \} */
3691
3692 /* -------------------------------------------------------------------- */
3693 /** \name Vertex Group Limit Total Operator
3694  * \{ */
3695
3696 static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
3697 {
3698   const int limit = RNA_int_get(op->ptr, "limit");
3699   const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3700   int remove_multi_count = 0;
3701
3702   uint objects_len;
3703   Object **objects = object_array_for_wpaint(C, &objects_len);
3704   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3705     Object *ob = objects[ob_index];
3706
3707     int subset_count, vgroup_tot;
3708     const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3709         ob, subset_type, &vgroup_tot, &subset_count);
3710     const int remove_count = vgroup_limit_total_subset(
3711         ob, vgroup_validmap, vgroup_tot, subset_count, limit);
3712     MEM_freeN((void *)vgroup_validmap);
3713
3714     if (remove_count != 0) {
3715       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3716       WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3717       WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3718     }
3719     remove_multi_count += remove_count;
3720   }
3721   MEM_freeN(objects);
3722
3723   if (remove_multi_count) {
3724     BKE_reportf(op->reports,
3725                 remove_multi_count ? RPT_INFO : RPT_WARNING,
3726                 "%d vertex weights limited",
3727                 remove_multi_count);
3728
3729     return OPERATOR_FINISHED;
3730   }
3731
3732   /* note, would normally return canceled, except we want the redo
3733    * UI to show up for users to change */
3734   return OPERATOR_FINISHED;
3735 }
3736
3737 void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot)
3738 {
3739   /* identifiers */
3740   ot->name = "Limit Number of Weights per Vertex";
3741   ot->idname = "OBJECT_OT_vertex_group_limit_total";
3742   ot->description =
3743       "Limit deform weights associated with a vertex to a specified number by removing lowest "
3744       "weights";
3745
3746   /* api callbacks */
3747   ot->poll = vertex_group_poll;
3748   ot->exec = vertex_group_limit_total_exec;
3749
3750   /* flags */
3751   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3752
3753   vgroup_operator_subset_select_props(ot, false);
3754   RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
3755 }
3756
3757 /** \} */
3758
3759 /* -------------------------------------------------------------------- */
3760 /** \name Vertex Group Mirror Operator
3761  * \{ */
3762
3763 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
3764 {
3765   Object *ob = ED_object_context(C);
3766   int totmirr = 0, totfail = 0;
3767
3768   ED_vgroup_mirror(ob,
3769                    RNA_boolean_get(op->ptr, "mirror_weights"),
3770                    RNA_boolean_get(op->ptr, "flip_group_names"),
3771                    RNA_boolean_get(op->ptr, "all_groups"),
3772                    RNA_boolean_get(op->ptr, "use_topology"),
3773                    &totmirr,
3774                    &totfail);
3775
3776   ED_mesh_report_mirror(op, totmirr, totfail);
3777
3778   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3779   DEG_relations_tag_update(CTX_data_main(C));
3780   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3781   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
3782
3783   return OPERATOR_FINISHED;
3784 }
3785
3786 void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
3787 {
3788   /* identifiers */
3789   ot->name = "Mirror Vertex Group";
3790   ot->idname = "OBJECT_OT_vertex_group_mirror";
3791   ot->description =
3792       "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
3793       "flipping when both sides are selected otherwise copy from unselected";
3794
3795   /* api callbacks */
3796   ot->poll = vertex_group_poll;
3797   ot->exec = vertex_group_mirror_exec;
3798
3799   /* flags */
3800   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3801
3802   /* properties */
3803   RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
3804   RNA_def_boolean(
3805       ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
3806   RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
3807   RNA_def_boolean(
3808       ot->srna,
3809       "use_topology",
3810       0,
3811       "Topology Mirror",
3812       "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
3813 }
3814
3815 /** \} */
3816
3817 /* -------------------------------------------------------------------- */
3818 /** \name Vertex Group Copy to Linked Operator
3819  * \{ */
3820
3821 static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
3822 {
3823   Scene *scene = CTX_data_scene(C);
3824   Object *ob_active = ED_object_context(C);
3825   int retval = OPERATOR_CANCELLED;
3826
3827   FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
3828     if (ob_iter->type == ob_active->type) {
3829       if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
3830         BLI_freelistN(&ob_iter->defbase);
3831         BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
3832         ob_iter->actdef = ob_active->actdef;
3833
3834         DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
3835         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
3836         WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
3837
3838         retval = OPERATOR_FINISHED;
3839       }
3840     }
3841   }
3842   FOREACH_SCENE_OBJECT_END;
3843
3844   return retval;
3845 }
3846
3847 void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
3848 {
3849   /* identifiers */
3850   ot->name = "Copy Vertex Groups to Linked";
3851   ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
3852   ot->description =
3853       "Replace vertex groups of all users of the same geometry data by vertex groups of active "
3854       "object";
3855
3856   /* api callbacks */
3857   ot->poll = vertex_group_poll;
3858   ot->exec = vertex_group_copy_to_linked_exec;
3859
3860   /* flags */
3861   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3862 }
3863
3864 /** \} */
3865
3866 /* -------------------------------------------------------------------- */
3867 /** \name Vertex Group Copy to Selected Operator
3868  * \{ */
3869
3870 static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
3871 {
3872   Object *obact = ED_object_context(C);
3873   int changed_tot = 0;
3874   int fail = 0;
3875
3876   CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
3877     if (obact != ob) {
3878       if (ED_vgroup_array_copy(ob, obact)) {
3879         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3880         DEG_relations_tag_update(CTX_data_main(C));
3881         WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
3882         changed_tot++;
3883       }
3884       else {
3885         fail++;
3886       }
3887     }
3888   }
3889   CTX_DATA_END;
3890
3891   if ((changed_tot == 0 && fail == 0) || fail) {
3892     BKE_reportf(op->reports,
3893                 RPT_ERROR,
3894                 "Copy vertex groups to selected: %d done, %d failed (object data must have "
3895                 "matching indices)",
3896                 changed_tot,
3897                 fail);
3898   }
3899
3900   return OPERATOR_FINISHED;
3901 }
3902
3903 void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
3904 {
3905   /* identifiers */
3906   ot->name = "Copy Vertex Group to Selected";
3907   ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
3908   ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
3909
3910   /* api callbacks */
3911   ot->poll = vertex_group_poll;
3912   ot->exec = vertex_group_copy_to_selected_exec;
3913
3914   /* flags */
3915   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3916 }
3917
3918 /** \} */
3919
3920 /* -------------------------------------------------------------------- */
3921 /** \name Vertex Group Set Active Operator
3922  * \{ */
3923
3924 static int set_active_group_exec(bContext *C, wmOperator *op)
3925 {
3926   Object *ob = ED_object_context(C);
3927   int nr = RNA_enum_get(op->ptr, "group");
3928
3929   BLI_assert(nr + 1 >= 0);
3930   ob->actdef = nr + 1;
3931
3932   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
3933   WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
3934
3935   return OPERATOR_FINISHED;
3936 }
3937
3938 static const EnumPropertyItem *vgroup_itemf(bContext *C,
3939                                             PointerRNA *UNUSED(ptr),
3940                                             PropertyRNA *UNUSED(prop),
3941                                             bool *r_free)
3942 {
3943   Object *ob = ED_object_context(C);
3944   EnumPropertyItem tmp = {0, "", 0, "", ""};
3945   EnumPropertyItem *item = NULL;
3946   bDeformGroup *def;
3947   int a, totitem = 0;
3948
3949   if (!ob) {
3950     return DummyRNA_NULL_items;
3951   }
3952
3953   for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
3954     tmp.value = a;
3955     tmp.icon = ICON_GROUP_VERTEX;
3956     tmp.identifier = def->name;
3957     tmp.name = def->name;
3958     RNA_enum_item_add(&item, &totitem, &tmp);
3959   }
3960
3961   RNA_enum_item_end(&item, &totitem);
3962   *r_free = true;
3963
3964   return item;
3965 }
3966
3967 void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
3968 {
3969   PropertyRNA *prop;
3970
3971   /* identifiers */
3972   ot->name = "Set Active Vertex Group";
3973   ot->idname = "OBJECT_OT_vertex_group_set_active";
3974   ot->description = "Set the active vertex group";
3975
3976   /* api callbacks */
3977   ot->poll = vertex_group_poll;
3978   ot->exec = set_active_group_exec;
3979   ot->invoke = WM_menu_invoke;
3980
3981   /* flags */
3982   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
3983
3984   /* properties */
3985   prop = RNA_def_enum(
3986       ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
3987   RNA_def_enum_funcs(prop, vgroup_itemf);
3988   RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
3989   ot->prop = prop;
3990 }
3991
3992 /** \} */
3993
3994 /* -------------------------------------------------------------------- */
3995 /** \name Vertex Group Sort Operator
3996  * \{ */
3997
3998 /* creates the name_array parameter for vgroup_do_remap, call this before fiddling
3999  * with the order of vgroups then call vgroup_do_remap after */
4000 static char *vgroup_init_remap(Object *ob)
4001 {
4002   bDeformGroup *def;
4003   int defbase_tot = BLI_listbase_count(&ob->defbase);
4004   char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
4005   char *name;
4006
4007   name = name_array;
4008   for (def = ob->defbase.first; def; def = def->next) {
4009     BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
4010     name += MAX_VGROUP_NAME;
4011   }
4012
4013   return name_array;
4014 }
4015
4016 static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
4017 {
4018   MDeformVert *dvert = NULL;
4019   bDeformGroup *def;
4020   int defbase_tot = BLI_listbase_count(&ob->defbase);
4021
4022   /* needs a dummy index at the start*/
4023   int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
4024   int *sort_map = sort_map_update + 1;
4025
4026   const char *name;
4027   int i;
4028
4029   name = name_array;
4030   for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
4031     sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
4032     name += MAX_VGROUP_NAME;
4033
4034     BLI_assert(sort_map[i] != -1);
4035   }
4036
4037   if (ob->mode == OB_MODE_EDIT) {
4038     if (ob->type == OB_MESH) {
4039       BMEditMesh *em = BKE_editmesh_from_object(ob);
4040       const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
4041
4042       if (cd_dvert_offset != -1) {
4043         BMIter iter;
4044         BMVert *eve;
4045
4046         BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
4047           dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
4048           if (dvert->totweight) {
4049             BKE_defvert_remap(dvert, sort_map, defbase_tot);
4050           }
4051         }
4052       }
4053     }
4054     else {
4055       BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
4056       MEM_freeN(sort_map_update);
4057       return OPERATOR_CANCELLED;
4058     }
4059   }
4060   else {
4061     int dvert_tot = 0;
4062
4063     BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
4064
4065     /*create as necessary*/
4066     if (dvert) {
4067       while (dvert_tot--) {
4068         if (dvert->totweight) {
4069           BKE_defvert_remap(dvert, sort_map, defbase_tot);
4070         }
4071         dvert++;
4072       }
4073     }
4074   }
4075
4076   /* update users */
4077   for (i = 0; i < defbase_tot; i++) {
4078     sort_map[i]++;
4079   }
4080
4081   sort_map_update[0] = 0;
4082   BKE_object_defgroup_remap_update_users(ob, sort_map_update);
4083
4084   BLI_assert(sort_map_update[ob->actdef] >= 0);
4085   ob->actdef = sort_map_update[ob->actdef];
4086
4087   MEM_freeN(sort_map_update);
4088
4089   return OPERATOR_FINISHED;
4090 }
4091
4092 static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
4093 {
4094   const bDeformGroup *def_a = def_a_ptr;
4095   const bDeformGroup *def_b = def_b_ptr;
4096
4097   return BLI_strcasecmp_natural(def_a->name, def_b->name);
4098 }
4099
4100 /**
4101  * Sorts the weight groups according to the bone hierarchy of the
4102  * associated armature (similar to how bones are ordered in the Outliner)
4103  */
4104 static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
4105 {
4106   if (bonebase == NULL) {
4107     Object *armobj = BKE_modifiers_is_deformed_by_armature(ob);
4108     if (armobj != NULL) {
4109       bArmature *armature = armobj->data;
4110       bonebase = &armature->bonebase;
4111     }
4112   }
4113
4114   if (bonebase != NULL) {
4115     Bone *bone;
4116     for (bone = bonebase->last; bone; bone = bone->prev) {
4117       bDeformGroup *dg = BKE_object_defgroup_find_name(ob, bone->name);
4118       vgroup_sort_bone_hierarchy(ob, &bone->childbase);
4119
4120       if (dg != NULL) {
4121         BLI_remlink(&ob->defbase, dg);
4122         BLI_addhead(&ob->defbase, dg);
4123       }
4124     }
4125   }
4126 }
4127
4128 enum {
4129   SORT_TYPE_NAME = 0,
4130   SORT_TYPE_BONEHIERARCHY = 1,
4131 };
4132
4133 static int vertex_group_sort_exec(bContext *C, wmOperator *op)
4134 {
4135   Object *ob = ED_object_context(C);
4136   char *name_array;
4137   int ret;
4138   int sort_type = RNA_enum_get(op->ptr, "sort_type");
4139
4140   /*init remapping*/
4141   name_array = vgroup_init_remap(ob);
4142
4143   /*sort vgroup names*/
4144   switch (sort_type) {
4145     case SORT_TYPE_NAME:
4146       BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
4147       break;
4148     case SORT_TYPE_BONEHIERARCHY:
4149       vgroup_sort_bone_hierarchy(ob, NULL);
4150       break;
4151   }
4152
4153   /*remap vgroup data to map to correct names*/
4154   ret = vgroup_do_remap(ob, name_array, op);
4155
4156   if (ret != OPERATOR_CANCELLED) {
4157     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
4158     WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
4159   }
4160
4161   if (name_array) {
4162     MEM_freeN(name_array);
4163   }
4164
4165   return ret;
4166 }
4167
4168 void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
4169 {
4170   static const EnumPropertyItem vgroup_sort_type[] = {
4171       {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
4172       {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
4173       {0, NULL, 0, NULL, NULL},
4174   };
4175
4176   ot->name = "Sort Vertex Groups";
4177   ot->idname = "OBJECT_OT_vertex_group_sort";
4178   ot->description = "Sort vertex groups";
4179
4180   /* api callbacks */
4181   ot->poll = vertex_group_poll;
4182   ot->exec = vertex_group_sort_exec;
4183
4184   /* flags */
4185   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4186
4187   RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
4188 }
4189
4190 /** \} */
4191
4192 /* -------------------------------------------------------------------- */
4193 /** \name Vertex Group Move Operator
4194  * \{ */
4195
4196 static int vgroup_move_exec(bContext *C, wmOperator *op)