Blender  V2.93
object_vgroup.c
Go to the documentation of this file.
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 
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 /* -------------------------------------------------------------------- */
87 {
88  bContext *C = user_data;
90  return true;
91  }
92  return false;
93 }
94 
95 static Object **object_array_for_wpaint(bContext *C, uint *r_objects_len)
96 {
98 }
99 
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 
113 {
114  Lattice *lt = ob->data;
115  BLI_assert(ob->type == OB_LATTICE);
116  return (lt->editlatt) ? lt->editlatt->latt : lt;
117 }
118 
121 /* -------------------------------------------------------------------- */
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 
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 
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 
273  MDeformVert **dvert_array,
274  const int dvert_tot,
275  const bool *vgroup_validmap,
276  const int vgroup_tot)
277 {
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) {
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 
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 
320 void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot)
321 {
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) {
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 
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) &&
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 */
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 
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 
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 
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. */
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 
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 
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 
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 
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) {
688  }
689  }
690  }
691  }
692  }
693 
694  MEM_freeN((void *)vgroup_validmap);
695 }
696 
699 /* -------------------------------------------------------------------- */
704  {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"},
706  "BONE_SELECT",
707  0,
708  "Selected Pose Bones",
709  "All Vertex Groups assigned to Selection"},
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 
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 */
732  }
733 
735  if (selection_mask & (1 << WT_VGROUP_ACTIVE)) {
737  }
738 
739  if (ob) {
741  if (selection_mask & (1 << WT_VGROUP_BONE_SELECT)) {
744  }
745  }
746 
748  if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM)) {
751  }
752  }
753  }
754 
755  if (selection_mask & (1 << WT_VGROUP_ALL)) {
757  }
758 
759  RNA_enum_item_end(&item, &totitem);
760  *r_free = true;
761 
762  return item;
763 }
764 
766  PointerRNA *ptr,
767  PropertyRNA *prop,
768  bool *r_free)
769 {
771 }
772 
774  PointerRNA *ptr,
775  PropertyRNA *prop,
776  bool *r_free)
777 {
779  C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
780 }
781 
783 {
784  PropertyRNA *prop;
785 
786  prop = RNA_def_enum(ot->srna,
787  "group_select_mode",
789  use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL,
790  "Subset",
791  "Define which subset of groups shall be used");
792 
793  if (use_active) {
795  }
796  else {
798  }
800  ot->prop = prop;
801 }
802 
805 /* -------------------------------------------------------------------- */
813 /* for Mesh in Object mode */
814 /* allows editmode for Lattice */
816  Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode)
817 {
818  /* Add the vert to the deform group with the specified number. */
819  MDeformVert *dvert = NULL;
820  int tot;
821 
822  /* Get the vert. */
823  BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
824 
825  if (dvert == NULL) {
826  return;
827  }
828 
829  /* Check that vertnum is valid before trying to get the relevant dvert. */
830  if ((vertnum < 0) || (vertnum >= tot)) {
831  return;
832  }
833 
834  MDeformVert *dv = &dvert[vertnum];
835  MDeformWeight *dw;
836 
837  /* Lets first check to see if this vert is already in the weight group - if so lets update it. */
838  dw = BKE_defvert_find_index(dv, def_nr);
839 
840  if (dw) {
841  switch (assignmode) {
842  case WEIGHT_REPLACE:
843  dw->weight = weight;
844  break;
845  case WEIGHT_ADD:
846  dw->weight += weight;
847  if (dw->weight >= 1.0f) {
848  dw->weight = 1.0f;
849  }
850  break;
851  case WEIGHT_SUBTRACT:
852  dw->weight -= weight;
853  /* If the weight is zero or less than remove the vert from the deform group. */
854  if (dw->weight <= 0.0f) {
855  BKE_defvert_remove_group(dv, dw);
856  }
857  break;
858  }
859  }
860  else {
861  /* If the vert wasn't in the deform group then we must take a different form of action. */
862 
863  switch (assignmode) {
864  case WEIGHT_SUBTRACT:
865  /* If we are subtracting then we don't need to do anything. */
866  return;
867 
868  case WEIGHT_REPLACE:
869  case WEIGHT_ADD:
870  /* If we are doing an additive assignment, then we need to create the deform weight. */
871 
872  /* We checked if the vertex was added before so no need to test again, simply add. */
873  BKE_defvert_add_index_notest(dv, def_nr, weight);
874  break;
875  }
876  }
877 }
878 
879 /* called while not in editmode */
880 void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
881 {
882  /* add the vert to the deform group with the
883  * specified assign mode
884  */
885  const int def_nr = BLI_findindex(&ob->defbase, dg);
886 
887  MDeformVert *dv = NULL;
888  int tot;
889 
890  /* get the deform group number, exit if
891  * it can't be found
892  */
893  if (def_nr != -1) {
894 
895  /* if there's no deform verts then create some,
896  */
897  if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL) {
899  }
900 
901  /* call another function to do the work
902  */
903  ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
904  }
905 }
906 
907 /* mesh object mode, lattice can be in editmode */
908 void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
909 {
910  /* This routine removes the vertex from the specified
911  * deform group.
912  */
913 
914  /* TODO(campbell): This is slow in a loop, better pass def_nr directly,
915  * but leave for later. */
916  const int def_nr = BLI_findindex(&ob->defbase, dg);
917 
918  if (def_nr != -1) {
919  MDeformVert *dvert = NULL;
920  int tot;
921 
922  /* get the deform vertices corresponding to the
923  * vertnum
924  */
925  BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
926 
927  if (dvert) {
928  MDeformVert *dv = &dvert[vertnum];
929  MDeformWeight *dw;
930 
931  dw = BKE_defvert_find_index(dv, def_nr);
932  BKE_defvert_remove_group(dv, dw); /* dw can be NULL */
933  }
934  }
935 }
936 
937 static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
938 {
939  MDeformVert *dv = NULL;
940 
941  /* get the deform vertices corresponding to the vertnum */
942  if (ob->type == OB_MESH) {
943  Mesh *me = ob->data;
944 
945  if (me->edit_mesh) {
946  BMEditMesh *em = me->edit_mesh;
947  const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
948  /* warning, this lookup is _not_ fast */
949 
950  if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
951  BMVert *eve;
953  eve = BM_vert_at_index(em->bm, vertnum);
954  dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
955  }
956  else {
957  return 0.0f;
958  }
959  }
960  else {
961  if (me->dvert) {
962  if (vertnum >= me->totvert) {
963  return 0.0f;
964  }
965  dv = &me->dvert[vertnum];
966  }
967  }
968  }
969  else if (ob->type == OB_LATTICE) {
970  Lattice *lt = vgroup_edit_lattice(ob);
971 
972  if (lt->dvert) {
973  if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
974  return 0.0f;
975  }
976  dv = &lt->dvert[vertnum];
977  }
978  }
979 
980  if (dv) {
981  MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr);
982  if (dw) {
983  return dw->weight;
984  }
985  }
986 
987  return -1;
988 }
989 
990 float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
991 {
992  const int def_nr = BLI_findindex(&ob->defbase, dg);
993 
994  if (def_nr == -1) {
995  return -1;
996  }
997 
998  return get_vert_def_nr(ob, def_nr, vertnum);
999 }
1000 
1001 void ED_vgroup_select_by_name(Object *ob, const char *name)
1002 {
1003  /* note: ob->actdef==0 signals on painting to create a new one,
1004  * if a bone in posemode is selected */
1005  ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1;
1006 }
1007 
1010 /* -------------------------------------------------------------------- */
1014 /* only in editmode */
1015 static void vgroup_select_verts(Object *ob, int select)
1016 {
1017  const int def_nr = ob->actdef - 1;
1018 
1019  if (!BLI_findlink(&ob->defbase, def_nr)) {
1020  return;
1021  }
1022 
1023  if (ob->type == OB_MESH) {
1024  Mesh *me = ob->data;
1025 
1026  if (me->edit_mesh) {
1027  BMEditMesh *em = me->edit_mesh;
1028  const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
1029 
1030  if (cd_dvert_offset != -1) {
1031  BMIter iter;
1032  BMVert *eve;
1033 
1034  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
1035  if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
1036  MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
1037  if (BKE_defvert_find_index(dv, def_nr)) {
1038  BM_vert_select_set(em->bm, eve, select);
1039  }
1040  }
1041  }
1042 
1043  /* this has to be called, because this function operates on vertices only */
1044  if (select) {
1045  EDBM_select_flush(em); /* vertices to edges/faces */
1046  }
1047  else {
1048  EDBM_deselect_flush(em);
1049  }
1050  }
1051  }
1052  else {
1053  if (me->dvert) {
1054  MVert *mv;
1055  MDeformVert *dv;
1056  int i;
1057 
1058  mv = me->mvert;
1059  dv = me->dvert;
1060 
1061  for (i = 0; i < me->totvert; i++, mv++, dv++) {
1062  if (!(mv->flag & ME_HIDE)) {
1063  if (BKE_defvert_find_index(dv, def_nr)) {
1064  if (select) {
1065  mv->flag |= SELECT;
1066  }
1067  else {
1068  mv->flag &= ~SELECT;
1069  }
1070  }
1071  }
1072  }
1073 
1075  }
1076  }
1077  }
1078  else if (ob->type == OB_LATTICE) {
1079  Lattice *lt = vgroup_edit_lattice(ob);
1080 
1081  if (lt->dvert) {
1082  MDeformVert *dv;
1083  BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
1084  int a, tot;
1085 
1086  dv = lt->dvert;
1087 
1088  tot = lt->pntsu * lt->pntsv * lt->pntsw;
1089  for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
1090  if (BKE_defvert_find_index(dv, def_nr)) {
1091  if (select) {
1092  bp->f1 |= SELECT;
1093  }
1094  else {
1095  bp->f1 &= ~SELECT;
1096  if (actbp && bp == actbp) {
1097  lt->actbp = LT_ACTBP_NONE;
1098  }
1099  }
1100  }
1101  }
1102  }
1103  }
1104 }
1105 
1106 static void vgroup_duplicate(Object *ob)
1107 {
1108  bDeformGroup *dg, *cdg;
1109  char name[sizeof(dg->name)];
1110  MDeformWeight *dw_org, *dw_cpy;
1111  MDeformVert **dvert_array = NULL;
1112  int i, idg, icdg, dvert_tot = 0;
1113 
1114  dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
1115  if (!dg) {
1116  return;
1117  }
1118 
1119  if (!strstr(dg->name, "_copy")) {
1120  BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
1121  }
1122  else {
1123  BLI_strncpy(name, dg->name, sizeof(name));
1124  }
1125 
1126  cdg = BKE_defgroup_duplicate(dg);
1127  BLI_strncpy(cdg->name, name, sizeof(cdg->name));
1129 
1130  BLI_addtail(&ob->defbase, cdg);
1131 
1132  idg = (ob->actdef - 1);
1133  ob->actdef = BLI_listbase_count(&ob->defbase);
1134  icdg = (ob->actdef - 1);
1135 
1136  /* TODO, we might want to allow only copy selected verts here? - campbell */
1137  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
1138 
1139  if (dvert_array) {
1140  for (i = 0; i < dvert_tot; i++) {
1141  MDeformVert *dv = dvert_array[i];
1142  dw_org = BKE_defvert_find_index(dv, idg);
1143  if (dw_org) {
1144  /* BKE_defvert_ensure_index re-allocs org so need to store the weight first */
1145  const float weight = dw_org->weight;
1146  dw_cpy = BKE_defvert_ensure_index(dv, icdg);
1147  dw_cpy->weight = weight;
1148  }
1149  }
1150 
1151  MEM_freeN(dvert_array);
1152  }
1153 }
1154 
1155 static bool vgroup_normalize(Object *ob)
1156 {
1157  MDeformWeight *dw;
1158  MDeformVert *dv, **dvert_array = NULL;
1159  int dvert_tot = 0;
1160  const int def_nr = ob->actdef - 1;
1161 
1162  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1163 
1164  if (!BLI_findlink(&ob->defbase, def_nr)) {
1165  return false;
1166  }
1167 
1168  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1169 
1170  if (dvert_array) {
1171  float weight_max = 0.0f;
1172 
1173  for (int i = 0; i < dvert_tot; i++) {
1174 
1175  /* in case its not selected */
1176  if (!(dv = dvert_array[i])) {
1177  continue;
1178  }
1179 
1180  dw = BKE_defvert_find_index(dv, def_nr);
1181  if (dw) {
1182  weight_max = max_ff(dw->weight, weight_max);
1183  }
1184  }
1185 
1186  if (weight_max > 0.0f) {
1187  for (int i = 0; i < dvert_tot; i++) {
1188 
1189  /* in case its not selected */
1190  if (!(dv = dvert_array[i])) {
1191  continue;
1192  }
1193 
1194  dw = BKE_defvert_find_index(dv, def_nr);
1195  if (dw) {
1196  dw->weight /= weight_max;
1197 
1198  /* in case of division errors with very low weights */
1199  CLAMP(dw->weight, 0.0f, 1.0f);
1200  }
1201  }
1202  }
1203 
1204  MEM_freeN(dvert_array);
1205 
1206  return true;
1207  }
1208 
1209  return false;
1210 }
1211 
1212 /* This finds all of the vertices face-connected to vert by an edge and returns a
1213  * MEM_allocated array of indices of size count.
1214  * count is an int passed by reference so it can be assigned the value of the length here. */
1215 static int *getSurroundingVerts(Mesh *me, int vert, int *count)
1216 {
1217  MPoly *mp = me->mpoly;
1218  int i = me->totpoly;
1219  /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
1220  * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
1221  * many vertices face-linked to another one, even 8 might be too high...). */
1222  int *verts = NULL;
1224 
1226  while (i--) {
1227  int j = mp->totloop;
1228  int first_l = mp->totloop - 1;
1229  MLoop *ml = &me->mloop[mp->loopstart];
1230  while (j--) {
1231  /* XXX This assume a vert can only be once in a poly, even though
1232  * it seems logical to me, not totally sure of that. */
1233  if (ml->v == vert) {
1234  int a, b, k;
1235  if (j == first_l) {
1236  /* We are on the first corner. */
1237  a = ml[1].v;
1238  b = ml[j].v;
1239  }
1240  else if (!j) {
1241  /* We are on the last corner. */
1242  a = (ml - 1)->v;
1243  b = me->mloop[mp->loopstart].v;
1244  }
1245  else {
1246  a = (ml - 1)->v;
1247  b = (ml + 1)->v;
1248  }
1249 
1250  /* Append a and b verts to array, if not yet present. */
1251  k = BLI_array_len(verts);
1252  /* XXX Maybe a == b is enough? */
1253  while (k-- && !(a == b && a == -1)) {
1254  if (verts[k] == a) {
1255  a = -1;
1256  }
1257  else if (verts[k] == b) {
1258  b = -1;
1259  }
1260  }
1261  if (a != -1) {
1263  }
1264  if (b != -1) {
1265  BLI_array_append(verts, b);
1266  }
1267 
1268  /* Vert found in this poly, we can go to next one! */
1269  break;
1270  }
1271  ml++;
1272  }
1273  mp++;
1274  }
1275 
1276  /* Do not free the array! */
1278  return verts;
1279 }
1280 
1281 /* Get a single point in space by averaging a point cloud (vectors of size 3)
1282  * coord is the place the average is stored,
1283  * points is the point cloud, count is the number of points in the cloud.
1284  */
1285 static void getSingleCoordinate(MVert *points, int count, float coord[3])
1286 {
1287  int i;
1288  zero_v3(coord);
1289  for (i = 0; i < count; i++) {
1290  add_v3_v3(coord, points[i].co);
1291  }
1292  mul_v3_fl(coord, 1.0f / count);
1293 }
1294 
1295 /* given a plane and a start and end position,
1296  * compute the amount of vertical distance relative to the plane and store it in dists,
1297  * then get the horizontal and vertical change and store them in changes
1298  */
1299 static void getVerticalAndHorizontalChange(const float norm[3],
1300  float d,
1301  const float coord[3],
1302  const float start[3],
1303  float distToStart,
1304  float *end,
1305  float (*changes)[2],
1306  float *dists,
1307  int index)
1308 {
1309  /* A = Q - ((Q - P).N)N
1310  * D = (a * x0 + b * y0 +c * z0 + d) */
1311  float projA[3], projB[3];
1312  float plane[4];
1313 
1314  plane_from_point_normal_v3(plane, coord, norm);
1315 
1316  closest_to_plane_normalized_v3(projA, plane, start);
1317  closest_to_plane_normalized_v3(projB, plane, end);
1318  /* (vertical and horizontal refer to the plane's y and xz respectively)
1319  * vertical distance */
1320  dists[index] = dot_v3v3(norm, end) + d;
1321  /* vertical change */
1322  changes[index][0] = dists[index] - distToStart;
1323  // printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
1324  /* horizontal change */
1325  changes[index][1] = len_v3v3(projA, projB);
1326 }
1327 
1328 /* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
1329  * distToBe distance away from the provided plane strength can change distToBe so that it moves
1330  * towards distToBe by that percentage cp changes how much the weights are adjusted
1331  * to check the distance
1332  *
1333  * index is the index of the vertex being moved
1334  * norm and d are the plane's properties for the equation: ax + by + cz + d = 0
1335  * coord is a point on the plane
1336  */
1338  Scene *UNUSED(scene),
1339  Object *ob,
1340  Mesh *me,
1341  int index,
1342  const float norm[3],
1343  const float coord[3],
1344  float d,
1345  float distToBe,
1346  float strength,
1347  float cp)
1348 {
1349  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
1350  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1351  Mesh *mesh_eval = (Mesh *)object_eval->data;
1352 
1353  Mesh *me_deform;
1354  MDeformWeight *dw, *dw_eval;
1355  MVert m;
1356  MDeformVert *dvert = me->dvert + index;
1357  MDeformVert *dvert_eval = mesh_eval->dvert + index;
1358  int totweight = dvert->totweight;
1359  float oldw = 0;
1360  float oldPos[3] = {0};
1361  float vc, hc, dist = 0.0f;
1362  int i, k;
1363  float(*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
1364  float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
1365 
1366  /* track if up or down moved it closer for each bone */
1367  int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
1368 
1369  int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
1370  float distToStart;
1371  int bestIndex = 0;
1372  bool wasChange;
1373  char wasUp;
1374  int lastIndex = -1;
1375  float originalDistToBe = distToBe;
1376  do {
1377  wasChange = false;
1378  me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1379  m = me_deform->mvert[index];
1380  copy_v3_v3(oldPos, m.co);
1381  distToStart = dot_v3v3(norm, oldPos) + d;
1382 
1383  if (distToBe == originalDistToBe) {
1384  distToBe += distToStart - distToStart * strength;
1385  }
1386  for (i = 0; i < totweight; i++) {
1387  dwIndices[i] = i;
1388  dw = (dvert->dw + i);
1389  dw_eval = (dvert_eval->dw + i);
1390  vc = hc = 0;
1391  if (!dw->weight) {
1392  changes[i][0] = 0;
1393  changes[i][1] = 0;
1394  dists[i] = distToStart;
1395  continue;
1396  }
1397  for (k = 0; k < 2; k++) {
1398  if (me_deform) {
1399  /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
1400  * Better to over-free and recompute a bit. */
1401  BKE_object_free_derived_caches(object_eval);
1402  }
1403  oldw = dw->weight;
1404  if (k) {
1405  dw->weight *= 1 + cp;
1406  }
1407  else {
1408  dw->weight /= 1 + cp;
1409  }
1410  if (dw->weight == oldw) {
1411  changes[i][0] = 0;
1412  changes[i][1] = 0;
1413  dists[i] = distToStart;
1414  break;
1415  }
1416  if (dw->weight > 1) {
1417  dw->weight = 1;
1418  }
1419  dw_eval->weight = dw->weight;
1420  me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1421  m = me_deform->mvert[index];
1423  norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
1424  dw->weight = oldw;
1425  dw_eval->weight = oldw;
1426  if (!k) {
1427  vc = changes[i][0];
1428  hc = changes[i][1];
1429  dist = dists[i];
1430  }
1431  else {
1432  if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
1433  upDown[i] = 0;
1434  changes[i][0] = vc;
1435  changes[i][1] = hc;
1436  dists[i] = dist;
1437  }
1438  else {
1439  upDown[i] = 1;
1440  }
1441  if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
1442  changes[i][0] = 0;
1443  changes[i][1] = 0;
1444  dists[i] = distToStart;
1445  }
1446  }
1447  }
1448  }
1449  /* sort the changes by the vertical change */
1450  for (k = 0; k < totweight; k++) {
1451  float tf;
1452  int ti;
1453  bestIndex = k;
1454  for (i = k + 1; i < totweight; i++) {
1455  dist = dists[i];
1456 
1457  if (fabsf(dist) > fabsf(dists[i])) {
1458  bestIndex = i;
1459  }
1460  }
1461  /* switch with k */
1462  if (bestIndex != k) {
1463  ti = upDown[k];
1464  upDown[k] = upDown[bestIndex];
1465  upDown[bestIndex] = ti;
1466 
1467  ti = dwIndices[k];
1468  dwIndices[k] = dwIndices[bestIndex];
1469  dwIndices[bestIndex] = ti;
1470 
1471  tf = changes[k][0];
1472  changes[k][0] = changes[bestIndex][0];
1473  changes[bestIndex][0] = tf;
1474 
1475  tf = changes[k][1];
1476  changes[k][1] = changes[bestIndex][1];
1477  changes[bestIndex][1] = tf;
1478 
1479  tf = dists[k];
1480  dists[k] = dists[bestIndex];
1481  dists[bestIndex] = tf;
1482  }
1483  }
1484  bestIndex = -1;
1485  /* find the best change with an acceptable horizontal change */
1486  for (i = 0; i < totweight; i++) {
1487  if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
1488  bestIndex = i;
1489  break;
1490  }
1491  }
1492  if (bestIndex != -1) {
1493  wasChange = true;
1494  /* it is a good place to stop if it tries to move the opposite direction
1495  * (relative to the plane) of last time */
1496  if (lastIndex != -1) {
1497  if (wasUp != upDown[bestIndex]) {
1498  wasChange = false;
1499  }
1500  }
1501  lastIndex = bestIndex;
1502  wasUp = upDown[bestIndex];
1503  dw = (dvert->dw + dwIndices[bestIndex]);
1504  oldw = dw->weight;
1505  if (upDown[bestIndex]) {
1506  dw->weight *= 1 + cp;
1507  }
1508  else {
1509  dw->weight /= 1 + cp;
1510  }
1511  if (dw->weight > 1) {
1512  dw->weight = 1;
1513  }
1514  if (oldw == dw->weight) {
1515  wasChange = false;
1516  }
1517  if (me_deform) {
1518  /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
1519  * Better to over-free and recompute a bit. */
1520  BKE_object_free_derived_caches(object_eval);
1521  }
1522  }
1523  } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
1524  (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
1525 
1526  MEM_freeN(upDown);
1527  MEM_freeN(changes);
1528  MEM_freeN(dists);
1529  MEM_freeN(dwIndices);
1530 }
1531 
1532 /* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
1533  * but it could be used to raise or lower an existing 'bump.' */
1534 static void vgroup_fix(
1535  const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp)
1536 {
1538  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
1539  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
1540  int i;
1541 
1542  Mesh *me = ob->data;
1543  MVert *mvert = me->mvert;
1544  int *verts = NULL;
1545  if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL)) {
1546  return;
1547  }
1548  for (i = 0; i < me->totvert && mvert; i++, mvert++) {
1549  if (mvert->flag & SELECT) {
1550  int count = 0;
1551  if ((verts = getSurroundingVerts(me, i, &count))) {
1552  MVert m;
1553  MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
1554  int k;
1555 
1556  Mesh *me_deform = mesh_get_eval_deform(
1557  depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
1558  k = count;
1559  while (k--) {
1560  p[k] = me_deform->mvert[verts[k]];
1561  }
1562 
1563  if (count >= 3) {
1564  float d /*, dist */ /* UNUSED */, mag;
1565  float coord[3];
1566  float norm[3];
1567  getSingleCoordinate(p, count, coord);
1568  m = me_deform->mvert[i];
1569  sub_v3_v3v3(norm, m.co, coord);
1570  mag = normalize_v3(norm);
1571  if (mag) { /* zeros fix */
1572  d = -dot_v3v3(norm, coord);
1573  /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
1575  depsgraph, scene_eval, object_eval, me, i, norm, coord, d, distToBe, strength, cp);
1576  }
1577  }
1578 
1579  MEM_freeN(verts);
1580  MEM_freeN(p);
1581  }
1582  }
1583  }
1584 }
1585 
1587  const bool *vgroup_validmap,
1588  const int vgroup_tot,
1589  const int UNUSED(subset_count),
1590  const float offset,
1591  const float gain)
1592 {
1593  MDeformWeight *dw;
1594  MDeformVert *dv, **dvert_array = NULL;
1595  int dvert_tot = 0;
1596 
1597  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1598  const bool use_mirror = (ob->type == OB_MESH) ?
1599  (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1600  false;
1601 
1602  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1603 
1604  if (dvert_array) {
1605 
1606  for (int i = 0; i < dvert_tot; i++) {
1607  /* in case its not selected */
1608  if (!(dv = dvert_array[i])) {
1609  continue;
1610  }
1611 
1612  int j = vgroup_tot;
1613  while (j--) {
1614  if (vgroup_validmap[j]) {
1615  dw = BKE_defvert_find_index(dv, j);
1616  if (dw) {
1617  dw->weight = gain * (dw->weight + offset);
1618 
1619  CLAMP(dw->weight, 0.0f, 1.0f);
1620  }
1621  }
1622  }
1623  }
1624 
1625  if (use_mirror && use_vert_sel) {
1626  ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
1627  }
1628 
1629  MEM_freeN(dvert_array);
1630  }
1631 }
1632 
1634  const bool *vgroup_validmap,
1635  const int vgroup_tot,
1636  const int subset_count,
1637  const bool lock_active,
1638  ReportList *reports)
1639 {
1640  MDeformVert *dv, **dvert_array = NULL;
1641  int i, dvert_tot = 0;
1642  const int def_nr = ob->actdef - 1;
1643 
1644  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1645 
1646  if (subset_count == 0) {
1647  BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
1648  return false;
1649  }
1650 
1651  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1652 
1653  if (dvert_array) {
1654  const int defbase_tot = BLI_listbase_count(&ob->defbase);
1655  bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
1656  bool changed = false;
1657 
1658  if ((lock_active == true) && (lock_flags != NULL) && (def_nr < defbase_tot)) {
1659  lock_flags[def_nr] = true;
1660  }
1661 
1662  if (lock_flags) {
1663  for (i = 0; i < defbase_tot; i++) {
1664  if (lock_flags[i] == false) {
1665  break;
1666  }
1667  }
1668 
1669  if (i == defbase_tot) {
1670  BKE_report(reports, RPT_ERROR, "All groups are locked");
1671  goto finally;
1672  }
1673  }
1674 
1675  for (i = 0; i < dvert_tot; i++) {
1676  /* in case its not selected */
1677  if ((dv = dvert_array[i])) {
1678  if (lock_flags) {
1679  BKE_defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, lock_flags, defbase_tot);
1680  }
1681  else if (lock_active) {
1682  BKE_defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
1683  }
1684  else {
1685  BKE_defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
1686  }
1687  }
1688  }
1689 
1690  changed = true;
1691 
1692  finally:
1693  if (lock_flags) {
1694  MEM_freeN(lock_flags);
1695  }
1696 
1697  MEM_freeN(dvert_array);
1698 
1699  return changed;
1700  }
1701 
1702  return false;
1703 }
1704 
1705 enum {
1710 };
1711 
1713  {VGROUP_TOGGLE,
1714  "TOGGLE",
1715  0,
1716  "Toggle",
1717  "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
1718  {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
1719  {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
1720  {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
1721  {0, NULL, 0, NULL, NULL},
1722 };
1723 
1724 enum {
1729 };
1730 
1732  {VGROUP_MASK_ALL, "ALL", 0, "All", "Apply action to all vertex groups"},
1733  {VGROUP_MASK_SELECTED, "SELECTED", 0, "Selected", "Apply to selected vertex groups"},
1734  {VGROUP_MASK_UNSELECTED, "UNSELECTED", 0, "Unselected", "Apply to unselected vertex groups"},
1736  "INVERT_UNSELECTED",
1737  0,
1738  "Invert Unselected",
1739  "Apply the opposite of Lock/Unlock to unselected vertex groups"},
1740  {0, NULL, 0, NULL, NULL},
1741 };
1742 
1743 static bool *vgroup_selected_get(Object *ob)
1744 {
1745  int sel_count = 0, defbase_tot = BLI_listbase_count(&ob->defbase);
1746  bool *mask;
1747 
1748  if (ob->mode & OB_MODE_WEIGHT_PAINT) {
1749  mask = BKE_object_defgroup_selected_get(ob, defbase_tot, &sel_count);
1750 
1751  /* Mirror the selection if X Mirror is enabled. */
1752  Mesh *me = BKE_mesh_from_object(ob);
1753 
1754  if (me && ME_USING_MIRROR_X_VERTEX_GROUPS(me)) {
1755  BKE_object_defgroup_mirror_selection(ob, defbase_tot, mask, mask, &sel_count);
1756  }
1757  }
1758  else {
1759  mask = MEM_callocN(defbase_tot * sizeof(bool), __func__);
1760  }
1761 
1762  if (sel_count == 0 && ob->actdef >= 1 && ob->actdef <= defbase_tot) {
1763  mask[ob->actdef - 1] = true;
1764  }
1765 
1766  return mask;
1767 }
1768 
1769 static void vgroup_lock_all(Object *ob, int action, int mask)
1770 {
1771  bDeformGroup *dg;
1772  bool *selected = NULL;
1773  int i;
1774 
1775  if (mask != VGROUP_MASK_ALL) {
1776  selected = vgroup_selected_get(ob);
1777  }
1778 
1779  if (action == VGROUP_TOGGLE) {
1780  action = VGROUP_LOCK;
1781 
1782  for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
1783  switch (mask) {
1785  case VGROUP_MASK_SELECTED:
1786  if (!selected[i]) {
1787  continue;
1788  }
1789  break;
1791  if (selected[i]) {
1792  continue;
1793  }
1794  break;
1795  default:;
1796  }
1797 
1798  if (dg->flag & DG_LOCK_WEIGHT) {
1799  action = VGROUP_UNLOCK;
1800  break;
1801  }
1802  }
1803  }
1804 
1805  for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
1806  switch (mask) {
1807  case VGROUP_MASK_SELECTED:
1808  if (!selected[i]) {
1809  continue;
1810  }
1811  break;
1813  if (selected[i]) {
1814  continue;
1815  }
1816  break;
1817  default:;
1818  }
1819 
1820  switch (action) {
1821  case VGROUP_LOCK:
1822  dg->flag |= DG_LOCK_WEIGHT;
1823  break;
1824  case VGROUP_UNLOCK:
1825  dg->flag &= ~DG_LOCK_WEIGHT;
1826  break;
1827  case VGROUP_INVERT:
1828  dg->flag ^= DG_LOCK_WEIGHT;
1829  break;
1830  }
1831 
1832  if (mask == VGROUP_MASK_INVERT_UNSELECTED && !selected[i]) {
1833  dg->flag ^= DG_LOCK_WEIGHT;
1834  }
1835  }
1836 
1837  if (selected) {
1838  MEM_freeN(selected);
1839  }
1840 }
1841 
1843  const bool *vgroup_validmap,
1844  const int vgroup_tot,
1845  const int UNUSED(subset_count),
1846  const bool auto_assign,
1847  const bool auto_remove)
1848 {
1849  MDeformWeight *dw;
1850  MDeformVert *dv, **dvert_array = NULL;
1851  int dvert_tot = 0;
1852  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
1853  const bool use_mirror = (ob->type == OB_MESH) ?
1854  (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1855  false;
1856 
1857  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
1858 
1859  if (dvert_array) {
1860  for (int i = 0; i < dvert_tot; i++) {
1861  /* in case its not selected */
1862  if (!(dv = dvert_array[i])) {
1863  continue;
1864  }
1865 
1866  int j = vgroup_tot;
1867  while (j--) {
1868 
1869  if (vgroup_validmap[j]) {
1870  if (auto_assign) {
1871  dw = BKE_defvert_ensure_index(dv, j);
1872  }
1873  else {
1874  dw = BKE_defvert_find_index(dv, j);
1875  }
1876 
1877  if (dw) {
1878  dw->weight = 1.0f - dw->weight;
1879  CLAMP(dw->weight, 0.0f, 1.0f);
1880  }
1881  }
1882  }
1883  }
1884 
1885  if (use_mirror && use_vert_sel) {
1886  ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
1887  }
1888 
1889  if (auto_remove) {
1891  dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, 0.0f, false);
1892  }
1893 
1894  MEM_freeN(dvert_array);
1895  }
1896 }
1897 
1899  const bool *vgroup_validmap,
1900  const int vgroup_tot,
1901  const int subset_count,
1902  const float fac,
1903  const int repeat,
1904  const float fac_expand)
1905 {
1906  const float ifac = 1.0f - fac;
1907  MDeformVert **dvert_array = NULL;
1908  int dvert_tot = 0;
1909  int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
1910  float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
1911  const bool use_mirror = (ob->type == OB_MESH) ?
1912  (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
1913  false;
1914  const bool use_select = vertex_group_use_vert_sel(ob);
1915  const bool use_hide = use_select;
1916 
1917  const int expand_sign = signum_i(fac_expand);
1918  const float expand = fabsf(fac_expand);
1919  const float iexpand = 1.0f - expand;
1920 
1922  BMesh *bm = em ? em->bm : NULL;
1923  Mesh *me = em ? NULL : ob->data;
1924 
1925  MeshElemMap *emap;
1926  int *emap_mem;
1927 
1928  float *weight_accum_prev;
1929  float *weight_accum_curr;
1930 
1931  uint subset_index;
1932 
1933  /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
1934  uint *verts_used;
1935  STACK_DECLARE(verts_used);
1936 
1937  BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
1938  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
1939  memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
1940 
1941  if (bm) {
1944 
1945  emap = NULL;
1946  emap_mem = NULL;
1947  }
1948  else {
1949  BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
1950  }
1951 
1952  weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
1953  weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
1954 
1955  verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
1956  STACK_INIT(verts_used, dvert_tot);
1957 
1958 #define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
1959 #define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
1960 
1961 #define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
1962 #define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true)
1963 
1964  /* initialize used verts */
1965  if (bm) {
1966  for (int i = 0; i < dvert_tot; i++) {
1967  BMVert *v = BM_vert_at_index(bm, i);
1968  if (IS_BM_VERT_WRITE(v)) {
1969  BMIter eiter;
1970  BMEdge *e;
1971  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
1972  BMVert *v_other = BM_edge_other_vert(e, v);
1973  if (IS_BM_VERT_READ(v_other)) {
1974  STACK_PUSH(verts_used, i);
1975  break;
1976  }
1977  }
1978  }
1979  }
1980  }
1981  else {
1982  for (int i = 0; i < dvert_tot; i++) {
1983  const MVert *v = &me->mvert[i];
1984  if (IS_ME_VERT_WRITE(v)) {
1985  for (int j = 0; j < emap[i].count; j++) {
1986  const MEdge *e = &me->medge[emap[i].indices[j]];
1987  const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
1988  if (IS_ME_VERT_READ(v_other)) {
1989  STACK_PUSH(verts_used, i);
1990  break;
1991  }
1992  }
1993  }
1994  }
1995  }
1996 
1997  for (subset_index = 0; subset_index < subset_count; subset_index++) {
1998  const int def_nr = vgroup_subset_map[subset_index];
1999  int iter;
2000 
2002  (const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
2003  memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
2004 
2005  for (iter = 0; iter < repeat; iter++) {
2006  uint *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
2007 
2008  /* avoid looping over all verts */
2009  // for (i = 0; i < dvert_tot; i++)
2010  for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
2011  const uint i = *vi_step;
2012  float weight_tot = 0.0f;
2013  float weight = 0.0f;
2014 
2015 #define WEIGHT_ACCUMULATE \
2016  { \
2017  float weight_other = weight_accum_prev[i_other]; \
2018  float tot_factor = 1.0f; \
2019  if (expand_sign == 1) { /* expand */ \
2020  if (weight_other < weight_accum_prev[i]) { \
2021  weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
2022  tot_factor = iexpand; \
2023  } \
2024  } \
2025  else if (expand_sign == -1) { /* contract */ \
2026  if (weight_other > weight_accum_prev[i]) { \
2027  weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
2028  tot_factor = iexpand; \
2029  } \
2030  } \
2031  weight += tot_factor * weight_other; \
2032  weight_tot += tot_factor; \
2033  } \
2034  ((void)0)
2035 
2036  if (bm) {
2037  BMVert *v = BM_vert_at_index(bm, i);
2038  BMIter eiter;
2039  BMEdge *e;
2040 
2041  /* checked already */
2043 
2044  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
2045  BMVert *v_other = BM_edge_other_vert(e, v);
2046  if (IS_BM_VERT_READ(v_other)) {
2047  const int i_other = BM_elem_index_get(v_other);
2048 
2050  }
2051  }
2052  }
2053  else {
2054  int j;
2055 
2056  /* checked already */
2057  BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
2058 
2059  for (j = 0; j < emap[i].count; j++) {
2060  MEdge *e = &me->medge[emap[i].indices[j]];
2061  const int i_other = (e->v1 == i ? e->v2 : e->v1);
2062  MVert *v_other = &me->mvert[i_other];
2063 
2064  if (IS_ME_VERT_READ(v_other)) {
2066  }
2067  }
2068  }
2069 
2070 #undef WEIGHT_ACCUMULATE
2071 
2072  if (weight_tot != 0.0f) {
2073  weight /= weight_tot;
2074  weight = (weight_accum_prev[i] * ifac) + (weight * fac);
2075 
2076  /* should be within range, just clamp because of float precision */
2077  CLAMP(weight, 0.0f, 1.0f);
2078  weight_accum_curr[i] = weight;
2079  }
2080  }
2081 
2082  SWAP(float *, weight_accum_curr, weight_accum_prev);
2083  }
2084 
2085  ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
2086  }
2087 
2088 #undef IS_BM_VERT_READ
2089 #undef IS_BM_VERT_WRITE
2090 #undef IS_ME_VERT_READ
2091 #undef IS_ME_VERT_WRITE
2092 
2093  MEM_freeN(weight_accum_curr);
2094  MEM_freeN(weight_accum_prev);
2095  MEM_freeN(verts_used);
2096 
2097  if (bm) {
2098  /* pass */
2099  }
2100  else {
2101  MEM_freeN(emap);
2102  MEM_freeN(emap_mem);
2103  }
2104 
2105  if (dvert_array) {
2106  MEM_freeN(dvert_array);
2107  }
2108 
2109  /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
2110  if (use_mirror) {
2111  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
2112  ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
2113  if (dvert_array) {
2114  MEM_freeN(dvert_array);
2115  }
2116  }
2117 }
2118 
2119 static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
2120 {
2121  /* qsort sorts in ascending order. We want descending order to save a memcopy
2122  * so this compare function is inverted from the standard greater than comparison qsort needs.
2123  * A normal compare function is called with two pointer arguments and should return an integer
2124  * less than, equal to, or greater than zero corresponding to whether its first argument is
2125  * considered less than, equal to, or greater than its second argument.
2126  * This does the opposite. */
2127  const struct MDeformWeight *dw1 = a1, *dw2 = a2;
2128 
2129  if (dw1->weight < dw2->weight) {
2130  return 1;
2131  }
2132  if (dw1->weight > dw2->weight) {
2133  return -1;
2134  }
2135  if (&dw1 < &dw2) {
2136  return 1; /* compare address for stable sort algorithm */
2137  }
2138  return -1;
2139 }
2140 
2141 /* Used for limiting the number of influencing bones per vertex when exporting
2142  * skinned meshes. if all_deform_weights is True, limit all deform modifiers
2143  * to max_weights regardless of type, otherwise,
2144  * only limit the number of influencing bones per vertex. */
2146  const bool *vgroup_validmap,
2147  const int vgroup_tot,
2148  const int subset_count,
2149  const int max_weights)
2150 {
2151  MDeformVert *dv, **dvert_array = NULL;
2152  int i, dvert_tot = 0;
2153  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2154  int remove_tot = 0;
2155 
2156  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2157 
2158  if (dvert_array) {
2159  int num_to_drop = 0;
2160 
2161  for (i = 0; i < dvert_tot; i++) {
2162 
2163  MDeformWeight *dw_temp;
2164  int bone_count = 0, non_bone_count = 0;
2165  int j;
2166 
2167  /* in case its not selected */
2168  if (!(dv = dvert_array[i])) {
2169  continue;
2170  }
2171 
2172  num_to_drop = subset_count - max_weights;
2173 
2174  /* first check if we even need to test further */
2175  if (num_to_drop > 0) {
2176  /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
2177  * sort the tail, then copy only the truncated array back to dv->dw */
2178  dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
2179  bone_count = 0;
2180  non_bone_count = 0;
2181  for (j = 0; j < dv->totweight; j++) {
2182  if (LIKELY(dv->dw[j].def_nr < vgroup_tot) && vgroup_validmap[dv->dw[j].def_nr]) {
2183  dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
2184  bone_count += 1;
2185  }
2186  else {
2187  dw_temp[non_bone_count] = dv->dw[j];
2188  non_bone_count += 1;
2189  }
2190  }
2191  BLI_assert(bone_count + non_bone_count == dv->totweight);
2192  num_to_drop = bone_count - max_weights;
2193  if (num_to_drop > 0) {
2194  qsort(&dw_temp[non_bone_count],
2195  bone_count,
2196  sizeof(MDeformWeight),
2198  dv->totweight -= num_to_drop;
2199  /* Do we want to clean/normalize here? */
2200  MEM_freeN(dv->dw);
2201  dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
2202  remove_tot += num_to_drop;
2203  }
2204  else {
2205  MEM_freeN(dw_temp);
2206  }
2207  }
2208  }
2209  MEM_freeN(dvert_array);
2210  }
2211 
2212  return remove_tot;
2213 }
2214 
2215 static void vgroup_clean_subset(Object *ob,
2216  const bool *vgroup_validmap,
2217  const int vgroup_tot,
2218  const int UNUSED(subset_count),
2219  const float epsilon,
2220  const bool keep_single)
2221 {
2222  MDeformVert **dvert_array = NULL;
2223  int dvert_tot = 0;
2224  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2225  const bool use_mirror = (ob->type == OB_MESH) ?
2226  (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
2227  false;
2228 
2229  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2230 
2231  if (dvert_array) {
2232  if (use_mirror && use_vert_sel) {
2233  /* correct behavior in this case isn't well defined
2234  * for now assume both sides are mirrored correctly,
2235  * so cleaning one side also cleans the other */
2236  ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
2237  }
2238 
2240  dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, epsilon, keep_single);
2241 
2242  MEM_freeN(dvert_array);
2243  }
2244 }
2245 
2247  const bool *vgroup_validmap,
2248  const int vgroup_tot,
2249  const int UNUSED(subset_count),
2250  const int steps)
2251 {
2252  MDeformVert **dvert_array = NULL;
2253  int dvert_tot = 0;
2254  const bool use_vert_sel = vertex_group_use_vert_sel(ob);
2255  const bool use_mirror = (ob->type == OB_MESH) ?
2256  (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 :
2257  false;
2258  ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
2259 
2260  if (dvert_array) {
2261  const float steps_fl = steps;
2262  MDeformVert *dv;
2263 
2264  if (use_mirror && use_vert_sel) {
2265  ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
2266  }
2267 
2268  for (int i = 0; i < dvert_tot; i++) {
2269  MDeformWeight *dw;
2270 
2271  /* in case its not selected */
2272  if (!(dv = dvert_array[i])) {
2273  continue;
2274  }
2275 
2276  int j;
2277  for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
2278  if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
2279  dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
2280  CLAMP(dw->weight, 0.0f, 1.0f);
2281  }
2282  }
2283  }
2284 
2285  MEM_freeN(dvert_array);
2286  }
2287 }
2288 
2289 static void dvert_mirror_op(MDeformVert *dvert,
2290  MDeformVert *dvert_mirr,
2291  const char sel,
2292  const char sel_mirr,
2293  const int *flip_map,
2294  const int flip_map_len,
2295  const bool mirror_weights,
2296  const bool flip_vgroups,
2297  const bool all_vgroups,
2298  const int act_vgroup)
2299 {
2300  BLI_assert(sel || sel_mirr);
2301 
2302  if (sel_mirr && sel) {
2303  /* swap */
2304  if (mirror_weights) {
2305  if (all_vgroups) {
2306  SWAP(MDeformVert, *dvert, *dvert_mirr);
2307  }
2308  else {
2309  MDeformWeight *dw = BKE_defvert_find_index(dvert, act_vgroup);
2310  MDeformWeight *dw_mirr = BKE_defvert_find_index(dvert_mirr, act_vgroup);
2311 
2312  if (dw && dw_mirr) {
2313  SWAP(float, dw->weight, dw_mirr->weight);
2314  }
2315  else if (dw) {
2316  dw_mirr = BKE_defvert_ensure_index(dvert_mirr, act_vgroup);
2317  dw_mirr->weight = dw->weight;
2318  BKE_defvert_remove_group(dvert, dw);
2319  }
2320  else if (dw_mirr) {
2321  dw = BKE_defvert_ensure_index(dvert, act_vgroup);
2322  dw->weight = dw_mirr->weight;
2323  BKE_defvert_remove_group(dvert_mirr, dw_mirr);
2324  }
2325  }
2326  }
2327 
2328  if (flip_vgroups) {
2329  BKE_defvert_flip(dvert, flip_map, flip_map_len);
2330  BKE_defvert_flip(dvert_mirr, flip_map, flip_map_len);
2331  }
2332  }
2333  else {
2334  /* dvert should always be the target, only swaps pointer */
2335  if (sel_mirr) {
2336  SWAP(MDeformVert *, dvert, dvert_mirr);
2337  }
2338 
2339  if (mirror_weights) {
2340  if (all_vgroups) {
2341  BKE_defvert_copy(dvert, dvert_mirr);
2342  }
2343  else {
2344  BKE_defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
2345  }
2346  }
2347 
2348  /* flip map already modified for 'all_vgroups' */
2349  if (flip_vgroups) {
2350  BKE_defvert_flip(dvert, flip_map, flip_map_len);
2351  }
2352  }
2353 }
2354 
2355 /* TODO, vgroup locking */
2356 /* TODO, face masking */
2358  const bool mirror_weights,
2359  const bool flip_vgroups,
2360  const bool all_vgroups,
2361  const bool use_topology,
2362  int *r_totmirr,
2363  int *r_totfail)
2364 {
2365 
2366 #define VGROUP_MIRR_OP \
2367  dvert_mirror_op(dvert, \
2368  dvert_mirr, \
2369  sel, \
2370  sel_mirr, \
2371  flip_map, \
2372  flip_map_len, \
2373  mirror_weights, \
2374  flip_vgroups, \
2375  all_vgroups, \
2376  def_nr)
2377 
2378  BMVert *eve, *eve_mirr;
2379  MDeformVert *dvert, *dvert_mirr;
2380  char sel, sel_mirr;
2381  int *flip_map = NULL, flip_map_len;
2382  const int def_nr = ob->actdef - 1;
2383  int totmirr = 0, totfail = 0;
2384 
2385  *r_totmirr = *r_totfail = 0;
2386 
2387  if ((mirror_weights == false && flip_vgroups == false) ||
2388  (BLI_findlink(&ob->defbase, def_nr) == NULL)) {
2389  return;
2390  }
2391 
2392  if (flip_vgroups) {
2393  flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) :
2394  BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
2395 
2396  BLI_assert(flip_map != NULL);
2397 
2398  if (flip_map == NULL) {
2399  /* something went wrong!, possibly no groups */
2400  return;
2401  }
2402  }
2403  else {
2404  flip_map = NULL;
2405  flip_map_len = 0;
2406  }
2407 
2408  /* only the active group */
2409  if (ob->type == OB_MESH) {
2410  Mesh *me = ob->data;
2411  BMEditMesh *em = me->edit_mesh;
2412 
2413  if (em) {
2414  const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
2415  BMIter iter;
2416 
2417  if (cd_dvert_offset == -1) {
2418  goto cleanup;
2419  }
2420 
2421  EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology);
2422 
2424 
2425  /* Go through the list of edit-vertices and assign them. */
2426  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2427  if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
2428  if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
2429  if (eve_mirr != eve) {
2430  if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
2431  sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
2432  sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
2433 
2434  if ((sel || sel_mirr) && (eve != eve_mirr)) {
2435  dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
2436  dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
2437 
2439  totmirr++;
2440  }
2441 
2442  /* don't use these again */
2444  BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
2445  }
2446  }
2447  }
2448  else {
2449  totfail++;
2450  }
2451  }
2452  }
2454  }
2455  else {
2456  /* object mode / weight paint */
2457  MVert *mv, *mv_mirr;
2458  int vidx, vidx_mirr;
2459  const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
2460 
2461  if (me->dvert == NULL) {
2462  goto cleanup;
2463  }
2464 
2465  if (!use_vert_sel) {
2466  sel = sel_mirr = true;
2467  }
2468 
2469  /* tag verts we have used */
2470  for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
2471  mv->flag &= ~ME_VERT_TMP_TAG;
2472  }
2473 
2474  for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
2475  if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
2476  if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
2477  if (vidx != vidx_mirr) {
2478  mv_mirr = &me->mvert[vidx_mirr];
2479  if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
2480 
2481  if (use_vert_sel) {
2482  sel = mv->flag & SELECT;
2483  sel_mirr = mv_mirr->flag & SELECT;
2484  }
2485 
2486  if (sel || sel_mirr) {
2487  dvert = &me->dvert[vidx];
2488  dvert_mirr = &me->dvert[vidx_mirr];
2489 
2491  totmirr++;
2492  }
2493 
2494  mv->flag |= ME_VERT_TMP_TAG;
2495  mv_mirr->flag |= ME_VERT_TMP_TAG;
2496  }
2497  }
2498  }
2499  else {
2500  totfail++;
2501  }
2502  }
2503  }
2504  }
2505  }
2506  else if (ob->type == OB_LATTICE) {
2507  Lattice *lt = vgroup_edit_lattice(ob);
2508  int i1, i2;
2509  int u, v, w;
2510  int pntsu_half;
2511  /* half but found up odd value */
2512 
2513  if (lt->pntsu == 1 || lt->dvert == NULL) {
2514  goto cleanup;
2515  }
2516 
2517  /* unlike editmesh we know that by only looping over the first half of
2518  * the 'u' indices it will cover all points except the middle which is
2519  * ok in this case */
2520  pntsu_half = lt->pntsu / 2;
2521 
2522  for (w = 0; w < lt->pntsw; w++) {
2523  for (v = 0; v < lt->pntsv; v++) {
2524  for (u = 0; u < pntsu_half; u++) {
2525  int u_inv = (lt->pntsu - 1) - u;
2526  if (u != u_inv) {
2527  BPoint *bp, *bp_mirr;
2528 
2529  i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
2530  i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
2531 
2532  bp = &lt->def[i1];
2533  bp_mirr = &lt->def[i2];
2534 
2535  sel = bp->f1 & SELECT;
2536  sel_mirr = bp_mirr->f1 & SELECT;
2537 
2538  if (sel || sel_mirr) {
2539  dvert = &lt->dvert[i1];
2540  dvert_mirr = &lt->dvert[i2];
2541 
2543  totmirr++;
2544  }
2545  }
2546  }
2547  }
2548  }
2549  }
2550 
2551  /* disabled, confusing when you have an active pose bone */
2552 #if 0
2553  /* flip active group index */
2554  if (flip_vgroups && flip_map[def_nr] >= 0) {
2555  ob->actdef = flip_map[def_nr] + 1;
2556  }
2557 #endif
2558 
2559 cleanup:
2560  *r_totmirr = totmirr;
2561  *r_totfail = totfail;
2562 
2563  if (flip_map) {
2564  MEM_freeN(flip_map);
2565  }
2566 
2567 #undef VGROUP_MIRR_OP
2568 }
2569 
2571 {
2572  bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
2573  if (!dg) {
2574  return;
2575  }
2576 
2578 }
2579 
2580 /* only in editmode */
2581 static void vgroup_assign_verts(Object *ob, const float weight)
2582 {
2583  const int def_nr = ob->actdef - 1;
2584 
2585  if (!BLI_findlink(&ob->defbase, def_nr)) {
2586  return;
2587  }
2588 
2589  if (ob->type == OB_MESH) {
2590  Mesh *me = ob->data;
2591 
2592  if (me->edit_mesh) {
2593  BMEditMesh *em = me->edit_mesh;
2594  int cd_dvert_offset;
2595 
2596  BMIter iter;
2597  BMVert *eve;
2598 
2601  }
2602 
2603  cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
2604 
2605  /* Go through the list of edit-vertices and assign them. */
2606  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
2607  if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
2608  MDeformVert *dv;
2609  MDeformWeight *dw;
2610  dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */
2611  dw = BKE_defvert_ensure_index(dv, def_nr);
2612  if (dw) {
2613  dw->weight = weight;
2614  }
2615  }
2616  }
2617  }
2618  else {
2619  if (!me->dvert) {
2621  }
2622 
2623  MVert *mv = me->mvert;
2624  MDeformVert *dv = me->dvert;
2625 
2626  for (int i = 0; i < me->totvert; i++, mv++, dv++) {
2627  if (mv->flag & SELECT) {
2628  MDeformWeight *dw;
2629  dw = BKE_defvert_ensure_index(dv, def_nr);
2630  if (dw) {
2631  dw->weight = weight;
2632  }
2633  }
2634  }
2635  }
2636  }
2637  else if (ob->type == OB_LATTICE) {
2638  Lattice *lt = vgroup_edit_lattice(ob);
2639  MDeformVert *dv;
2640  BPoint *bp;
2641  int a, tot;
2642 
2643  if (lt->dvert == NULL) {
2645  }
2646 
2647  dv = lt->dvert;
2648 
2649  tot = lt->pntsu * lt->pntsv * lt->pntsw;
2650  for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
2651  if (bp->f1 & SELECT) {
2652  MDeformWeight *dw;
2653 
2654  dw = BKE_defvert_ensure_index(dv, def_nr);
2655  if (dw) {
2656  dw->weight = weight;
2657  }
2658  }
2659  }
2660  }
2661 }
2662 
2665 /* -------------------------------------------------------------------- */
2670 {
2672  CTX_wm_operator_poll_msg_set(C, "No active editable object");
2673  return false;
2674  }
2675 
2676  if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) {
2677  CTX_wm_operator_poll_msg_set(C, "Object type does not support vertex groups");
2678  return false;
2679  }
2680 
2681  /* Data checks. */
2682  const ID *data = ob->data;
2684  CTX_wm_operator_poll_msg_set(C, "Object type \"%s\" does not have editable data");
2685  return false;
2686  }
2687 
2688  return true;
2689 }
2690 
2692 {
2693  Object *ob = ED_object_context(C);
2694  return vertex_group_supported_poll_ex(C, ob);
2695 }
2696 
2698 {
2699  if (!vertex_group_supported_poll_ex(C, ob)) {
2700  return false;
2701  }
2702 
2703  if (BLI_listbase_is_empty(&ob->defbase)) {
2704  CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups");
2705  return false;
2706  }
2707 
2708  return true;
2709 }
2710 
2712 {
2713  Object *ob = ED_object_context(C);
2714  return vertex_group_poll_ex(C, ob);
2715 }
2716 
2718 {
2719  if (!vertex_group_poll_ex(C, ob)) {
2720  return false;
2721  }
2722 
2723  if (ob->type != OB_MESH) {
2724  CTX_wm_operator_poll_msg_set(C, "Only mesh objects are supported");
2725  return false;
2726  }
2727 
2728  return true;
2729 }
2730 
2732 {
2733  Object *ob = ED_object_context(C);
2734  if (!vertex_group_mesh_poll_ex(C, ob)) {
2735  return false;
2736  }
2737 
2738  Mesh *me = ob->data;
2739  if (me->dvert == NULL) {
2740  CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data");
2741  return false;
2742  }
2743 
2744  return true;
2745 }
2746 
2748 {
2749  Object *ob = ED_object_context(C);
2750 
2751  if (!vertex_group_supported_poll_ex(C, ob)) {
2752  return false;
2753  }
2754 
2756 }
2757 
2758 /* editmode _or_ weight paint vertex sel */
2760  const bool needs_select,
2761  const short ob_type_flag)
2762 {
2763  Object *ob = ED_object_context(C);
2764 
2765  if (!vertex_group_supported_poll_ex(C, ob)) {
2766  return false;
2767  }
2768 
2769  if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
2770  return false;
2771  }
2772 
2774  return true;
2775  }
2776  if (ob->mode & OB_MODE_WEIGHT_PAINT) {
2777  if (needs_select) {
2779  return true;
2780  }
2781  CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
2782  return false;
2783  }
2784  return true;
2785  }
2786  return false;
2787 }
2788 
2789 #if 0
2790 static bool vertex_group_vert_poll(bContext *C)
2791 {
2792  return vertex_group_vert_poll_ex(C, false, 0);
2793 }
2794 #endif
2795 
2797 {
2798  return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
2799 }
2800 
2802 {
2803  return vertex_group_vert_poll_ex(C, true, 0);
2804 }
2805 
2806 #if 0
2807 static bool vertex_group_mesh_vert_select_poll(bContext *C)
2808 {
2809  return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
2810 }
2811 #endif
2812 
2813 /* editmode _or_ weight paint vertex sel and active group unlocked */
2815 {
2816  Object *ob = ED_object_context(C);
2817 
2818  if (!vertex_group_supported_poll_ex(C, ob)) {
2819  return false;
2820  }
2821 
2823  return false;
2824  }
2825 
2826  if (ob->actdef != 0) {
2827  bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
2828  if (dg) {
2829  return !(dg->flag & DG_LOCK_WEIGHT);
2830  }
2831  }
2832  return true;
2833 }
2834 
2836 {
2837  Object *ob = ED_object_context(C);
2838 
2839  if (!vertex_group_supported_poll_ex(C, ob)) {
2840  return false;
2841  }
2842 
2843  /* only difference to #vertex_group_vert_select_poll */
2844  if (ob->type != OB_MESH) {
2845  return false;
2846  }
2847 
2849 }
2850 
2853 /* -------------------------------------------------------------------- */
2858 {
2859  Object *ob = ED_object_context(C);
2860 
2866 
2867  return OPERATOR_FINISHED;
2868 }
2869 
2871 {
2872  /* identifiers */
2873  ot->name = "Add Vertex Group";
2874  ot->idname = "OBJECT_OT_vertex_group_add";
2875  ot->description = "Add a new vertex group to the active object";
2876 
2877  /* api callbacks */
2880 
2881  /* flags */
2883 }
2884 
2887 /* -------------------------------------------------------------------- */
2892 {
2893  Object *ob = ED_object_context(C);
2894 
2895  if (RNA_boolean_get(op->ptr, "all")) {
2897  }
2898  else if (RNA_boolean_get(op->ptr, "all_unlocked")) {
2900  }
2901  else {
2903  }
2904 
2909 
2910  return OPERATOR_FINISHED;
2911 }
2912 
2914 {
2915  /* identifiers */
2916  ot->name = "Remove Vertex Group";
2917  ot->idname = "OBJECT_OT_vertex_group_remove";
2918  ot->description = "Delete the active or all vertex groups from the active object";
2919 
2920  /* api callbacks */
2923 
2924  /* flags */
2925  /* redo operator will fail in this case because vertex groups aren't stored
2926  * in local edit mode stack and toggling "all" property will lead to
2927  * all groups deleted without way to restore them (see T29527, sergey) */
2928  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
2929 
2930  /* properties */
2931  PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
2933  prop = RNA_def_boolean(
2934  ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
2936 }
2937 
2940 /* -------------------------------------------------------------------- */
2945 {
2947  Object *ob = ED_object_context(C);
2948 
2952 
2953  return OPERATOR_FINISHED;
2954 }
2955 
2957 {
2958  /* identifiers */
2959  ot->name = "Assign to Vertex Group";
2960  ot->idname = "OBJECT_OT_vertex_group_assign";
2961  ot->description = "Assign the selected vertices to the active vertex group";
2962 
2963  /* api callbacks */
2966 
2967  /* flags */
2968  /* redo operator will fail in this case because vertex group assignment
2969  * isn't stored in local edit mode stack and toggling "new" property will
2970  * lead to creating plenty of new vertex groups (see T29527, sergey) */
2971  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
2972 }
2973 
2976 /* -------------------------------------------------------------------- */
2980 /* NOTE: just a wrapper around vertex_group_assign_exec(), except we add these to a new group */
2982 {
2983  /* create new group... */
2984  Object *ob = ED_object_context(C);
2986 
2987  /* assign selection to new group */
2988  return vertex_group_assign_exec(C, op);
2989 }
2990 
2992 {
2993  /* identifiers */
2994  ot->name = "Assign to New Group";
2995  ot->idname = "OBJECT_OT_vertex_group_assign_new";
2996  ot->description = "Assign the selected vertices to a new vertex group";
2997 
2998  /* api callbacks */
3001 
3002  /* flags */
3003  /* redo operator will fail in this case because vertex group assignment
3004  * isn't stored in local edit mode stack and toggling "new" property will
3005  * lead to creating plenty of new vertex groups (see T29527, sergey) */
3006  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
3007 }
3008 
3011 /* -------------------------------------------------------------------- */
3016 {
3017  const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
3018  const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
3019 
3020  Object *ob = ED_object_context(C);
3021 
3022  if (use_all_groups) {
3023  if (BKE_object_defgroup_clear_all(ob, true) == false) {
3024  return OPERATOR_CANCELLED;
3025  }
3026  }
3027  else {
3028  bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
3029 
3030  if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
3031  return OPERATOR_CANCELLED;
3032  }
3033  }
3034 
3037 
3038  return OPERATOR_FINISHED;
3039 }
3040 
3042 {
3043  PropertyRNA *prop;
3044  /* identifiers */
3045  ot->name = "Remove from Vertex Group";
3046  ot->idname = "OBJECT_OT_vertex_group_remove_from";
3047  ot->description = "Remove the selected vertices from active or all vertex group(s)";
3048 
3049  /* api callbacks */
3052 
3053  /* flags */
3054  /* redo operator will fail in this case because vertex groups assignment
3055  * isn't stored in local edit mode stack and toggling "all" property will lead to
3056  * removing vertices from all groups (see T29527, sergey) */
3057  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
3058 
3059  /* properties */
3060  prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
3062  prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Vertices", "Clear the active group");
3064 }
3065 
3068 /* -------------------------------------------------------------------- */
3073 {
3074  Object *ob = ED_object_context(C);
3075 
3076  if (!ob || ID_IS_LINKED(ob)) {
3077  return OPERATOR_CANCELLED;
3078  }
3079 
3080  vgroup_select_verts(ob, 1);
3083 
3084  return OPERATOR_FINISHED;
3085 }
3086 
3088 {
3089  /* identifiers */
3090  ot->name = "Select Vertex Group";
3091  ot->idname = "OBJECT_OT_vertex_group_select";
3092  ot->description = "Select all the vertices assigned to the active vertex group";
3093 
3094  /* api callbacks */
3097 
3098  /* flags */
3100 }
3101 
3104 /* -------------------------------------------------------------------- */
3109 {
3110  Object *ob = ED_object_context(C);
3111 
3112  vgroup_select_verts(ob, 0);
3115 
3116  return OPERATOR_FINISHED;
3117 }
3118 
3120 {
3121  /* identifiers */
3122  ot->name = "Deselect Vertex Group";
3123  ot->idname = "OBJECT_OT_vertex_group_deselect";
3124  ot->description = "Deselect all selected vertices assigned to the active vertex group";
3125 
3126  /* api callbacks */
3129 
3130  /* flags */
3132 }
3133 
3136 /* -------------------------------------------------------------------- */
3141 {
3142  Object *ob = ED_object_context(C);
3143 
3144  vgroup_duplicate(ob);
3149 
3150  return OPERATOR_FINISHED;
3151 }
3152 
3154 {
3155  /* identifiers */
3156  ot->name = "Copy Vertex Group";
3157  ot->idname = "OBJECT_OT_vertex_group_copy";
3158  ot->description = "Make a copy of the active vertex group";
3159 
3160  /* api callbacks */
3163 
3164  /* flags */
3166 }
3167 
3170 /* -------------------------------------------------------------------- */
3175 {
3176  Object *ob = ED_object_context(C);
3177 
3178  float offset = RNA_float_get(op->ptr, "offset");
3179  float gain = RNA_float_get(op->ptr, "gain");
3180  eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3181 
3182  int subset_count, vgroup_tot;
3183 
3184  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3185  ob, subset_type, &vgroup_tot, &subset_count);
3186  vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
3187  MEM_freeN((void *)vgroup_validmap);
3188 
3192 
3193  return OPERATOR_FINISHED;
3194 }
3195 
3197 {
3198  /* identifiers */
3199  ot->name = "Vertex Group Levels";
3200  ot->idname = "OBJECT_OT_vertex_group_levels";
3201  ot->description =
3202  "Add some offset and multiply with some gain the weights of the active vertex group";
3203 
3204  /* api callbacks */
3207 
3208  /* flags */
3210 
3212  RNA_def_float(
3213  ot->srna, "offset", 0.0f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.0f);
3214  RNA_def_float(
3215  ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.0f);
3216 }
3217 
3220 /* -------------------------------------------------------------------- */
3225 {
3226  Object *ob = ED_object_context(C);
3227  bool changed;
3228 
3229  changed = vgroup_normalize(ob);
3230 
3231  if (changed) {
3235 
3236  return OPERATOR_FINISHED;
3237  }
3238  return OPERATOR_CANCELLED;
3239 }
3240 
3242 {
3243  /* identifiers */
3244  ot->name = "Normalize Vertex Group";
3245  ot->idname = "OBJECT_OT_vertex_group_normalize";
3246  ot->description =
3247  "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
3248 
3249  /* api callbacks */
3252 
3253  /* flags */
3255 }
3256 
3259 /* -------------------------------------------------------------------- */
3264 {
3265  Object *ob = ED_object_context(C);
3266  bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
3267  eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3268  bool changed;
3269  int subset_count, vgroup_tot;
3270  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3271  ob, subset_type, &vgroup_tot, &subset_count);
3272 
3273  changed = vgroup_normalize_all(
3274  ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
3275  MEM_freeN((void *)vgroup_validmap);
3276 
3277  if (changed) {
3281 
3282  return OPERATOR_FINISHED;
3283  }
3284 
3285  /* allow to adjust settings */
3286  return OPERATOR_FINISHED;
3287 }
3288 
3290 {
3291  /* identifiers */
3292  ot->name = "Normalize All Vertex Groups";
3293  ot->idname = "OBJECT_OT_vertex_group_normalize_all";
3294  ot->description =
3295  "Normalize all weights of all vertex groups, "
3296  "so that for each vertex, the sum of all weights is 1.0";
3297 
3298  /* api callbacks */
3301 
3302  /* flags */
3304 
3307  "lock_active",
3308  true,
3309  "Lock Active",
3310  "Keep the values of the active group while normalizing others");
3311 }
3312 
3315 /* -------------------------------------------------------------------- */
3320 {
3323 
3324  float distToBe = RNA_float_get(op->ptr, "dist");
3325  float strength = RNA_float_get(op->ptr, "strength");
3326  float cp = RNA_float_get(op->ptr, "accuracy");
3327  ModifierData *md = ob->modifiers.first;
3328 
3329  while (md) {
3330  if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
3331  break;
3332  }
3333  md = md->next;
3334  }
3335 
3336  if (md && md->type == eModifierType_Mirror) {
3337  BKE_report(op->reports,
3339  "This operator does not support an active mirror modifier");
3340  return OPERATOR_CANCELLED;
3341  }
3342  vgroup_fix(C, scene, ob, distToBe, strength, cp);
3343 
3347 
3348  return OPERATOR_FINISHED;
3349 }
3350 
3352 {
3353  /* identifiers */
3354  ot->name = "Fix Vertex Group Deform";
3355  ot->idname = "OBJECT_OT_vertex_group_fix";
3356  ot->description =
3357  "Modify the position of selected vertices by changing only their respective "
3358  "groups' weights (this tool may be slow for many vertices)";
3359 
3360  /* api callbacks */
3363 
3364  /* flags */
3367  "dist",
3368  0.0f,
3369  -FLT_MAX,
3370  FLT_MAX,
3371  "Distance",
3372  "The distance to move to",
3373  -10.0f,
3374  10.0f);
3376  "strength",
3377  1.0f,
3378  -2.0f,
3379  FLT_MAX,
3380  "Strength",
3381  "The distance moved can be changed by this multiplier",
3382  -2.0f,
3383  2.0f);
3384  RNA_def_float(
3385  ot->srna,
3386  "accuracy",
3387  1.0f,
3388  0.05f,
3389  FLT_MAX,
3390  "Change Sensitivity",
3391  "Change the amount weights are altered with each iteration: lower values are slower",
3392  0.05f,
3393  1.0f);
3394 }
3395 
3398 /* -------------------------------------------------------------------- */
3403 {
3405 
3406  int action = RNA_enum_get(op->ptr, "action");
3407  int mask = RNA_enum_get(op->ptr, "mask");
3408 
3409  vgroup_lock_all(ob, action, mask);
3410 
3412 
3413  return OPERATOR_FINISHED;
3414 }
3415 
3417  struct wmOperatorType *UNUSED(op),
3418  struct PointerRNA *params)
3419 {
3420  int action = RNA_enum_get(params, "action");
3421  int mask = RNA_enum_get(params, "mask");
3422 
3423  const char *action_str, *target_str;
3424 
3425  switch (action) {
3426  case VGROUP_LOCK:
3427  action_str = "Lock";
3428  break;
3429  case VGROUP_UNLOCK:
3430  action_str = "Unlock";
3431  break;
3432  case VGROUP_TOGGLE:
3433  action_str = "Toggle locks of";
3434  break;
3435  case VGROUP_INVERT:
3436  action_str = "Invert locks of";
3437  break;
3438  default:
3439  return NULL;
3440  }
3441 
3442  switch (mask) {
3443  case VGROUP_MASK_ALL:
3444  target_str = "all";
3445  break;
3446  case VGROUP_MASK_SELECTED:
3447  target_str = "selected";
3448  break;
3450  target_str = "unselected";
3451  break;
3453  switch (action) {
3454  case VGROUP_INVERT:
3455  target_str = "selected";
3456  break;
3457  case VGROUP_LOCK:
3458  target_str = "selected and unlock unselected";
3459  break;
3460  case VGROUP_UNLOCK:
3461  target_str = "selected and lock unselected";
3462  break;
3463  default:
3464  target_str = "all and invert unselected";
3465  }
3466  break;
3467  default:
3468  return NULL;
3469  }
3470 
3471  return BLI_sprintfN("%s %s vertex groups of the active object", action_str, target_str);
3472 }
3473 
3475 {
3476  /* identifiers */
3477  ot->name = "Change the Lock On Vertex Groups";
3478  ot->idname = "OBJECT_OT_vertex_group_lock";
3479  ot->description = "Change the lock state of all or some vertex groups of active object";
3480 
3481  /* api callbacks */
3485 
3486  /* flags */
3488 
3489  RNA_def_enum(ot->srna,
3490  "action",
3492  VGROUP_TOGGLE,
3493  "Action",
3494  "Lock action to execute on vertex groups");
3495 
3496  RNA_def_enum(ot->srna,
3497  "mask",
3500  "Mask",
3501  "Apply the action based on vertex group selection");
3502 }
3503 
3506 /* -------------------------------------------------------------------- */
3511 {
3512  Object *ob = ED_object_context(C);
3513  bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
3514  bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
3515 
3516  eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3517 
3518  int subset_count, vgroup_tot;
3519 
3520  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3521  ob, subset_type, &vgroup_tot, &subset_count);
3522  vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
3523  MEM_freeN((void *)vgroup_validmap);
3524 
3528 
3529  return OPERATOR_FINISHED;
3530 }
3531 
3533 {
3534  /* identifiers */
3535  ot->name = "Invert Vertex Group";
3536  ot->idname = "OBJECT_OT_vertex_group_invert";
3537  ot->description = "Invert active vertex group's weights";
3538 
3539  /* api callbacks */
3542 
3543  /* flags */
3545 
3548  "auto_assign",
3549  true,
3550  "Add Weights",
3551  "Add vertices from groups that have zero weight before inverting");
3553  "auto_remove",
3554  true,
3555  "Remove Weights",
3556  "Remove vertices from groups that have zero weight after inverting");
3557 }
3558 
3561 /* -------------------------------------------------------------------- */
3566 {
3567  const float fac = RNA_float_get(op->ptr, "factor");
3568  const int repeat = RNA_int_get(op->ptr, "repeat");
3569  const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3570  const float fac_expand = RNA_float_get(op->ptr, "expand");
3571 
3572  uint objects_len;
3573  Object **objects = object_array_for_wpaint(C, &objects_len);
3574 
3575  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3576  Object *ob = objects[ob_index];
3577 
3578  int subset_count, vgroup_tot;
3579 
3580  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3581  ob, subset_type, &vgroup_tot, &subset_count);
3582 
3583  vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
3584  MEM_freeN((void *)vgroup_validmap);
3585 
3589  }
3590  MEM_freeN(objects);
3591 
3592  return OPERATOR_FINISHED;
3593 }
3594 
3596 {
3597  /* identifiers */
3598  ot->name = "Smooth Vertex Weights";
3599  ot->idname = "OBJECT_OT_vertex_group_smooth";
3600  ot->description = "Smooth weights for selected vertices";
3601 
3602  /* api callbacks */
3605 
3606  /* flags */
3608 
3610  RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
3611  RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
3612 
3614  "expand",
3615  0.0f,
3616  -1.0f,
3617  1.0,
3618  "Expand/Contract",
3619  "Expand/contract weights",
3620  -1.0f,
3621  1.0f);
3622 }
3623 
3626 /* -------------------------------------------------------------------- */
3631 {
3632  const float limit = RNA_float_get(op->ptr, "limit");
3633  const bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
3634  const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3635 
3636  uint objects_len;
3637  Object **objects = object_array_for_wpaint(C, &objects_len);
3638 
3639  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3640  Object *ob = objects[ob_index];
3641 
3642  int subset_count, vgroup_tot;
3643 
3644  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3645  ob, subset_type, &vgroup_tot, &subset_count);
3646 
3647  vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
3648  MEM_freeN((void *)vgroup_validmap);
3649 
3653  }
3654  MEM_freeN(objects);
3655 
3656  return OPERATOR_FINISHED;
3657 }
3658 
3660 {
3661  /* identifiers */
3662  ot->name = "Clean Vertex Group Weights";
3663  ot->idname = "OBJECT_OT_vertex_group_clean";
3664  ot->description = "Remove vertex group assignments which are not required";
3665 
3666  /* api callbacks */
3669 
3670  /* flags */
3672 
3675  "limit",
3676  0.0f,
3677  0.0f,
3678  1.0,
3679  "Limit",
3680  "Remove vertices which weight is below or equal to this limit",
3681  0.0f,
3682  0.99f);
3684  "keep_single",
3685  false,
3686  "Keep Single",
3687  "Keep verts assigned to at least one group when cleaning");
3688 }
3689 
3692 /* -------------------------------------------------------------------- */
3697 {
3698  Object *ob = ED_object_context(C);
3699 
3700  const int steps = RNA_int_get(op->ptr, "steps");
3701  eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3702 
3703  int subset_count, vgroup_tot;
3704 
3705  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3706  ob, subset_type, &vgroup_tot, &subset_count);
3707  vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
3708  MEM_freeN((void *)vgroup_validmap);
3709 
3713 
3714  return OPERATOR_FINISHED;
3715 }
3716 
3718 {
3719  /* identifiers */
3720  ot->name = "Quantize Vertex Weights";
3721  ot->idname = "OBJECT_OT_vertex_group_quantize";
3722  ot->description = "Set weights to a fixed number of steps";
3723 
3724  /* api callbacks */
3727 
3728  /* flags */
3730 
3732  RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
3733 }
3734 
3737 /* -------------------------------------------------------------------- */
3742 {
3743  const int limit = RNA_int_get(op->ptr, "limit");
3744  const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
3745  int remove_multi_count = 0;
3746 
3747  uint objects_len;
3748  Object **objects = object_array_for_wpaint(C, &objects_len);
3749  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
3750  Object *ob = objects[ob_index];
3751 
3752  int subset_count, vgroup_tot;
3753  const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
3754  ob, subset_type, &vgroup_tot, &subset_count);
3755  const int remove_count = vgroup_limit_total_subset(
3756  ob, vgroup_validmap, vgroup_tot, subset_count, limit);
3757  MEM_freeN((void *)vgroup_validmap);
3758 
3759  if (remove_count != 0) {
3763  }
3764  remove_multi_count += remove_count;
3765  }
3766  MEM_freeN(objects);
3767 
3768  if (remove_multi_count) {
3769  BKE_reportf(op->reports,
3770  remove_multi_count ? RPT_INFO : RPT_WARNING,
3771  "%d vertex weights limited",
3772  remove_multi_count);
3773 
3774  return OPERATOR_FINISHED;
3775  }
3776 
3777  /* note, would normally return canceled, except we want the redo
3778  * UI to show up for users to change */
3779  return OPERATOR_FINISHED;
3780 }
3781 
3783 {
3784  /* identifiers */
3785  ot->name = "Limit Number of Weights per Vertex";
3786  ot->idname = "OBJECT_OT_vertex_group_limit_total";
3787  ot->description =
3788  "Limit deform weights associated with a vertex to a specified number by removing lowest "
3789  "weights";
3790 
3791  /* api callbacks */
3794 
3795  /* flags */
3797 
3799  RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
3800 }
3801 
3804 /* -------------------------------------------------------------------- */
3809 {
3810  Object *ob = ED_object_context(C);
3811  int totmirr = 0, totfail = 0;
3812 
3813  ED_vgroup_mirror(ob,
3814  RNA_boolean_get(op->ptr, "mirror_weights"),
3815  RNA_boolean_get(op->ptr, "flip_group_names"),
3816  RNA_boolean_get(op->ptr, "all_groups"),
3817  RNA_boolean_get(op->ptr, "use_topology"),
3818  &totmirr,
3819  &totfail);
3820 
3821  ED_mesh_report_mirror(op, totmirr, totfail);
3822 
3827 
3828  return OPERATOR_FINISHED;
3829 }
3830 
3832 {
3833  /* identifiers */
3834  ot->name = "Mirror Vertex Group";
3835  ot->idname = "OBJECT_OT_vertex_group_mirror";
3836  ot->description =
3837  "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
3838  "flipping when both sides are selected otherwise copy from unselected";
3839 
3840  /* api callbacks */
3843 
3844  /* flags */
3846 
3847  /* properties */
3848  RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
3850  ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
3851  RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
3853  ot->srna,
3854  "use_topology",
3855  0,
3856  "Topology Mirror",
3857  "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
3858 }
3859 
3862 /* -------------------------------------------------------------------- */
3867 {
3869  Object *ob_active = ED_object_context(C);
3870  int retval = OPERATOR_CANCELLED;
3871 
3872  FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
3873  if (ob_iter->type == ob_active->type) {
3874  if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
3875  BLI_freelistN(&ob_iter->defbase);
3876  BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
3877  ob_iter->actdef = ob_active->actdef;
3878 
3879  DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
3881  WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
3882 
3883  retval = OPERATOR_FINISHED;
3884  }
3885  }
3886  }
3888 
3889  return retval;
3890 }
3891 
3893 {
3894  /* identifiers */
3895  ot->name = "Copy Vertex Groups to Linked";
3896  ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
3897  ot->description =
3898  "Replace vertex groups of all users of the same geometry data by vertex groups of active "
3899  "object";
3900 
3901  /* api callbacks */
3904 
3905  /* flags */
3907 }
3908 
3911 /* -------------------------------------------------------------------- */
3916 {
3917  Object *obact = ED_object_context(C);
3918  int changed_tot = 0;
3919  int fail = 0;
3920 
3921  CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
3922  if (obact != ob) {
3923  if (ED_vgroup_array_copy(ob, obact)) {
3927  changed_tot++;
3928  }
3929  else {
3930  fail++;
3931  }
3932  }
3933  }
3934  CTX_DATA_END;
3935 
3936  if ((changed_tot == 0 && fail == 0) || fail) {
3937  BKE_reportf(op->reports,
3938  RPT_ERROR,
3939  "Copy vertex groups to selected: %d done, %d failed (object data must have "
3940  "matching indices)",
3941  changed_tot,
3942  fail);
3943  }
3944 
3945  return OPERATOR_FINISHED;
3946 }
3947 
3949 {
3950  /* identifiers */
3951  ot->name = "Copy Vertex Group to Selected";
3952  ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
3953  ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
3954 
3955  /* api callbacks */
3958 
3959  /* flags */
3961 }
3962 
3965 /* -------------------------------------------------------------------- */
3970 {
3971  Object *ob = ED_object_context(C);
3972  int nr = RNA_enum_get(op->ptr, "group");
3973 
3974  BLI_assert(nr + 1 >= 0);
3975  ob->actdef = nr + 1;
3976 
3979 
3980  return OPERATOR_FINISHED;
3981 }
3982 
3984  PointerRNA *UNUSED(ptr),
3985  PropertyRNA *UNUSED(prop),
3986  bool *r_free)
3987 {
3988  if (C == NULL) {
3989  return DummyRNA_NULL_items;
3990  }
3991 
3992  Object *ob = ED_object_context(C);
3993  EnumPropertyItem tmp = {0, "", 0, "", ""};
3994  EnumPropertyItem *item = NULL;
3995  bDeformGroup *def;
3996  int a, totitem = 0;
3997 
3998  if (!ob) {
3999  return DummyRNA_NULL_items;
4000  }
4001 
4002  for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
4003  tmp.value = a;
4004  tmp.icon = ICON_GROUP_VERTEX;
4005  tmp.identifier = def->name;
4006  tmp.name = def->name;
4007  RNA_enum_item_add(&item, &totitem, &tmp);
4008  }
4009 
4010  RNA_enum_item_end(&item, &totitem);
4011  *r_free = true;
4012 
4013  return item;
4014 }
4015 
4017 {
4018  PropertyRNA *prop;
4019 
4020  /* identifiers */
4021  ot->name = "Set Active Vertex Group";
4022  ot->idname = "OBJECT_OT_vertex_group_set_active";
4023  ot->description = "Set the active vertex group";
4024 
4025  /* api callbacks */
4029 
4030  /* flags */
4032 
4033  /* properties */
4034  prop = RNA_def_enum(
4035  ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
4038  ot->prop = prop;
4039 }
4040 
4043 /* -------------------------------------------------------------------- */
4047 /* creates the name_array parameter for vgroup_do_remap, call this before fiddling
4048  * with the order of vgroups then call vgroup_do_remap after */
4049 static char *vgroup_init_remap(Object *ob)
4050 {
4051  bDeformGroup *def;
4052  int defbase_tot = BLI_listbase_count(&ob->defbase);
4053  char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
4054  char *name;
4055 
4056  name = name_array;
4057  for (def = ob->defbase.first; def; def = def->next) {
4058  BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
4059  name += MAX_VGROUP_NAME;
4060  }
4061 
4062  return name_array;
4063 }
4064 
4065 static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
4066 {
4067  MDeformVert *dvert = NULL;
4068  bDeformGroup *def;
4069  int defbase_tot = BLI_listbase_count(&ob->defbase);
4070 
4071  /* needs a dummy index at the start*/
4072  int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
4073  int *sort_map = sort_map_update + 1;
4074 
4075  const char *name;
4076  int i;
4077 
4078  name = name_array;
4079  for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
4080  sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
4081  name += MAX_VGROUP_NAME;
4082 
4083  BLI_assert(sort_map[i] != -1);
4084  }
4085 
4086  if (ob->mode == OB_MODE_EDIT) {
4087  if (ob->type == OB_MESH) {
4089  const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
4090 
4091  if (cd_dvert_offset != -1) {
4092  BMIter iter;
4093  BMVert *eve;
4094 
4095  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
4096  dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
4097  if (dvert->totweight) {
4098  BKE_defvert_remap(dvert, sort_map, defbase_tot);
4099  }
4100  }
4101  }
4102  }
4103  else {
4104  BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
4105  MEM_freeN(sort_map_update);
4106  return OPERATOR_CANCELLED;
4107  }
4108  }
4109  else {
4110  int dvert_tot = 0;
4111 
4112  BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
4113 
4114  /*create as necessary*/
4115  if (dvert) {
4116  while (dvert_tot--) {
4117  if (dvert->totweight) {
4118  BKE_defvert_remap(dvert, sort_map, defbase_tot);
4119  }
4120  dvert++;
4121  }
4122  }
4123  }
4124 
4125  /* update users */
4126  for (i = 0; i < defbase_tot; i++) {
4127  sort_map[i]++;
4128  }
4129 
4130  sort_map_update[0] = 0;
4131  BKE_object_defgroup_remap_update_users(ob, sort_map_update);
4132 
4133  BLI_assert(sort_map_update[ob->actdef] >= 0);
4134  ob->actdef = sort_map_update[ob->actdef];
4135 
4136  MEM_freeN(sort_map_update);
4137 
4138  return OPERATOR_FINISHED;
4139 }
4140 
4141 static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
4142 {
4143  const bDeformGroup *def_a = def_a_ptr;
4144  const bDeformGroup *def_b = def_b_ptr;
4145 
4146  return BLI_strcasecmp_natural(def_a->name, def_b->name);
4147 }
4148 
4153 static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
4154 {
4155  if (bonebase == NULL) {
4157  if (armobj != NULL) {
4158  bArmature *armature = armobj->data;
4159  bonebase = &armature->bonebase;
4160  }
4161  }
4162 
4163  if (bonebase != NULL) {
4164  Bone *bone;
4165  for (bone = bonebase->last; bone; bone = bone->prev) {
4168 
4169  if (dg != NULL) {
4170  BLI_remlink(&ob->defbase, dg);
4171  BLI_addhead(&ob->defbase, dg);
4172  }
4173  }
4174  }
4175 }
4176 
4177 enum {
4180 };
4181 
4183 {
4184  Object *ob = ED_object_context(C);
4185  char *name_array;
4186  int ret;
4187  int sort_type = RNA_enum_get(op->ptr, "sort_type");
4188 
4189  /*init remapping*/
4190  name_array = vgroup_init_remap(ob);
4191 
4192  /*sort vgroup names*/
4193  switch (sort_type) {
4194  case SORT_TYPE_NAME:
4196  break;
4199  break;
4200  }
4201 
4202  /*remap vgroup data to map to correct names*/
4203  ret = vgroup_do_remap(ob, name_array, op);
4204 
4205  if (ret != OPERATOR_CANCELLED) {
4208  }
4209 
4210  if (name_array) {
4211  MEM_freeN(name_array);
4212  }
4213 
4214  return ret;
4215 }
4216 
4218 {
4219  static const EnumPropertyItem vgroup_sort_type[] = {
4220  {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
4221  {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
4222  {0, NULL, 0, NULL, NULL},
4223  };
4224 
4225  ot->name = "Sort Vertex Groups";
4226  ot->idname = "OBJECT_OT_vertex_group_sort";
4227  ot->description = "Sort vertex groups";
4228 
4229  /* api callbacks */
4232 
4233  /* flags */
4235 
4236  RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort Type", "Sort type");
4237 }
4238 
4241 /* -------------------------------------------------------------------- */
4246 {
4247  Object *ob = ED_object_context(C);
4248  bDeformGroup *def;
4249  char *name_array;
4250  int dir = RNA_enum_get(op->ptr, "direction");
4251  int ret = OPERATOR_FINISHED;
4252 
4253  def = BLI_findlink(&ob->defbase, ob->actdef - 1);
4254  if (!def) {
4255  return OPERATOR_CANCELLED;
4256  }
4257 
4258  name_array = vgroup_init_remap(ob);
4259 
4260  if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
4261  ret = vgroup_do_remap(ob, name_array, op);
4262 
4263  if (ret != OPERATOR_CANCELLED) {
4266  }
4267  }
4268 
4269  if (name_array) {
4270  MEM_freeN(name_array);
4271  }
4272 
4273  return ret;
4274 }
4275 
4277 {
4278  static const EnumPropertyItem vgroup_slot_move[] = {
4279  {-1, "UP", 0, "Up", ""},
4280  {1, "DOWN", 0, "Down", ""},
4281  {0, NULL, 0, NULL, NULL},
4282  };
4283 
4284  /* identifiers */
4285  ot->name = "Move Vertex Group";
4286  ot->idname = "OBJECT_OT_vertex_group_move";
4287  ot->description = "Move the active vertex group up/down in the list";
4288 
4289  /* api callbacks */
4292 
4293  /* flags */
4295 
4296  RNA_def_enum(ot->srna,
4297  "direction",
4298  vgroup_slot_move,
4299  0,
4300  "Direction",
4301  "Direction to move the active vertex group towards");
4302 }
4303 
4306 /* -------------------------------------------------------------------- */
4311 {
4312  MDeformVert *dvert_act;
4313 
4314  Mesh *me = ob->data;
4315  BMEditMesh *em = me->edit_mesh;
4316  float weight_act;
4317  int i;
4318 
4319  if (em) {
4320  const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
4321  BMIter iter;
4322  BMVert *eve, *eve_act;
4323 
4324  dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
4325  if (dvert_act == NULL) {
4326  return;
4327  }
4328  weight_act = BKE_defvert_find_weight(dvert_act, def_nr);
4329 
4330  BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
4331  if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
4332  MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
4334  if (dw) {
4335  dw->weight = weight_act;
4336 
4337  if (me->symmetry & ME_SYMMETRY_X) {
4338  ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
4339  }
4340  }
4341  }
4342  }
4343 
4344  if (me->symmetry & ME_SYMMETRY_X) {
4345  ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
4346  }
4347  }
4348  else {
4349  MDeformVert *dv;
4350  int v_act;
4351 
4352  dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
4353  if (dvert_act == NULL) {
4354  return;
4355  }
4356  weight_act = BKE_defvert_find_weight(dvert_act, def_nr);
4357 
4358  dv = me->dvert;
4359  for (i = 0; i < me->totvert; i++, dv++) {
4360  if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
4362  if (dw) {
4363  dw->weight = weight_act;
4364  if (me->symmetry & ME_SYMMETRY_X) {
4366  }
4367  }
4368  }
4369  }
4370 
4371  if (me->symmetry & ME_SYMMETRY_X) {
4372  ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
4373  }
4374  }
4375 }
4376 
4378 {
4379  bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
4380 
4381  if (!dg) {
4382  BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
4383  return false;
4384  }
4385 
4386  if (dg->flag & DG_LOCK_WEIGHT) {
4387  BKE_report(op->reports, RPT_ERROR, "Vertex group is locked");
4388  return false;
4389  }
4390 
4391  return true;
4392 }
4393 
4395 {
4396  Object *ob = ED_object_context(C);
4397  const int def_nr = RNA_int_get(op->ptr, "weight_group");
4398 
4399  if (!check_vertex_group_accessible(op, ob, def_nr)) {
4400  return OPERATOR_CANCELLED;
4401  }
4402 
4404 
4407 
4408  return OPERATOR_FINISHED;
4409 }
4410 
4412 {
4413  PropertyRNA *prop;
4414 
4415  ot->name = "Paste Weight to Selected";
4416  ot->idname = "OBJECT_OT_vertex_weight_paste";
4417  ot->description =
4418  "Copy this group's weight to other selected vertices (disabled if vertex group is locked)";
4419 
4420  /* api callbacks */
4423 
4424  /* flags */
4426 
4427  prop = RNA_def_int(ot->srna,
4428  "weight_group",
4429  -1,
4430  -1,
4431  INT_MAX,
4432  "Weight Index",
4433  "Index of source weight in active vertex group",
4434  -1,
4435  INT_MAX);
4437 }
4438 
4441 /* -------------------------------------------------------------------- */
4446 {
4447  Object *ob = ED_object_context(C);
4448  const int def_nr = RNA_int_get(op->ptr, "weight_group");
4449 
4450  if (!check_vertex_group_accessible(op, ob, def_nr)) {
4451  return OPERATOR_CANCELLED;
4452  }
4453 
4455 
4458 
4459  return OPERATOR_FINISHED;
4460 }
4461 
4463 {
4464  PropertyRNA *prop;
4465 
4466  ot->name = "Delete Weight";
4467  ot->idname = "OBJECT_OT_vertex_weight_delete";
4468  ot->description = "Delete this weight from the vertex (disabled if vertex group is locked)";
4469 
4470  /* api callbacks */
4473 
4474  /* flags */
4476 
4477  prop = RNA_def_int(ot->srna,
4478  "weight_group",
4479  -1,
4480  -1,
4481  INT_MAX,
4482  "Weight Index",
4483  "Index of source weight in active vertex group",
4484  -1,
4485  INT_MAX);
4487 }
4488 
4491 /* -------------------------------------------------------------------- */
4496 {
4497  Object *ob = ED_object_context(C);
4498  const int wg_index = RNA_int_get(op->ptr, "weight_group");
4499 
4500  if (wg_index != -1) {
4501  ob->actdef = wg_index + 1;
4504  }
4505 
4506  return OPERATOR_FINISHED;
4507 }
4508 
4510 {
4511  PropertyRNA *prop;
4512 
4513  ot->name = "Set Active Group";
4514  ot->idname = "OBJECT_OT_vertex_weight_set_active";
4515  ot->description = "Set as active vertex group";
4516 
4517  /* api callbacks */
4520 
4521  /* flags */
4523 
4524  prop = RNA_def_int(ot->srna,
4525  "weight_group",
4526  -1,
4527  -1,
4528  INT_MAX,
4529  "Weight Index",
4530  "Index of source weight in active vertex group",
4531  -1,
4532  INT_MAX);
4534 }
4535 
4538 /* -------------------------------------------------------------------- */
4543 {
4544  Object *ob = ED_object_context(C);
4546  eVGroupSelect subset_type = ts->vgroupsubset;
4547  bool changed;
4548 
4549  changed = vgroup_normalize_active_vertex(ob, subset_type);
4550 
4551  if (changed) {
4554 
4555  return OPERATOR_FINISHED;
4556  }
4557  return OPERATOR_CANCELLED;
4558 }
4559 
4561 {
4562 
4563  ot->name = "Normalize Active";
4564  ot->idname = "OBJECT_OT_vertex_weight_normalize_active_vertex";
4565  ot->description = "Normalize active vertex's weights";
4566 
4567  /* api callbacks */
4570 
4571  /* flags */
4573 }
4574 
4577 /* -------------------------------------------------------------------- */
4582 {
4583  Object *ob = ED_object_context(C);
4585  eVGroupSelect subset_type = ts->vgroupsubset;
4586 
4587  vgroup_copy_active_to_sel(ob, subset_type);
4588 
4591 
4592  return OPERATOR_FINISHED;
4593 }
4594 
4596 {
4597 
4598  ot->name = "Copy Active";
4599  ot->idname = "OBJECT_OT_vertex_weight_copy";
4600  ot->description = "Copy weights from active to selected";
4601 
4602  /* api callbacks */
4605 
4606  /* flags */
4608 }
4609 
typedef float(TangentPoint)[2]
#define FOREACH_SCENE_OBJECT_END
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg)
Definition: context.c:1006
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1208
#define CTX_DATA_END
Definition: BKE_context.h:260
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.c:1919
int CustomData_get_offset(const struct CustomData *data, int type)
support for deformation groups and hooks.
void BKE_defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot, const bool *lock_flags, const int defbase_tot)
Definition: deform.c:393
void BKE_defvert_sync_mapped(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const int *flip_map, const int flip_map_len, const bool use_ensure)
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
void BKE_defvert_normalize_subset(struct MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot)
Definition: deform.c:267
void BKE_defvert_copy_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool *vgroup_subset, const int vgroup_tot)
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, const int defgroup)
Definition: deform.c:688
int BKE_object_defgroup_flip_index(const struct Object *ob, int index, const bool use_default)
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup)
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
void BKE_defvert_copy_index(struct MDeformVert *dvert_dst, const int defgroup_dst, const struct MDeformVert *dvert_src, const int defgroup_src)
void BKE_defvert_mirror_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool *vgroup_subset, const int vgroup_tot, const int *flip_map, const int flip_map_len)
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob)
Definition: deform.c:620
int * BKE_object_defgroup_flip_map(const struct Object *ob, int *flip_map_len, const bool use_default)
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw)
Definition: deform.c:754
void BKE_defvert_remap(struct MDeformVert *dvert, const int *map, const int map_len)
Definition: deform.c:252
void BKE_defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src)
void BKE_defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len)
Definition: deform.c:448
int * BKE_object_defgroup_flip_map_single(const struct Object *ob, int *flip_map_len, const bool use_default, int defgroup)
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
void BKE_defvert_add_index_notest(struct MDeformVert *dv, int defgroup, const float weight)
Definition: deform.c:726
void BKE_defvert_normalize_lock_single(struct MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot, const uint def_nr_lock)
Definition: deform.c:336
struct bDeformGroup * BKE_defgroup_duplicate(const struct bDeformGroup *ingroup)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
struct BPoint * BKE_lattice_active_point_get(struct Lattice *lt)
Definition: lattice.c:606
int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w)
Definition: lattice.c:214
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge)
struct Mesh * mesh_get_eval_deform(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
struct Object * BKE_modifiers_is_deformed_by_armature(struct Object *ob)
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.c:2487
bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob)
bool BKE_object_is_in_editmode_vgroup(const struct Object *ob)
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.c:1719
Functions for dealing with objects and deform verts, used by painting and tools.
struct MDeformVert * BKE_object_defgroup_data_create(struct ID *id)
void BKE_object_defgroup_subset_to_index_array(const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map)
bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot)
void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup)
bool * BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot)
bool BKE_object_defgroup_clear(struct Object *ob, struct bDeformGroup *dg, const bool use_selection)
void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
void BKE_object_defgroup_remap_update_users(struct Object *ob, const int *map)
Definition: object_deform.c:72
void BKE_object_defgroup_mirror_selection(struct Object *ob, int defbase_tot, const bool *selection, bool *dg_flags_sel, int *r_dg_flags_sel_tot)
struct bDeformGroup * BKE_object_defgroup_add(struct Object *ob)
bool * BKE_object_defgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection)
bool * BKE_object_defgroup_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
void BKE_object_defgroup_remove_all(struct Object *ob)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
A (mainly) macro array library.
#define BLI_array_append(arr, item)
Definition: BLI_array.h:104
#define BLI_array_reserve(arr, num)
Definition: BLI_array.h:81
#define BLI_array_declare(arr)
Definition: BLI_array.h:62
#define BLI_array_len(arr)
Definition: BLI_array.h:74
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void void void bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL()
Definition: listbase.c:475
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE int signum_i(float a)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:243
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:412
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:766
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED_FUNCTION(x)
#define SWAP(type, a, b)
#define UNUSED(x)
#define IN_RANGE_INCL(a, b, c)
#define LIKELY(x)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_INIT(stack, tot)
#define STACK_SIZE(stack)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_LT
Definition: DNA_ID_enums.h:66
@ CD_MDEFORMVERT
#define LT_ACTBP_NONE
@ ME_SYMMETRY_X
#define ME_USING_MIRROR_X_VERTEX_GROUPS(_me)
@ ME_EDIT_PAINT_VERT_SEL
@ ME_EDIT_PAINT_FACE_SEL
@ ME_EDIT_MIRROR_TOPO
@ ME_HIDE
@ ME_VERT_TMP_TAG
@ eModifierMode_Realtime
@ eModifierType_Mirror
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
#define MAX_VGROUP_NAME
#define OB_TYPE_SUPPORT_VGROUP(_type)
#define DG_LOCK_WEIGHT
@ OB_LATTICE
@ OB_MESH
#define WT_VGROUP_MASK_ALL
eVGroupSelect
@ WT_VGROUP_BONE_SELECT
@ WT_VGROUP_ALL
@ WT_VGROUP_ACTIVE
@ WT_VGROUP_BONE_DEFORM
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ RPT_ERROR_INVALID_CONTEXT
struct MDeformVert * ED_mesh_active_dvert_get_ob(struct Object *ob, int *r_index)
Definition: meshtools.c:1499
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology)
Definition: meshtools.c:932
#define WEIGHT_REPLACE
Definition: ED_mesh.h:345
struct BMVert * editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index, const bool use_topology)
Definition: meshtools.c:996
struct MDeformVert * ED_mesh_active_dvert_get_em(struct Object *ob, struct BMVert **r_eve)
Definition: meshtools.c:1474
void paintvert_flush_flags(struct Object *ob)
Definition: editface.c:443
void EDBM_select_flush(struct BMEditMesh *em)
struct BMVert * EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v)
void EDBM_verts_mirror_cache_end(struct BMEditMesh *em)
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail)
Definition: mesh_data.c:1355
#define WEIGHT_ADD
Definition: ED_mesh.h:346
struct MDeformVert * ED_mesh_active_dvert_get_only(struct Object *ob)
Definition: meshtools.c:1512
#define WEIGHT_SUBTRACT
Definition: ED_mesh.h:347
int ED_mesh_mirror_get_vert(struct Object *ob, int index)
Definition: meshtools.c:1014
void EDBM_deselect_flush(struct BMEditMesh *em)
void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const int axis, const bool use_self, const bool use_select, const bool respecthide, const bool use_topology)
struct Object * ED_object_context(const struct bContext *C)
Object ** ED_object_array_in_mode_or_selected(struct bContext *C, bool(*filter_fn)(struct Object *ob, void *user_data), void *filter_user_data, uint *r_objects_len)
bool ED_operator_object_active_local_editable_ex(struct bContext *C, const Object *ob)
Definition: screen_ops.c:373
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Group RGB to Bright Vector Camera CLAMP
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
#define ND_DRAW
Definition: WM_types.h:362
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define ND_VERTEX_GROUP
Definition: WM_types.h:409
#define ND_SELECT
Definition: WM_types.h:407
#define NC_OBJECT
Definition: WM_types.h:280
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:894
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
Select Vert.
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
#define SELECT
Scene scene
const Depsgraph * depsgraph
void * user_data
static float verts[][3]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
#define GS(x)
Definition: iris.c:241
#define floorf(x)
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
static double epsilon
static int vertex_group_levels_exec(bContext *C, wmOperator *op)
void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot, const bool *vgroup_validmap, const int vgroup_tot, const float epsilon, const bool keep_single)
static bool vertex_group_poll_ex(bContext *C, Object *ob)
static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
static int vertex_group_assign_new_exec(bContext *C, wmOperator *op)
static void getVerticalAndHorizontalChange(const float norm[3], float d, const float coord[3], const float start[3], float distToStart, float *end, float(*changes)[2], float *dists, int index)
void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot)
static int set_active_group_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem vgroup_lock_actions[]
void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot)
static bool vertex_group_vert_select_mesh_poll(bContext *C)
float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
void ED_vgroup_data_clamp_range(ID *id, const int total)
void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
static void vgroup_assign_verts(Object *ob, const float weight)
static const EnumPropertyItem vgroup_lock_mask[]
void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot)
static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot)
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob, Mesh *me, int index, const float norm[3], const float coord[3], float d, float distToBe, float strength, float cp)
#define IS_BM_VERT_READ(v)
void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
static bool vertex_group_mesh_vert_poll(bContext *C)
void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
@ VGROUP_LOCK
@ VGROUP_TOGGLE
@ VGROUP_INVERT
@ VGROUP_UNLOCK
static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob)
static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr, const char sel, const char sel_mirr, const int *flip_map, const int flip_map_len, const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups, const int act_vgroup)
static void vgroup_fix(const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp)
static void vgroup_remove_weight(Object *ob, const int def_nr)
static Lattice * vgroup_edit_lattice(Object *ob)
static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr)
static bool vertex_group_poll(bContext *C)
void ED_vgroup_mirror(Object *ob, const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups, const bool use_topology, int *r_totmirr, int *r_totfail)
void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
void ED_vgroup_parray_mirror_sync(Object *ob, MDeformVert **dvert_array, const int dvert_tot, const bool *vgroup_validmap, const int vgroup_tot)
void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot)
static int vgroup_limit_total_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int subset_count, const int max_weights)
static bool object_array_for_wpaint_filter(Object *ob, void *user_data)
Definition: object_vgroup.c:86
#define VGROUP_MIRR_OP
void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
static int vertex_weight_set_active_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
const EnumPropertyItem * ED_object_vgroup_selection_itemf_helper(const bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free, const uint selection_mask)
static bool vertex_group_mesh_poll_ex(bContext *C, Object *ob)
void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
static void getSingleCoordinate(MVert *points, int count, float coord[3])
static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
static void vgroup_lock_all(Object *ob, int action, int mask)
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
#define IS_ME_VERT_READ(v)
void ED_vgroup_parray_to_weight_array(const MDeformVert **dvert_array, const int dvert_tot, float *dvert_weights, const int def_nr)
static bool * vgroup_selected_get(Object *ob)
static bool UNUSED_FUNCTION() vertex_group_poll_edit(bContext *C)
void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
static int vertex_weight_delete_exec(bContext *C, wmOperator *op)
static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
static const EnumPropertyItem * rna_vertex_group_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count), const float epsilon, const bool keep_single)
void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot)
static bool vertex_group_mesh_with_dvert_poll(bContext *C)
static int vertex_group_remove_exec(bContext *C, wmOperator *op)
static void ED_vgroup_nr_vert_add(Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode)
static int vertex_group_fix_exec(bContext *C, wmOperator *op)
static char * vertex_group_lock_description(struct bContext *UNUSED(C), struct wmOperatorType *UNUSED(op), struct PointerRNA *params)
#define IS_ME_VERT_WRITE(v)
static const EnumPropertyItem * rna_vertex_group_with_single_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
static void mesh_defvert_mirror_update_internal(Object *ob, MDeformVert *dvert_dst, MDeformVert *dvert_src, const int def_nr)
static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
#define IS_BM_VERT_WRITE(v)
void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
static char * vgroup_init_remap(Object *ob)
void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
static bool vertex_group_vert_select_poll(bContext *C)
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
static void vgroup_select_verts(Object *ob, int select)
bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel)
static void vgroup_quantize_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count), const int steps)
static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
static bool vertex_group_vert_select_unlocked_poll(bContext *C)
void ED_vgroup_vert_active_mirror(Object *ob, int def_nr)
static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
bool ED_vgroup_sync_from_pose(Object *ob)
static const EnumPropertyItem WT_vertex_group_select_item[]
static void vgroup_delete_active(Object *ob)
static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
static bool vgroup_normalize_all(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int subset_count, const bool lock_active, ReportList *reports)
@ SORT_TYPE_NAME
@ SORT_TYPE_BONEHIERARCHY
static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array, const int dvert_tot, const float *dvert_weights, const int def_nr, const bool remove_zero)
static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot)
static int vertex_group_sort_exec(bContext *C, wmOperator *op)
static Object ** object_array_for_wpaint(bContext *C, uint *r_objects_len)
Definition: object_vgroup.c:95
@ VGROUP_MASK_UNSELECTED
@ VGROUP_MASK_INVERT_UNSELECTED
@ VGROUP_MASK_SELECTED
@ VGROUP_MASK_ALL
static bool vertex_group_supported_poll(bContext *C)
static int * getSurroundingVerts(Mesh *me, int vert, int *count)
static void ED_mesh_defvert_mirror_update_em(Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset)
void ED_vgroup_select_by_name(Object *ob, const char *name)
static bool vertex_group_vert_poll_ex(bContext *C, const bool needs_select, const short ob_type_flag)
void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot)
static int vgroup_move_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem * vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
static bool vertex_group_use_vert_sel(Object *ob)
void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
#define WEIGHT_ACCUMULATE
static int vertex_group_lock_exec(bContext *C, wmOperator *op)
static int vertex_weight_paste_exec(bContext *C, wmOperator *op)
static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count), const float offset, const float gain)
static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot)
static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
static void vgroup_invert_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
static void vgroup_duplicate(Object *ob)
void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
static bool vgroup_normalize(Object *ob)
static void vgroup_smooth_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int subset_count, const float fac, const int repeat, const float fac_expand)
return ret
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4470
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4416
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3819
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
Definition: rna_define.c:4455
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:40
static const int steps
Definition: sky_nishita.cpp:28
struct BMesh * bm
Definition: BKE_editmesh.h:52
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
CustomData vdata
Definition: bmesh_class.h:337
uint8_t f1
char name[64]
ListBase childbase
struct Bone * prev
struct Lattice * latt
const char * identifier
Definition: RNA_types.h:446
const char * name
Definition: RNA_types.h:450
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
struct MDeformVert * dvert
struct EditLatt * editlatt
struct BPoint * def
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct MDeformWeight * dw
unsigned int def_nr
unsigned int v
float co[3]
struct MEdge * medge
struct BMEditMesh * edit_mesh
char symmetry
struct MVert * mvert
struct MDeformVert * dvert
int totedge
char editflag
int totvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct ModifierData * next
ListBase defbase
ListBase modifiers
unsigned short actdef
void * data
ListBase bonebase
struct bDeformGroup * next
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
char *(* get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:799
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982