Blender  V2.93
paint_vertex_weight_ops.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 
21 #include "MEM_guardedalloc.h"
22 
23 #include "BLI_bitmap.h"
24 #include "BLI_blenlib.h"
25 #include "BLI_math.h"
26 
27 #include "DNA_brush_types.h"
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_define.h"
35 #include "RNA_enum_types.h"
36 
37 #include "BKE_brush.h"
38 #include "BKE_colortools.h"
39 #include "BKE_context.h"
40 #include "BKE_deform.h"
41 #include "BKE_mesh.h"
42 #include "BKE_mesh_iterators.h"
43 #include "BKE_mesh_runtime.h"
44 #include "BKE_modifier.h"
45 #include "BKE_object_deform.h"
46 #include "BKE_paint.h"
47 #include "BKE_report.h"
48 
49 #include "DEG_depsgraph.h"
50 #include "DEG_depsgraph_query.h"
51 
52 #include "WM_api.h"
53 #include "WM_types.h"
54 
55 #include "ED_armature.h"
56 #include "ED_mesh.h"
57 #include "ED_screen.h"
58 #include "ED_view3d.h"
59 
60 #include "paint_intern.h" /* own include */
61 
62 /* -------------------------------------------------------------------- */
68 struct WPaintPrev {
69  /* previous vertex weights */
71  /* allocation size of prev buffers */
72  int tot;
73 };
74 
75 static void wpaint_prev_init(struct WPaintPrev *wpp)
76 {
77  wpp->wpaint_prev = NULL;
78  wpp->tot = 0;
79 }
80 
81 static void wpaint_prev_create(struct WPaintPrev *wpp, MDeformVert *dverts, int dcount)
82 {
83  wpaint_prev_init(wpp);
84 
85  if (dverts && dcount) {
86  wpp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
87  wpp->tot = dcount;
88  BKE_defvert_array_copy(wpp->wpaint_prev, dverts, dcount);
89  }
90 }
91 
92 static void wpaint_prev_destroy(struct WPaintPrev *wpp)
93 {
94  if (wpp->wpaint_prev) {
96  }
97  wpp->wpaint_prev = NULL;
98  wpp->tot = 0;
99 }
100 
103 /* -------------------------------------------------------------------- */
108 {
110 
112 }
113 
115 {
120  Mesh *me = ob->data;
121  int type = RNA_enum_get(op->ptr, "type");
122 
124  op->reports, depsgraph, scene, ob, armob, type, (me->symmetry & ME_SYMMETRY_X));
125 
126  DEG_id_tag_update(&me->id, 0);
129 
130  return OPERATOR_FINISHED;
131 }
132 
134 {
135  static const EnumPropertyItem type_items[] = {
136  {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights from bones"},
138  "ENVELOPES",
139  0,
140  "From Envelopes",
141  "Weights from envelopes with user defined radius"},
142  {0, NULL, 0, NULL, NULL},
143  };
144 
145  /* identifiers */
146  ot->name = "Weight from Bones";
147  ot->idname = "PAINT_OT_weight_from_bones";
148  ot->description =
149  ("Set the weights of the groups matching the attached armature's selected bones, "
150  "using the distance between the vertices and the bones");
151 
152  /* api callbacks */
156 
157  /* flags */
159 
160  /* properties */
161  ot->prop = RNA_def_enum(
162  ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights");
163 }
164 
167 /* -------------------------------------------------------------------- */
176 static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
177 {
179  ViewContext vc;
180  Mesh *me;
181  bool changed = false;
182 
184  me = BKE_mesh_from_object(vc.obact);
185 
186  if (me && me->dvert && vc.v3d && vc.rv3d && (vc.obact->actdef != 0)) {
187  const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
188  int v_idx_best = -1;
189  uint index;
190 
193 
194  if (use_vert_sel) {
195  if (ED_mesh_pick_vert(
196  C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
197  v_idx_best = index;
198  }
199  }
200  else {
202  C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
203  v_idx_best = index;
204  }
205  else if (ED_mesh_pick_face(
206  C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
207  /* This relies on knowing the internal workings of #ED_mesh_pick_face_vert() */
208  BKE_report(
209  op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
210  }
211  }
212 
213  if (v_idx_best != -1) { /* should always be valid */
214  ToolSettings *ts = vc.scene->toolsettings;
215  Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
216  const int vgroup_active = vc.obact->actdef - 1;
217  float vgroup_weight = BKE_defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
218  const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
219  bool use_lock_relative = ts->wpaint_lock_relative;
220  bool *defbase_locked = NULL, *defbase_unlocked = NULL;
221 
222  if (use_lock_relative) {
223  defbase_locked = BKE_object_defgroup_lock_flags_get(vc.obact, defbase_tot);
224  defbase_unlocked = BKE_object_defgroup_validmap_get(vc.obact, defbase_tot);
225 
226  use_lock_relative = BKE_object_defgroup_check_lock_relative(
227  defbase_locked, defbase_unlocked, vgroup_active);
228  }
229 
230  /* use combined weight in multipaint mode,
231  * since that's what is displayed to the user in the colors */
232  if (ts->multipaint) {
233  int defbase_tot_sel;
234  bool *defbase_sel = BKE_object_defgroup_selected_get(
235  vc.obact, defbase_tot, &defbase_tot_sel);
236 
237  if (defbase_tot_sel > 1) {
240  vc.obact, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
241  }
242 
243  use_lock_relative = use_lock_relative &&
245  defbase_tot, defbase_locked, defbase_sel, defbase_tot_sel);
246 
247  bool is_normalized = ts->auto_normalize || use_lock_relative;
249  &me->dvert[v_idx_best], defbase_tot, defbase_sel, defbase_tot_sel, is_normalized);
250  }
251 
252  MEM_freeN(defbase_sel);
253  }
254 
255  if (use_lock_relative) {
257  defbase_tot, defbase_locked, defbase_unlocked, defbase_locked, defbase_unlocked);
258 
259  vgroup_weight = BKE_defvert_lock_relative_weight(
260  vgroup_weight, &me->dvert[v_idx_best], defbase_tot, defbase_locked, defbase_unlocked);
261  }
262 
263  MEM_SAFE_FREE(defbase_locked);
264  MEM_SAFE_FREE(defbase_unlocked);
265 
266  CLAMP(vgroup_weight, 0.0f, 1.0f);
267  BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
268  changed = true;
269  }
270  }
271 
272  if (changed) {
273  /* not really correct since the brush didn't change, but redraws the toolbar */
274  WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL); /* ts->wpaint->paint.brush */
275 
276  return OPERATOR_FINISHED;
277  }
278  return OPERATOR_CANCELLED;
279 }
280 
282 {
283  /* identifiers */
284  ot->name = "Weight Paint Sample Weight";
285  ot->idname = "PAINT_OT_weight_sample";
286  ot->description = "Use the mouse to sample a weight in the 3D view";
287 
288  /* api callbacks */
291 
292  /* flags */
293  ot->flag = OPTYPE_UNDO;
294 }
295 
298 /* -------------------------------------------------------------------- */
302 /* samples cursor location, and gives menu with vertex groups to activate */
304  const int defbase_tot,
305  int *groups)
306 {
307  /* this func fills in used vgroup's */
308  bool found = false;
309  int i = dvert->totweight;
310  MDeformWeight *dw;
311  for (dw = dvert->dw; i > 0; dw++, i--) {
312  if (dw->def_nr < defbase_tot) {
313  groups[dw->def_nr] = true;
314  found = true;
315  }
316  }
317  return found;
318 }
321  PropertyRNA *UNUSED(prop),
322  bool *r_free)
323 {
324  if (C) {
325  wmWindow *win = CTX_wm_window(C);
326  if (win && win->eventstate) {
328  ViewContext vc;
329  Mesh *me;
330 
332  me = BKE_mesh_from_object(vc.obact);
333 
334  if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
335  const int defbase_tot = BLI_listbase_count(&vc.obact->defbase);
336  const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
337  int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
338  bool found = false;
339  uint index;
340 
341  const int mval[2] = {
342  win->eventstate->x - vc.region->winrct.xmin,
343  win->eventstate->y - vc.region->winrct.ymin,
344  };
345 
348 
349  if (use_vert_sel) {
350  if (ED_mesh_pick_vert(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
351  MDeformVert *dvert = &me->dvert[index];
352  found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
353  }
354  }
355  else {
356  if (ED_mesh_pick_face(C, vc.obact, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
357  const MPoly *mp = &me->mpoly[index];
358  uint fidx = mp->totloop - 1;
359 
360  do {
361  MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v];
362  found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
363  } while (fidx--);
364  }
365  }
366 
367  if (found == false) {
368  MEM_freeN(groups);
369  }
370  else {
371  EnumPropertyItem *item = NULL, item_tmp = {0};
372  int totitem = 0;
373  int i = 0;
374  bDeformGroup *dg;
375  for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
376  if (groups[i]) {
377  item_tmp.identifier = item_tmp.name = dg->name;
378  item_tmp.value = i;
379  RNA_enum_item_add(&item, &totitem, &item_tmp);
380  }
381  }
382 
383  RNA_enum_item_end(&item, &totitem);
384  *r_free = true;
385 
386  MEM_freeN(groups);
387  return item;
388  }
389  }
390  }
391  }
392 
393  return DummyRNA_NULL_items;
394 }
395 
397 {
398  int type = RNA_enum_get(op->ptr, "group");
400  ViewContext vc;
402 
403  BLI_assert(type + 1 >= 0);
404  vc.obact->actdef = type + 1;
405 
408  return OPERATOR_FINISHED;
409 }
410 
411 /* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active
412  * rather than its own operator */
414 {
415  PropertyRNA *prop = NULL;
416 
417  /* identifiers */
418  ot->name = "Weight Paint Sample Group";
419  ot->idname = "PAINT_OT_weight_sample_group";
420  ot->description = "Select one of the vertex groups available under current mouse position";
421 
422  /* api callbacks */
426 
427  /* flags */
428  ot->flag = OPTYPE_UNDO;
429 
430  /* keyingset to use (dynamic enum) */
431  prop = RNA_def_enum(
432  ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
435  ot->prop = prop;
436 }
437 
440 /* -------------------------------------------------------------------- */
444 /* fills in the selected faces with the current weight and vertex group */
445 static bool weight_paint_set(Object *ob, float paintweight)
446 {
447  Mesh *me = ob->data;
448  const MPoly *mp;
449  MDeformWeight *dw, *dw_prev;
450  int vgroup_active, vgroup_mirror = -1;
451  uint index;
452  const bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
453 
454  /* mutually exclusive, could be made into a */
455  const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
456 
457  if (me->totpoly == 0 || me->dvert == NULL || !me->mpoly) {
458  return false;
459  }
460 
461  vgroup_active = ob->actdef - 1;
462 
463  /* if mirror painting, find the other group */
465  vgroup_mirror = ED_wpaint_mirror_vgroup_ensure(ob, vgroup_active);
466  }
467 
468  struct WPaintPrev wpp;
469  wpaint_prev_create(&wpp, me->dvert, me->totvert);
470 
471  for (index = 0, mp = me->mpoly; index < me->totpoly; index++, mp++) {
472  uint fidx = mp->totloop - 1;
473 
474  if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) {
475  continue;
476  }
477 
478  do {
479  uint vidx = me->mloop[mp->loopstart + fidx].v;
480 
481  if (!me->dvert[vidx].flag) {
482  if ((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
483  continue;
484  }
485 
486  dw = BKE_defvert_ensure_index(&me->dvert[vidx], vgroup_active);
487  if (dw) {
488  dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + vidx, vgroup_active);
489  dw_prev->weight = dw->weight; /* set the undo weight */
490  dw->weight = paintweight;
491 
492  if (me->symmetry & ME_SYMMETRY_X) {
493  /* x mirror painting */
494  int j = mesh_get_x_mirror_vert(ob, NULL, vidx, topology);
495  if (j >= 0) {
496  /* copy, not paint again */
497  if (vgroup_mirror != -1) {
498  dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_mirror);
499  dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_mirror);
500  }
501  else {
502  dw = BKE_defvert_ensure_index(me->dvert + j, vgroup_active);
503  dw_prev = BKE_defvert_ensure_index(wpp.wpaint_prev + j, vgroup_active);
504  }
505  dw_prev->weight = dw->weight; /* set the undo weight */
506  dw->weight = paintweight;
507  }
508  }
509  }
510  me->dvert[vidx].flag = 1;
511  }
512 
513  } while (fidx--);
514  }
515 
516  {
517  MDeformVert *dv = me->dvert;
518  for (index = me->totvert; index != 0; index--, dv++) {
519  dv->flag = 0;
520  }
521  }
522 
523  wpaint_prev_destroy(&wpp);
524 
525  DEG_id_tag_update(&me->id, 0);
526 
527  return true;
528 }
529 
531 {
532  struct Scene *scene = CTX_data_scene(C);
533  Object *obact = CTX_data_active_object(C);
535  Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
536  float vgroup_weight = BKE_brush_weight_get(scene, brush);
537 
539  return OPERATOR_CANCELLED;
540  }
541 
542  if (weight_paint_set(obact, vgroup_weight)) {
543  ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
544  return OPERATOR_FINISHED;
545  }
546  return OPERATOR_CANCELLED;
547 }
548 
550 {
551  /* identifiers */
552  ot->name = "Set Weight";
553  ot->idname = "PAINT_OT_weight_set";
554  ot->description = "Fill the active vertex group with the current paint weight";
555 
556  /* api callbacks */
559 
560  /* flags */
562 }
563 
566 /* -------------------------------------------------------------------- */
570 /* *** VGroups Gradient *** */
571 typedef struct WPGradient_vertStore {
572  float sco[2];
573  float weight_orig;
574  enum {
577  VGRAD_STORE_IS_MODIFIED = (1 << 1)
578  } flag;
580 
581 typedef struct WPGradient_vertStoreBase {
582  struct WPaintPrev wpp;
585 
586 typedef struct WPGradient_userData {
587  struct ARegion *region;
591  const float *sco_start; /* [2] */
592  const float *sco_end; /* [2] */
593  float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
594  int def_nr;
595  bool is_init;
597  /* only for init */
599 
600  /* options */
603  short type;
604  float weightpaint;
606 
607 static void gradientVert_update(WPGradient_userData *grad_data, int index)
608 {
609  Mesh *me = grad_data->me;
610  WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
611 
612  /* Optionally restrict to assigned vertices only. */
613  if (grad_data->use_vgroup_restrict && ((vs->flag & VGRAD_STORE_DW_EXIST) == 0)) {
614  /* In this case the vertex will never have been touched. */
615  BLI_assert((vs->flag & VGRAD_STORE_IS_MODIFIED) == 0);
616  return;
617  }
618 
619  float alpha;
620  if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
621  alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
622  }
623  else {
625  alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
626  }
627  /* no need to clamp 'alpha' yet */
628 
629  /* adjust weight */
630  alpha = BKE_brush_curve_strength_clamped(grad_data->brush, alpha, 1.0f);
631 
632  if (alpha != 0.0f) {
633  MDeformVert *dv = &me->dvert[index];
634  MDeformWeight *dw = BKE_defvert_ensure_index(dv, grad_data->def_nr);
635  // dw->weight = alpha; // testing
636  int tool = grad_data->brush->blend;
637  float testw;
638 
639  /* init if we just added */
640  testw = ED_wpaint_blend_tool(
641  tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
642  CLAMP(testw, 0.0f, 1.0f);
643  dw->weight = testw;
644  vs->flag |= VGRAD_STORE_IS_MODIFIED;
645  }
646  else {
647  MDeformVert *dv = &me->dvert[index];
648  if (vs->flag & VGRAD_STORE_DW_EXIST) {
649  /* normally we NULL check, but in this case we know it exists */
650  MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
651  dw->weight = vs->weight_orig;
652  }
653  else {
654  /* wasn't originally existing, remove */
655  MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
656  if (dw) {
657  BKE_defvert_remove_group(dv, dw);
658  }
659  }
660  vs->flag &= ~VGRAD_STORE_IS_MODIFIED;
661  }
662 }
663 
664 static void gradientVertUpdate__mapFunc(void *userData,
665  int index,
666  const float UNUSED(co[3]),
667  const float UNUSED(no_f[3]),
668  const short UNUSED(no_s[3]))
669 {
670  WPGradient_userData *grad_data = userData;
671  WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
672 
673  if (vs->sco[0] == FLT_MAX) {
674  return;
675  }
676 
677  gradientVert_update(grad_data, index);
678 }
679 
680 static void gradientVertInit__mapFunc(void *userData,
681  int index,
682  const float co[3],
683  const float UNUSED(no_f[3]),
684  const short UNUSED(no_s[3]))
685 {
686  WPGradient_userData *grad_data = userData;
687  Mesh *me = grad_data->me;
688  WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
689 
690  if (grad_data->use_select && !(me->mvert[index].flag & SELECT)) {
691  copy_v2_fl(vs->sco, FLT_MAX);
692  return;
693  }
694 
695  /* run first pass only,
696  * the screen coords of the verts need to be cached because
697  * updating the mesh may move them about (entering feedback loop) */
698  if (BLI_BITMAP_TEST(grad_data->vert_visit, index)) {
699  /* Do not copy FLT_MAX here, for generative modifiers we are getting here
700  * multiple times with the same orig index. */
701  return;
702  }
703 
705  grad_data->region, co, vs->sco, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) !=
706  V3D_PROJ_RET_OK) {
707  copy_v2_fl(vs->sco, FLT_MAX);
708  return;
709  }
710 
711  MDeformVert *dv = &me->dvert[index];
712  const MDeformWeight *dw = BKE_defvert_find_index(dv, grad_data->def_nr);
713  if (dw) {
714  vs->weight_orig = dw->weight;
715  vs->flag = VGRAD_STORE_DW_EXIST;
716  }
717  else {
718  vs->weight_orig = 0.0f;
719  vs->flag = VGRAD_STORE_NOP;
720  }
721  BLI_BITMAP_ENABLE(grad_data->vert_visit, index);
722  gradientVert_update(grad_data, index);
723 }
724 
725 static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
726 {
727  wmGesture *gesture = op->customdata;
728  WPGradient_vertStoreBase *vert_cache = gesture->user_data.data;
729  int ret = WM_gesture_straightline_modal(C, op, event);
730 
731  if (ret & OPERATOR_RUNNING_MODAL) {
732  if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* XXX, hardcoded */
733  /* generally crap! redo! */
737  }
738  }
739 
740  if (ret & OPERATOR_CANCELLED) {
742  if (vert_cache != NULL) {
743  Mesh *me = ob->data;
744  if (vert_cache->wpp.wpaint_prev) {
746  BKE_defvert_array_copy(me->dvert, vert_cache->wpp.wpaint_prev, me->totvert);
747  wpaint_prev_destroy(&vert_cache->wpp);
748  }
749  MEM_freeN(vert_cache);
750  }
751 
754  }
755  else if (ret & OPERATOR_FINISHED) {
756  wpaint_prev_destroy(&vert_cache->wpp);
757  MEM_freeN(vert_cache);
758  }
759 
760  return ret;
761 }
762 
764 {
765  wmGesture *gesture = op->customdata;
766  WPGradient_vertStoreBase *vert_cache;
767  struct ARegion *region = CTX_wm_region(C);
770  Mesh *me = ob->data;
771  int x_start = RNA_int_get(op->ptr, "xstart");
772  int y_start = RNA_int_get(op->ptr, "ystart");
773  int x_end = RNA_int_get(op->ptr, "xend");
774  int y_end = RNA_int_get(op->ptr, "yend");
775  const float sco_start[2] = {x_start, y_start};
776  const float sco_end[2] = {x_end, y_end};
777  const bool is_interactive = (gesture != NULL);
778 
780 
782 
783  if (is_interactive) {
784  if (gesture->user_data.data == NULL) {
786  (sizeof(WPGradient_vertStore) * me->totvert),
787  __func__);
788  gesture->user_data.use_free = false;
789  data.is_init = true;
790 
792  &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert);
793 
794  /* on init only, convert face -> vert sel */
795  if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
797  }
798  }
799 
800  vert_cache = gesture->user_data.data;
801  }
802  else {
803  if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
804  return OPERATOR_CANCELLED;
805  }
806 
807  data.is_init = true;
808  vert_cache = MEM_mallocN(
809  sizeof(WPGradient_vertStoreBase) + (sizeof(WPGradient_vertStore) * me->totvert), __func__);
810  }
811 
812  data.region = region;
813  data.scene = scene;
814  data.me = ob->data;
815  data.sco_start = sco_start;
816  data.sco_end = sco_end;
817  data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
818  data.def_nr = ob->actdef - 1;
819  data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
820  data.vert_cache = vert_cache;
821  data.vert_visit = NULL;
822  data.type = RNA_enum_get(op->ptr, "type");
823 
824  {
826  VPaint *wp = ts->wpaint;
827  struct Brush *brush = BKE_paint_brush(&wp->paint);
828 
830 
831  data.brush = brush;
832  data.weightpaint = BKE_brush_weight_get(scene, brush);
833  data.use_vgroup_restrict = (ts->wpaint->flag & VP_FLAG_VGROUP_RESTRICT) != 0;
834  }
835 
837 
838  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
839  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
840 
842  cddata_masks.vmask |= CD_MASK_ORIGINDEX;
843  cddata_masks.emask |= CD_MASK_ORIGINDEX;
844  cddata_masks.pmask |= CD_MASK_ORIGINDEX;
845  Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
846  if (data.is_init) {
847  data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
848 
850 
851  MEM_freeN(data.vert_visit);
852  data.vert_visit = NULL;
853  }
854  else {
856  }
857 
860 
861  if (is_interactive == false) {
862  MEM_freeN(vert_cache);
863  }
864 
866  const int vgroup_num = BLI_listbase_count(&ob->defbase);
867  bool *vgroup_validmap = BKE_object_defgroup_validmap_get(ob, vgroup_num);
868  if (vgroup_validmap != NULL) {
869  MDeformVert *dvert = me->dvert;
870  for (int i = 0; i < me->totvert; i++) {
871  if ((data.vert_cache->elem[i].flag & VGRAD_STORE_IS_MODIFIED) != 0) {
872  BKE_defvert_normalize_lock_single(&dvert[i], vgroup_validmap, vgroup_num, data.def_nr);
873  }
874  }
875  MEM_freeN(vgroup_validmap);
876  }
877  }
878 
879  return OPERATOR_FINISHED;
880 }
881 
883 {
884  int ret;
885 
886  if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
887  return OPERATOR_CANCELLED;
888  }
889 
890  ret = WM_gesture_straightline_invoke(C, op, event);
891  if (ret & OPERATOR_RUNNING_MODAL) {
892  struct ARegion *region = CTX_wm_region(C);
893  if (region->regiontype == RGN_TYPE_WINDOW) {
894  /* TODO, hardcoded, extend WM_gesture_straightline_ */
895  if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
896  wmGesture *gesture = op->customdata;
897  gesture->is_active = true;
898  }
899  }
900  }
901  return ret;
902 }
903 
905 {
906  /* defined in DNA_space_types.h */
907  static const EnumPropertyItem gradient_types[] = {
908  {WPAINT_GRADIENT_TYPE_LINEAR, "LINEAR", 0, "Linear", ""},
909  {WPAINT_GRADIENT_TYPE_RADIAL, "RADIAL", 0, "Radial", ""},
910  {0, NULL, 0, NULL, NULL},
911  };
912 
913  PropertyRNA *prop;
914 
915  /* identifiers */
916  ot->name = "Weight Gradient";
917  ot->idname = "PAINT_OT_weight_gradient";
918  ot->description = "Draw a line to apply a weight gradient to selected vertices";
919 
920  /* api callbacks */
926 
927  /* flags */
929 
930  prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
932 
934 }
935 
float BKE_brush_weight_get(const struct Scene *scene, const struct Brush *brush)
void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float value)
float BKE_brush_curve_strength_clamped(struct Brush *br, float p, const float len)
Definition: brush.c:2464
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
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
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
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
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
support for deformation groups and hooks.
void BKE_defvert_array_free(struct MDeformVert *dvert, int totvert)
Definition: deform.c:977
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, const int defgroup)
Definition: deform.c:688
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_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert)
float BKE_defvert_lock_relative_weight(float weight, const struct MDeformVert *dv, int defbase_tot, const bool *defbase_locked, const bool *defbase_unlocked)
Definition: deform.c:920
void BKE_defvert_array_free_elems(struct MDeformVert *dvert, int totvert)
Definition: deform.c:959
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw)
Definition: deform.c:754
float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv, int defbase_tot, const bool *defbase_sel, int defbase_tot_sel, bool is_normalized)
Definition: deform.c:865
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 Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
void BKE_mesh_flush_select_from_polys(struct Mesh *me)
@ MESH_FOREACH_NOP
void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), void *userData, MeshForeachFlag flag)
struct Mesh * mesh_get_eval_final(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)
Functions for dealing with objects and deform verts, used by painting and tools.
bool BKE_object_defgroup_check_lock_relative(const bool *lock_flags, const bool *validmap, int index)
void BKE_object_defgroup_split_locked_validmap(int defbase_tot, const bool *locked, const bool *deform, bool *r_locked, bool *r_unlocked)
bool * BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot)
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)
bool BKE_object_defgroup_check_lock_relative_multi(int defbase_tot, const bool *lock_flags, const bool *selected, int sel_tot)
bool * BKE_object_defgroup_validmap_get(struct Object *ob, const int defbase_tot)
bool * BKE_object_defgroup_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot)
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:604
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:3469
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_fl(float r[2], float f)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
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_GEOMETRY
Definition: DNA_ID.h:611
#define CD_MASK_ORIGINDEX
@ 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
#define ME_EDIT_PAINT_SEL_MODE(_me)
@ ME_FACE_SEL
@ OB_MODE_WEIGHT_PAINT
Object is a sort of wrapper for general info.
@ VP_FLAG_VGROUP_RESTRICT
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
@ RGN_TYPE_WINDOW
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#define ARM_GROUPS_ENVELOPE
Definition: ED_armature.h:141
#define ARM_GROUPS_AUTO
Definition: ED_armature.h:142
bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, uint *r_index)
Definition: meshtools.c:1281
#define ED_MESH_PICK_DEFAULT_VERT_DIST
Definition: ED_mesh.h:514
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology)
Definition: meshtools.c:932
bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, uint *r_index)
Definition: meshtools.c:1215
#define ED_MESH_PICK_DEFAULT_FACE_DIST
Definition: ED_mesh.h:515
bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
Definition: meshtools.c:1401
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
Definition: space_view3d.c:190
@ V3D_PROJ_TEST_CLIP_NEAR
Definition: ED_view3d.h:196
@ V3D_PROJ_TEST_CLIP_BB
Definition: ED_view3d.h:194
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *region, const float co[3], float r_co[2], const eV3DProjTest flag)
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:176
void view3d_operator_needs_opengl(const struct bContext *C)
_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 type
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group RGB to Bright Vector Camera CLAMP
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
#define ND_DRAW
Definition: WM_types.h:362
#define NC_BRUSH
Definition: WM_types.h:286
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NA_EDITED
Definition: WM_types.h:462
#define KM_PRESS
Definition: WM_types.h:242
#define NC_OBJECT
Definition: WM_types.h:280
#define KM_RELEASE
Definition: WM_types.h:243
void ED_object_vgroup_calc_from_armature(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par, const int mode, const bool mirror)
#define SELECT
Scene scene
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
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 ulong * next
bool mask_paint_poll(bContext *C)
Definition: paint_image.c:1375
@ WPAINT_GRADIENT_TYPE_RADIAL
Definition: paint_intern.h:112
@ WPAINT_GRADIENT_TYPE_LINEAR
Definition: paint_intern.h:111
bool ED_wpaint_ensure_data(struct bContext *C, struct ReportList *reports, enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index)
int ED_wpaint_mirror_vgroup_ensure(struct Object *ob, const int vgroup_active)
float ED_wpaint_blend_tool(const int tool, const float weight, const float paintval, const float alpha)
bool weight_paint_mode_poll(struct bContext *C)
Definition: paint_vertex.c:238
@ WPAINT_ENSURE_MIRROR
Definition: paint_intern.h:137
bool weight_paint_poll_ignore_tool(bContext *C)
Definition: paint_vertex.c:268
void PAINT_OT_weight_set(wmOperatorType *ot)
static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
static bool weight_paint_set(Object *ob, float paintweight)
static void wpaint_prev_create(struct WPaintPrev *wpp, MDeformVert *dverts, int dcount)
struct WPGradient_userData WPGradient_userData
struct WPGradient_vertStore WPGradient_vertStore
struct WPGradient_vertStoreBase WPGradient_vertStoreBase
static void gradientVertInit__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
static int weight_from_bones_exec(bContext *C, wmOperator *op)
static int weight_paint_set_exec(bContext *C, wmOperator *op)
static bool weight_paint_sample_enum_itemf__helper(const MDeformVert *dvert, const int defbase_tot, int *groups)
static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
void PAINT_OT_weight_sample(wmOperatorType *ot)
static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void gradientVert_update(WPGradient_userData *grad_data, int index)
static void wpaint_prev_destroy(struct WPaintPrev *wpp)
static bool weight_from_bones_poll(bContext *C)
static void wpaint_prev_init(struct WPaintPrev *wpp)
static void gradientVertUpdate__mapFunc(void *userData, int index, const float UNUSED(co[3]), const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
void PAINT_OT_weight_from_bones(wmOperatorType *ot)
void PAINT_OT_weight_gradient(wmOperatorType *ot)
void PAINT_OT_weight_sample_group(wmOperatorType *ot)
static const EnumPropertyItem * weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int weight_sample_group_exec(bContext *C, wmOperator *op)
return ret
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
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
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3819
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_DEFAULT_items[]
Definition: rna_rna.c:45
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:40
void * regiondata
short regiontype
float alpha
struct CurveMapping * curve
short blend
void * first
Definition: DNA_listBase.h:47
struct MDeformWeight * dw
unsigned int def_nr
unsigned int v
char symmetry
struct MVert * mvert
struct MDeformVert * dvert
char editflag
int totvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
ListBase defbase
unsigned short actdef
void * data
struct CustomData_MeshMasks customdata_mask
struct ToolSettings * toolsettings
struct Scene * scene
Definition: ED_view3d.h:76
struct ARegion * region
Definition: ED_view3d.h:80
struct Object * obact
Definition: ED_view3d.h:78
struct View3D * v3d
Definition: ED_view3d.h:81
struct RegionView3D * rv3d
Definition: ED_view3d.h:83
WPGradient_vertStoreBase * vert_cache
WPGradient_vertStore elem[0]
enum WPGradient_vertStore::@486 flag
struct MDeformVert * wpaint_prev
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int y
Definition: WM_types.h:581
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
int x
Definition: WM_types.h:581
short type
Definition: WM_types.h:577
wmGenericUserData user_data
Definition: WM_types.h:532
uint is_active
Definition: WM_types.h:508
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
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
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
struct wmEvent * eventstate
@ WM_CURSOR_EDIT
Definition: wm_cursors.h:38
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ LEFTMOUSE
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982