Blender  V2.93
paint_vertex.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 
29 #include "MEM_guardedalloc.h"
30 
31 #include "BLI_array_utils.h"
32 #include "BLI_listbase.h"
33 #include "BLI_math.h"
34 #include "BLI_rect.h"
35 #include "BLI_task.h"
36 
37 #include "DNA_brush_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_particle_types.h"
41 #include "DNA_scene_types.h"
42 
43 #include "RNA_access.h"
44 
45 #include "BKE_brush.h"
46 #include "BKE_context.h"
47 #include "BKE_deform.h"
48 #include "BKE_layer.h"
49 #include "BKE_main.h"
50 #include "BKE_mesh.h"
51 #include "BKE_mesh_mapping.h"
52 #include "BKE_modifier.h"
53 #include "BKE_object.h"
54 #include "BKE_object_deform.h"
55 #include "BKE_paint.h"
56 #include "BKE_report.h"
57 #include "BKE_subsurf.h"
58 
59 #include "DEG_depsgraph.h"
60 
61 #include "WM_api.h"
62 #include "WM_message.h"
63 #include "WM_toolsystem.h"
64 #include "WM_types.h"
65 
66 #include "ED_armature.h"
67 #include "ED_mesh.h"
68 #include "ED_object.h"
69 #include "ED_screen.h"
70 #include "ED_view3d.h"
71 
72 /* For IMB_BlendMode only. */
73 #include "IMB_imbuf.h"
74 
75 #include "BKE_ccg.h"
76 #include "bmesh.h"
77 
78 #include "paint_intern.h" /* own include */
79 #include "sculpt_intern.h"
80 
81 /* -------------------------------------------------------------------- */
85 /* Use for 'blur' brush, align with PBVH nodes, created and freed on each update. */
88  uint value[3];
89 };
90 
93  double value;
94 };
95 
98  /* what angle to mask at */
99  float angle;
100  /* cos(angle), faster to compare */
101  float angle__cos;
102  float angle_inner;
104  /* difference between angle and angle_inner, for easy access */
105  float angle_range;
106 };
107 
108 static void view_angle_limits_init(struct NormalAnglePrecalc *a, float angle, bool do_mask_normal)
109 {
110  angle = RAD2DEGF(angle);
111  a->do_mask_normal = do_mask_normal;
112  if (do_mask_normal) {
113  a->angle_inner = angle;
114  a->angle = (a->angle_inner + 90.0f) * 0.5f;
115  }
116  else {
117  a->angle_inner = a->angle = angle;
118  }
119 
120  a->angle_inner *= (float)(M_PI_2 / 90);
121  a->angle *= (float)(M_PI_2 / 90);
122  a->angle_range = a->angle - a->angle_inner;
123 
124  if (a->angle_range <= 0.0f) {
125  a->do_mask_normal = false; /* no need to do blending */
126  }
127 
128  a->angle__cos = cosf(a->angle);
129  a->angle_inner__cos = cosf(a->angle_inner);
130 }
131 
133  float angle_cos,
134  float *mask_p)
135 {
136  if (angle_cos <= a->angle__cos) {
137  /* outsize the normal limit */
138  return false;
139  }
140  if (angle_cos < a->angle_inner__cos) {
141  *mask_p *= (a->angle - acosf(angle_cos)) / a->angle_range;
142  return true;
143  }
144  return true;
145 }
146 
147 static bool vwpaint_use_normal(const VPaint *vp)
148 {
149  return ((vp->paint.brush->flag & BRUSH_FRONTFACE) != 0) ||
150  ((vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
151 }
152 
153 static bool brush_use_accumulate_ex(const Brush *brush, const int ob_mode)
154 {
155  return ((brush->flag & BRUSH_ACCUMULATE) != 0 ||
156  (ob_mode == OB_MODE_VERTEX_PAINT ? (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) :
157  (brush->weightpaint_tool == WPAINT_TOOL_SMEAR)));
158 }
159 
160 static bool brush_use_accumulate(const VPaint *vp)
161 {
163 }
164 
166  MDeformVert *dvert_curr,
167  int index)
168 {
169  MDeformVert *dv_curr = &dvert_curr[index];
170  MDeformVert *dv_prev = &dvert_prev[index];
171  if (dv_prev->flag == 1) {
172  dv_prev->flag = 0;
173  BKE_defvert_copy(dv_prev, dv_curr);
174  }
175  return dv_prev;
176 }
177 
178 /* check if we can do partial updates and have them draw realtime
179  * (without evaluating modifiers) */
181 {
182  Mesh *me_eval = BKE_object_get_evaluated_mesh(ob);
183 
184  if (me_eval != NULL) {
185  Mesh *me = BKE_mesh_from_object(ob);
186  if (me && me->mloopcol) {
187  return (me->mloopcol == CustomData_get_layer(&me_eval->ldata, CD_MLOOPCOL));
188  }
189  }
190 
191  return false;
192 }
193 
194 static void paint_last_stroke_update(Scene *scene, const float location[3])
195 {
197  ups->average_stroke_counter++;
198  add_v3_v3(ups->average_stroke_accum, location);
199  ups->last_stroke_valid = true;
200 }
201 
202 /* polling - retrieve whether cursor should be set or operator should be done */
203 
204 /* Returns true if vertex paint mode is active */
206 {
208 
209  return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
210 }
211 
212 static bool vertex_paint_poll_ex(bContext *C, bool check_tool)
213 {
216  if (area && area->spacetype == SPACE_VIEW3D) {
217  ARegion *region = CTX_wm_region(C);
218  if (region->regiontype == RGN_TYPE_WINDOW) {
219  if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
220  return true;
221  }
222  }
223  }
224  }
225  return false;
226 }
227 
229 {
230  return vertex_paint_poll_ex(C, true);
231 }
232 
234 {
235  return vertex_paint_poll_ex(C, false);
236 }
237 
239 {
241 
242  return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
243 }
244 
245 static bool weight_paint_poll_ex(bContext *C, bool check_tool)
246 {
248  ScrArea *area;
249 
250  if ((ob != NULL) && (ob->mode & OB_MODE_WEIGHT_PAINT) &&
251  (BKE_paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
252  (area = CTX_wm_area(C)) && (area->spacetype == SPACE_VIEW3D)) {
253  ARegion *region = CTX_wm_region(C);
254  if (ELEM(region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_HUD)) {
255  if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
256  return true;
257  }
258  }
259  }
260  return false;
261 }
262 
264 {
265  return weight_paint_poll_ex(C, true);
266 }
267 
269 {
270  return weight_paint_poll_ex(C, false);
271 }
272 
274 {
275  Brush *brush = BKE_paint_brush(&vp->paint);
276  uchar col[4];
278  secondary ? BKE_brush_secondary_color_get(scene, brush) :
279  BKE_brush_color_get(scene, brush));
280  col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
281  return *(uint *)col;
282 }
283 
284 /* wpaint has 'wpaint_blend' */
285 static uint vpaint_blend(const VPaint *vp,
286  uint color_curr,
287  uint color_orig,
288  uint color_paint,
289  const int alpha_i,
290  /* pre scaled from [0-1] --> [0-255] */
291  const int brush_alpha_value_i)
292 {
293  const Brush *brush = vp->paint.brush;
294  const IMB_BlendMode blend = brush->blend;
295 
296  uint color_blend = ED_vpaint_blend_tool(blend, color_curr, color_paint, alpha_i);
297 
298  /* if no accumulate, clip color adding with colorig & orig alpha */
299  if (!brush_use_accumulate(vp)) {
300  uint color_test, a;
301  char *cp, *ct, *co;
302 
303  color_test = ED_vpaint_blend_tool(blend, color_orig, color_paint, brush_alpha_value_i);
304 
305  cp = (char *)&color_blend;
306  ct = (char *)&color_test;
307  co = (char *)&color_orig;
308 
309  for (a = 0; a < 4; a++) {
310  if (ct[a] < co[a]) {
311  if (cp[a] < ct[a]) {
312  cp[a] = ct[a];
313  }
314  else if (cp[a] > co[a]) {
315  cp[a] = co[a];
316  }
317  }
318  else {
319  if (cp[a] < co[a]) {
320  cp[a] = co[a];
321  }
322  else if (cp[a] > ct[a]) {
323  cp[a] = ct[a];
324  }
325  }
326  }
327  }
328 
329  if ((brush->flag & BRUSH_LOCK_ALPHA) &&
331  char *cp, *cc;
332  cp = (char *)&color_blend;
333  cc = (char *)&color_curr;
334  cp[3] = cc[3];
335  }
336 
337  return color_blend;
338 }
339 
340 static void tex_color_alpha(VPaint *vp, const ViewContext *vc, const float co[3], float r_rgba[4])
341 {
342  const Brush *brush = BKE_paint_brush(&vp->paint);
343  BLI_assert(brush->mtex.tex != NULL);
344  if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
345  BKE_brush_sample_tex_3d(vc->scene, brush, co, r_rgba, 0, NULL);
346  }
347  else {
348  float co_ss[2]; /* screenspace */
351  V3D_PROJ_RET_OK) {
352  const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
353  BKE_brush_sample_tex_3d(vc->scene, brush, co_ss_3d, r_rgba, 0, NULL);
354  }
355  else {
356  zero_v4(r_rgba);
357  }
358  }
359 }
360 
361 /* vpaint has 'vpaint_blend' */
362 static float wpaint_blend(const VPaint *wp,
363  float weight,
364  const float alpha,
365  float paintval,
366  const float UNUSED(brush_alpha_value),
367  const short do_flip)
368 {
369  const Brush *brush = wp->paint.brush;
370  IMB_BlendMode blend = brush->blend;
371 
372  if (do_flip) {
373  switch (blend) {
374  case IMB_BLEND_MIX:
375  paintval = 1.0f - paintval;
376  break;
377  case IMB_BLEND_ADD:
379  break;
380  case IMB_BLEND_SUB:
382  break;
383  case IMB_BLEND_LIGHTEN:
385  break;
386  case IMB_BLEND_DARKEN:
388  break;
389  default:
390  break;
391  }
392  }
393 
394  weight = ED_wpaint_blend_tool(blend, weight, paintval, alpha);
395 
396  CLAMP(weight, 0.0f, 1.0f);
397 
398  return weight;
399 }
400 
401 static float wpaint_clamp_monotonic(float oldval, float curval, float newval)
402 {
403  if (newval < oldval) {
404  return MIN2(newval, curval);
405  }
406  if (newval > oldval) {
407  return MAX2(newval, curval);
408  }
409  return newval;
410 }
411 
413  float weight, float old_weight, float locked_weight, float free_weight, bool auto_normalize)
414 {
415  /* In auto-normalize mode, or when there is no unlocked weight,
416  * compute based on locked weight. */
417  if (auto_normalize || free_weight <= 0.0f) {
418  if (locked_weight < 1.0f - VERTEX_WEIGHT_LOCK_EPSILON) {
419  weight *= (1.0f - locked_weight);
420  }
421  else {
422  weight = 0;
423  }
424  }
425  else {
426  /* When dealing with full unlocked weight, don't paint, as it is always displayed as 1. */
427  if (old_weight >= free_weight) {
428  weight = old_weight;
429  }
430  /* Try to compute a weight value that would produce the desired effect if normalized. */
431  else if (weight < 1.0f) {
432  weight = weight * (free_weight - old_weight) / (1 - weight);
433  }
434  else {
435  weight = 1.0f;
436  }
437  }
438 
439  return weight;
440 }
441 
442 /* ----------------------------------------------------- */
443 
445  const int defbase_tot,
446  const bool *vgroup_validmap)
447 {
448  float sum = 0.0f, fac;
449  uint i, tot = 0;
450  MDeformWeight *dw;
451 
452  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
453  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
454  tot++;
455  sum += dw->weight;
456  }
457  }
458 
459  if ((tot == 0) || (sum == 1.0f)) {
460  return;
461  }
462 
463  if (sum != 0.0f) {
464  fac = 1.0f / sum;
465 
466  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
467  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
468  dw->weight *= fac;
469  }
470  }
471  }
472  else {
473  /* hrmf, not a factor in this case */
474  fac = 1.0f / tot;
475 
476  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
477  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
478  dw->weight = fac;
479  }
480  }
481  }
482 }
483 
489  const int defbase_tot,
490  const bool *vgroup_validmap,
491  const bool *lock_flags)
492 {
493  float sum = 0.0f, fac;
494  float sum_unlock = 0.0f;
495  float lock_weight = 0.0f;
496  uint i, tot = 0;
497  MDeformWeight *dw;
498 
499  if (lock_flags == NULL) {
500  do_weight_paint_normalize_all(dvert, defbase_tot, vgroup_validmap);
501  return true;
502  }
503 
504  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
505  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
506  sum += dw->weight;
507 
508  if (lock_flags[dw->def_nr]) {
509  lock_weight += dw->weight;
510  }
511  else {
512  tot++;
513  sum_unlock += dw->weight;
514  }
515  }
516  }
517 
518  if (sum == 1.0f) {
519  return true;
520  }
521 
522  if (tot == 0) {
523  return false;
524  }
525 
526  if (lock_weight >= 1.0f - VERTEX_WEIGHT_LOCK_EPSILON) {
527  /* locked groups make it impossible to fully normalize,
528  * zero out what we can and return false */
529  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
530  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
531  if (lock_flags[dw->def_nr] == false) {
532  dw->weight = 0.0f;
533  }
534  }
535  }
536 
537  return (lock_weight == 1.0f);
538  }
539  if (sum_unlock != 0.0f) {
540  fac = (1.0f - lock_weight) / sum_unlock;
541 
542  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
543  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
544  if (lock_flags[dw->def_nr] == false) {
545  dw->weight *= fac;
546  /* paranoid but possibly with float error */
547  CLAMP(dw->weight, 0.0f, 1.0f);
548  }
549  }
550  }
551  }
552  else {
553  /* hrmf, not a factor in this case */
554  fac = (1.0f - lock_weight) / tot;
555  /* paranoid but possibly with float error */
556  CLAMP(fac, 0.0f, 1.0f);
557 
558  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
559  if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
560  if (lock_flags[dw->def_nr] == false) {
561  dw->weight = fac;
562  }
563  }
564  }
565  }
566 
567  return true;
568 }
569 
575  const int defbase_tot,
576  const bool *vgroup_validmap,
577  const bool *lock_flags,
578  const bool *lock_with_active)
579 {
580  /* first pass with both active and explicitly locked groups restricted from change */
581 
583  dvert, defbase_tot, vgroup_validmap, lock_with_active);
584 
585  if (!success) {
595  do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
596  }
597 }
598 
599 #if 0 /* UNUSED */
600 static bool has_unselected_unlocked_bone_group(int defbase_tot,
601  bool *defbase_sel,
602  int selected,
603  const bool *lock_flags,
604  const bool *vgroup_validmap)
605 {
606  int i;
607  if (defbase_tot == selected) {
608  return false;
609  }
610  for (i = 0; i < defbase_tot; i++) {
611  if (vgroup_validmap[i] && !defbase_sel[i] && !lock_flags[i]) {
612  return true;
613  }
614  }
615  return false;
616 }
617 #endif
618 
620  const int defbase_tot,
621  const bool *defbase_sel,
622  float *change_p)
623 {
624  int i;
625  MDeformWeight *dw;
626  float val;
627  float change = *change_p;
628 
629  /* verify that the change does not cause values exceeding 1 and clamp it */
630  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
631  if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
632  if (dw->weight) {
633  val = dw->weight * change;
634  if (val > 1) {
635  change = 1.0f / dw->weight;
636  }
637  }
638  }
639  }
640 
641  *change_p = change;
642 }
643 
645  const int defbase_tot,
646  float change,
647  const bool *defbase_sel)
648 {
649  int i;
650  MDeformWeight *dw;
651  float val;
652 
653  /* in case the change is reduced, you need to recheck
654  * the earlier values to make sure they are not 0
655  * (precision error) */
656  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
657  if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
658  if (dw->weight) {
659  val = dw->weight * change;
660  /* the value should never reach zero while multi-painting if it
661  * was nonzero beforehand */
662  if (val <= 0) {
663  return false;
664  }
665  }
666  }
667  }
668 
669  return true;
670 }
671 
673  const int defbase_tot,
674  float change,
675  const bool *defbase_sel)
676 {
677  int i;
678  MDeformWeight *dw;
679 
680  /* apply the valid change */
681  for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
682  if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
683  if (dw->weight) {
684  dw->weight = dw->weight * change;
685  CLAMP(dw->weight, 0.0f, 1.0f);
686  }
687  }
688  }
689 }
690 
701  int index;
707  const bool *lock;
708 };
709 
710 /* struct to avoid passing many args each call to do_weight_paint_vertex()
711  * this _could_ be made a part of the operators 'WPaintData' struct, or at
712  * least a member, but for now keep its own struct, initialized on every
713  * paint stroke update - campbell */
714 typedef struct WeightPaintInfo {
715 
717 
718  /* both must add up to 'defbase_tot' */
721 
723 
724  /* boolean array for locked bones,
725  * length of defbase_tot */
726  const bool *lock_flags;
727  /* boolean array for selected bones,
728  * length of defbase_tot, cant be const because of how its passed */
729  const bool *defbase_sel;
730  /* same as WeightPaintData.vgroup_validmap,
731  * only added here for convenience */
732  const bool *vgroup_validmap;
733  /* same as WeightPaintData.vgroup_locked/unlocked,
734  * only added here for convenience */
735  const bool *vgroup_locked;
736  const bool *vgroup_unlocked;
737 
738  bool do_flip;
743 
744  float brush_alpha_value; /* result of BKE_brush_alpha_get() */
746 
748  /* vars which remain the same for every vert */
749  const VPaint *wp,
750  Object *ob,
751  const WeightPaintInfo *wpi,
752  /* vars which change on each stroke */
753  const uint index,
754  float alpha,
755  float paintweight)
756 {
757  Mesh *me = ob->data;
758  MDeformVert *dv = &me->dvert[index];
759  bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
760 
761  MDeformWeight *dw;
762  float weight_prev, weight_cur;
763  float dw_rel_locked = 0.0f, dw_rel_free = 1.0f;
764 
765  /* mirror vars */
766  int index_mirr;
767  int vgroup_mirr;
768 
769  MDeformVert *dv_mirr;
770  MDeformWeight *dw_mirr;
771 
772  /* Check if we should mirror vertex groups (X-axis). */
774  index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
775  vgroup_mirr = wpi->mirror.index;
776 
777  /* another possible error - mirror group _and_ active group are the same (which is fine),
778  * but we also are painting onto a center vertex - this would paint the same weight twice */
779  if (index_mirr == index && vgroup_mirr == wpi->active.index) {
780  index_mirr = vgroup_mirr = -1;
781  }
782  }
783  else {
784  index_mirr = vgroup_mirr = -1;
785  }
786 
787  /* Check if painting should create new deform weight entries. */
788  bool restrict_to_existing = (wp->flag & VP_FLAG_VGROUP_RESTRICT) != 0;
789 
790  if (wpi->do_lock_relative || wpi->do_auto_normalize) {
791  /* Without do_lock_relative only dw_rel_locked is reliable, while dw_rel_free may be fake 0. */
792  dw_rel_free = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_unlocked);
793  dw_rel_locked = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_locked);
794  CLAMP(dw_rel_locked, 0.0f, 1.0f);
795 
796  /* Do not create entries if there is not enough free weight to paint.
797  * This logic is the same as in wpaint_undo_lock_relative and auto-normalize. */
798  if (wpi->do_auto_normalize || dw_rel_free <= 0.0f) {
799  if (dw_rel_locked >= 1.0f - VERTEX_WEIGHT_LOCK_EPSILON) {
800  restrict_to_existing = true;
801  }
802  }
803  }
804 
805  if (restrict_to_existing) {
806  dw = BKE_defvert_find_index(dv, wpi->active.index);
807  }
808  else {
809  dw = BKE_defvert_ensure_index(dv, wpi->active.index);
810  }
811 
812  if (dw == NULL) {
813  return;
814  }
815 
816  /* get the mirror def vars */
817  if (index_mirr != -1) {
818  dv_mirr = &me->dvert[index_mirr];
819  if (wp->flag & VP_FLAG_VGROUP_RESTRICT) {
820  dw_mirr = BKE_defvert_find_index(dv_mirr, vgroup_mirr);
821 
822  if (dw_mirr == NULL) {
823  index_mirr = vgroup_mirr = -1;
824  dv_mirr = NULL;
825  }
826  }
827  else {
828  if (index != index_mirr) {
829  dw_mirr = BKE_defvert_ensure_index(dv_mirr, vgroup_mirr);
830  }
831  else {
832  /* dv and dv_mirr are the same */
833  int totweight_prev = dv_mirr->totweight;
834  int dw_offset = (int)(dw - dv_mirr->dw);
835  dw_mirr = BKE_defvert_ensure_index(dv_mirr, vgroup_mirr);
836 
837  /* if we added another, get our old one back */
838  if (totweight_prev != dv_mirr->totweight) {
839  dw = &dv_mirr->dw[dw_offset];
840  }
841  }
842  }
843  }
844  else {
845  dv_mirr = NULL;
846  dw_mirr = NULL;
847  }
848 
849  weight_cur = dw->weight;
850 
851  /* Handle weight caught up in locked defgroups for Lock Relative. */
852  if (wpi->do_lock_relative) {
853  weight_cur = BKE_defvert_calc_lock_relative_weight(weight_cur, dw_rel_locked, dw_rel_free);
854  }
855 
856  if (!brush_use_accumulate(wp)) {
857  MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
858  MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index);
859  if (index_mirr != -1) {
860  defweight_prev_init(dvert_prev, me->dvert, index_mirr);
861  }
862 
863  weight_prev = BKE_defvert_find_weight(dv_prev, wpi->active.index);
864 
865  if (wpi->do_lock_relative) {
866  weight_prev = BKE_defvert_lock_relative_weight(
867  weight_prev, dv_prev, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
868  }
869  }
870  else {
871  weight_prev = weight_cur;
872  }
873 
874  /* If there are no normalize-locks or multipaint,
875  * then there is no need to run the more complicated checks */
876 
877  {
878  float new_weight = wpaint_blend(
879  wp, weight_prev, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
880 
881  float weight = wpaint_clamp_monotonic(weight_prev, weight_cur, new_weight);
882 
883  /* Undo the lock relative weight correction. */
884  if (wpi->do_lock_relative) {
885  if (index_mirr == index) {
886  /* When painting a center vertex with X Mirror and L/R pair,
887  * handle both groups together. This avoids weird fighting
888  * in the non-normalized weight mode. */
889  float orig_weight = dw->weight + dw_mirr->weight;
890  weight = 0.5f *
892  weight * 2, orig_weight, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
893  }
894  else {
895  weight = wpaint_undo_lock_relative(
896  weight, dw->weight, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
897  }
898 
899  CLAMP(weight, 0.0f, 1.0f);
900  }
901 
902  dw->weight = weight;
903 
904  /* WATCH IT: take care of the ordering of applying mirror -> normalize,
905  * can give wrong results T26193, least confusing if normalize is done last */
906 
907  /* apply mirror */
908  if (index_mirr != -1) {
909  /* copy, not paint again */
910  dw_mirr->weight = dw->weight;
911  }
912 
913  /* apply normalize */
914  if (wpi->do_auto_normalize) {
915  /* note on normalize - this used to be applied after painting and normalize all weights,
916  * in some ways this is good because there is feedback where the more weights involved would
917  * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active.
918  *
919  * However this gave a problem since applying mirror, then normalize both verts
920  * the resulting weight wont match on both sides.
921  *
922  * If this 'resisting', slower normalize is nicer, we could call
923  * do_weight_paint_normalize_all() and only use...
924  * do_weight_paint_normalize_all_active() when normalizing the mirror vertex.
925  * - campbell
926  */
928  dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
929 
930  if (index_mirr != -1) {
931  /* only normalize if this is not a center vertex,
932  * else we get a conflict, normalizing twice */
933  if (index != index_mirr) {
935  dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->mirror.lock);
936  }
937  else {
938  /* This case accounts for:
939  * - Painting onto a center vertex of a mesh.
940  * - X-mirror is enabled.
941  * - Auto normalize is enabled.
942  * - The group you are painting onto has a L / R version.
943  *
944  * We want L/R vgroups to have the same weight but this cant be if both are over 0.5,
945  * We _could_ have special check for that, but this would need its own
946  * normalize function which holds 2 groups from changing at once.
947  *
948  * So! just balance out the 2 weights, it keeps them equal and everything normalized.
949  *
950  * While it wont hit the desired weight immediately as the user waggles their mouse,
951  * constant painting and re-normalizing will get there. this is also just simpler logic.
952  * - campbell */
953  dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f;
954  }
955  }
956  }
957  }
958 }
959 
961  /* vars which remain the same for every vert */
962  const VPaint *wp,
963  Object *ob,
964  const WeightPaintInfo *wpi,
965  /* vars which change on each stroke */
966  const uint index,
967  float alpha,
968  float paintweight)
969 {
970  Mesh *me = ob->data;
971  MDeformVert *dv = &me->dvert[index];
972  bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
973 
974  /* mirror vars */
975  int index_mirr = -1;
976  MDeformVert *dv_mirr = NULL;
977 
978  /* weights */
979  float curw, curw_real, oldw, neww, change, curw_mirr, change_mirr;
980  float dw_rel_free, dw_rel_locked;
981 
982  /* Check if we should mirror vertex groups (X-axis). */
984  index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
985 
986  if (!ELEM(index_mirr, -1, index)) {
987  dv_mirr = &me->dvert[index_mirr];
988  }
989  else {
990  index_mirr = -1;
991  }
992  }
993 
994  /* compute weight change by applying the brush to average or sum of group weights */
995  curw = curw_real = BKE_defvert_multipaint_collective_weight(
996  dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
997 
998  if (curw == 0.0f) {
999  /* note: no weight to assign to this vertex, could add all groups? */
1000  return;
1001  }
1002 
1003  /* Handle weight caught up in locked defgroups for Lock Relative. */
1004  if (wpi->do_lock_relative) {
1005  dw_rel_free = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_unlocked);
1006  dw_rel_locked = BKE_defvert_total_selected_weight(dv, wpi->defbase_tot, wpi->vgroup_locked);
1007  CLAMP(dw_rel_locked, 0.0f, 1.0f);
1008 
1009  curw = BKE_defvert_calc_lock_relative_weight(curw, dw_rel_locked, dw_rel_free);
1010  }
1011 
1012  if (!brush_use_accumulate(wp)) {
1013  MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
1014  MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index);
1015  if (index_mirr != -1) {
1016  defweight_prev_init(dvert_prev, me->dvert, index_mirr);
1017  }
1018 
1020  dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
1021 
1022  if (wpi->do_lock_relative) {
1024  oldw, dv_prev, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
1025  }
1026  }
1027  else {
1028  oldw = curw;
1029  }
1030 
1031  neww = wpaint_blend(wp, oldw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
1032  neww = wpaint_clamp_monotonic(oldw, curw, neww);
1033 
1034  if (wpi->do_lock_relative) {
1036  neww, curw_real, dw_rel_locked, dw_rel_free, wpi->do_auto_normalize);
1037  }
1038 
1039  change = neww / curw_real;
1040 
1041  /* verify for all groups that 0 < result <= 1 */
1042  multipaint_clamp_change(dv, wpi->defbase_tot, wpi->defbase_sel, &change);
1043 
1044  if (dv_mirr != NULL) {
1046  dv_mirr, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
1047 
1048  if (curw_mirr == 0.0f) {
1049  /* can't mirror into a zero weight vertex */
1050  dv_mirr = NULL;
1051  }
1052  else {
1053  /* mirror is changed to achieve the same collective weight value */
1054  float orig = change_mirr = curw_real * change / curw_mirr;
1055 
1056  multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
1057 
1058  if (!multipaint_verify_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel)) {
1059  return;
1060  }
1061 
1062  change *= change_mirr / orig;
1063  }
1064  }
1065 
1066  if (!multipaint_verify_change(dv, wpi->defbase_tot, change, wpi->defbase_sel)) {
1067  return;
1068  }
1069 
1070  /* apply validated change to vertex and mirror */
1071  multipaint_apply_change(dv, wpi->defbase_tot, change, wpi->defbase_sel);
1072 
1073  if (dv_mirr != NULL) {
1074  multipaint_apply_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel);
1075  }
1076 
1077  /* normalize */
1078  if (wpi->do_auto_normalize) {
1080  dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
1081 
1082  if (dv_mirr != NULL) {
1084  dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
1085  }
1086  }
1087 }
1088 
1090  /* vars which remain the same for every vert */
1091  const VPaint *wp,
1092  Object *ob,
1093  const WeightPaintInfo *wpi,
1094  /* vars which change on each stroke */
1095  const uint index,
1096  float alpha,
1097  float paintweight)
1098 {
1099  if (wpi->do_multipaint) {
1100  do_weight_paint_vertex_multi(wp, ob, wpi, index, alpha, paintweight);
1101  }
1102  else {
1103  do_weight_paint_vertex_single(wp, ob, wpi, index, alpha, paintweight);
1104  }
1105 }
1106 
1107 /* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
1109  Scene *scene,
1110  Object *ob,
1111  eObjectMode object_mode)
1112 {
1113  /* Create persistent sculpt mode data */
1115 
1116  BLI_assert(ob->sculpt == NULL);
1117  ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
1118  ob->sculpt->mode_type = object_mode;
1119  BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
1120 }
1121 
1123 {
1124  BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
1125 }
1126 
1128 {
1129  /* Create maps */
1130  struct SculptVertexPaintGeomMap *gmap = NULL;
1131  if (ob->mode == OB_MODE_VERTEX_PAINT) {
1132  gmap = &ob->sculpt->mode.vpaint.gmap;
1134  }
1135  else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
1136  gmap = &ob->sculpt->mode.wpaint.gmap;
1138  }
1139  else {
1140  ob->sculpt->mode_type = 0;
1141  BLI_assert(0);
1142  return;
1143  }
1144 
1145  Mesh *me = ob->data;
1146 
1147  if (gmap->vert_to_loop == NULL) {
1148  gmap->vert_map_mem = NULL;
1149  gmap->vert_to_loop = NULL;
1150  gmap->poly_map_mem = NULL;
1151  gmap->vert_to_poly = NULL;
1153  &gmap->vert_map_mem,
1154  me->mpoly,
1155  me->mloop,
1156  me->totvert,
1157  me->totpoly,
1158  me->totloop);
1160  &gmap->poly_map_mem,
1161  me->mpoly,
1162  me->mloop,
1163  me->totvert,
1164  me->totpoly,
1165  me->totloop);
1166  }
1167 
1168  /* Create average brush arrays */
1169  if (ob->mode == OB_MODE_VERTEX_PAINT) {
1170  if (!brush_use_accumulate(ts->vpaint)) {
1171  if (ob->sculpt->mode.vpaint.previous_color == NULL) {
1172  ob->sculpt->mode.vpaint.previous_color = MEM_callocN(me->totloop * sizeof(uint), __func__);
1173  }
1174  }
1175  else {
1176  MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_color);
1177  }
1178  }
1179  else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
1180  if (!brush_use_accumulate(ts->wpaint)) {
1181  if (ob->sculpt->mode.wpaint.alpha_weight == NULL) {
1182  ob->sculpt->mode.wpaint.alpha_weight = MEM_callocN(me->totvert * sizeof(float), __func__);
1183  }
1184  if (ob->sculpt->mode.wpaint.dvert_prev == NULL) {
1185  ob->sculpt->mode.wpaint.dvert_prev = MEM_callocN(me->totvert * sizeof(MDeformVert),
1186  __func__);
1187  MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
1188  for (int i = 0; i < me->totvert; i++, dv++) {
1189  /* Use to show this isn't initialized, never apply to the mesh data. */
1190  dv->flag = 1;
1191  }
1192  }
1193  }
1194  else {
1195  MEM_SAFE_FREE(ob->sculpt->mode.wpaint.alpha_weight);
1196  if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
1197  BKE_defvert_array_free_elems(ob->sculpt->mode.wpaint.dvert_prev, me->totvert);
1198  MEM_freeN(ob->sculpt->mode.wpaint.dvert_prev);
1199  ob->sculpt->mode.wpaint.dvert_prev = NULL;
1200  }
1201  }
1202  }
1203 }
1204 
1207 /* -------------------------------------------------------------------- */
1212  Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag)
1213 {
1214  ob->mode |= mode_flag;
1215  Mesh *me = BKE_mesh_from_object(ob);
1216 
1217  /* Same as sculpt mode, make sure we don't have cached derived mesh which
1218  * points to freed arrays.
1219  */
1221 
1222  if (mode_flag == OB_MODE_VERTEX_PAINT) {
1223  const ePaintMode paint_mode = PAINT_MODE_VERTEX;
1225 
1227  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
1229  BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
1230  }
1231  else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
1232  const ePaintMode paint_mode = PAINT_MODE_WEIGHT;
1233 
1235  Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
1237  BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
1238 
1239  /* weight paint specific */
1242  }
1243  else {
1244  BLI_assert(0);
1245  }
1246 
1247  /* Create vertex/weight paint mode session data */
1248  if (ob->sculpt) {
1249  if (ob->sculpt->cache) {
1251  ob->sculpt->cache = NULL;
1252  }
1254  }
1255 
1256  vertex_paint_init_session(depsgraph, scene, ob, mode_flag);
1257 
1258  /* Flush object mode. */
1260 }
1261 
1263 {
1265 }
1267 {
1268  Main *bmain = CTX_data_main(C);
1272 }
1273 
1275 {
1277 }
1279 {
1280  Main *bmain = CTX_data_main(C);
1284 }
1285 
1288 /* -------------------------------------------------------------------- */
1292 static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
1293 {
1294  Mesh *me = BKE_mesh_from_object(ob);
1295  ob->mode &= ~mode_flag;
1296 
1297  if (mode_flag == OB_MODE_VERTEX_PAINT) {
1298  if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
1300  }
1301  else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
1303  }
1304  }
1305  else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
1306  if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
1308  }
1309  else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
1311  }
1312  }
1313  else {
1314  BLI_assert(0);
1315  }
1316 
1317  /* If the cache is not released by a cancel or a done, free it now. */
1318  if (ob->sculpt && ob->sculpt->cache) {
1320  ob->sculpt->cache = NULL;
1321  }
1322 
1324 
1326 
1327  if (mode_flag == OB_MODE_WEIGHT_PAINT) {
1330  }
1331 
1332  /* Never leave derived meshes behind. */
1334 
1335  /* Flush object mode. */
1337 }
1338 
1340 {
1342 }
1344 {
1347 }
1348 
1350 {
1352 }
1354 {
1357 }
1358 
1361 /* -------------------------------------------------------------------- */
1369 {
1370  Main *bmain = CTX_data_main(C);
1371  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
1373  const int mode_flag = OB_MODE_WEIGHT_PAINT;
1374  const bool is_mode_set = (ob->mode & mode_flag) != 0;
1377 
1378  if (!is_mode_set) {
1379  if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
1380  return OPERATOR_CANCELLED;
1381  }
1382  }
1383 
1384  Mesh *me = BKE_mesh_from_object(ob);
1385 
1386  if (is_mode_set) {
1388  }
1389  else {
1391  if (depsgraph) {
1393  }
1396  }
1397 
1398  /* Prepare armature posemode. */
1399  ED_object_posemode_set_for_weight_paint(C, bmain, ob, is_mode_set);
1400 
1401  /* Weight-paint works by overriding colors in mesh,
1402  * so need to make sure we recalculate on enter and
1403  * exit (exit needs doing regardless because we
1404  * should re-deform).
1405  */
1406  DEG_id_tag_update(&me->id, 0);
1407 
1409 
1410  WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
1411 
1413 
1414  return OPERATOR_FINISHED;
1415 }
1416 
1418 {
1420  if (ob == NULL || ob->type != OB_MESH) {
1421  return false;
1422  }
1423  if (!ob->data || ID_IS_LINKED(ob->data)) {
1424  return false;
1425  }
1426  return true;
1427 }
1428 
1430 {
1431 
1432  /* identifiers */
1433  ot->name = "Weight Paint Mode";
1434  ot->idname = "PAINT_OT_weight_paint_toggle";
1435  ot->description = "Toggle weight paint mode in 3D view";
1436 
1437  /* api callbacks */
1440 
1441  /* flags */
1443 }
1444 
1447 /* -------------------------------------------------------------------- */
1451 struct WPaintData {
1454 
1456 
1457  /* variables for auto normalize */
1458  const bool *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
1459  const bool *lock_flags;
1460  const bool *vgroup_locked; /* mask of locked defbones */
1461  const bool *vgroup_unlocked; /* mask of unlocked defbones */
1462 
1463  /* variables for multipaint */
1464  const bool *defbase_sel; /* set of selected groups */
1465  int defbase_tot_sel; /* number of selected groups */
1466  bool do_multipaint; /* true if multipaint enabled and multiple groups selected */
1468 
1470 
1471  /* original weight values for use in blur/smear */
1474 };
1475 
1476 /* Initialize the stroke cache invariants from operator properties */
1478  bContext *C, const VPaint *vp, SculptSession *ss, wmOperator *op, const float mouse[2])
1479 {
1480  StrokeCache *cache;
1483  const Brush *brush = vp->paint.brush;
1486  float mat[3][3];
1487  float view_dir[3] = {0.0f, 0.0f, 1.0f};
1488  int mode;
1489 
1490  /* VW paint needs to allocate stroke cache before update is called. */
1491  if (!ss->cache) {
1492  cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
1493  ss->cache = cache;
1494  }
1495  else {
1496  cache = ss->cache;
1497  }
1498 
1499  /* Initial mouse location */
1500  if (mouse) {
1501  copy_v2_v2(cache->initial_mouse, mouse);
1502  }
1503  else {
1504  zero_v2(cache->initial_mouse);
1505  }
1506 
1507  mode = RNA_enum_get(op->ptr, "mode");
1508  cache->invert = mode == BRUSH_STROKE_INVERT;
1509  cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
1510  /* not very nice, but with current events system implementation
1511  * we can't handle brush appearance inversion hotkey separately (sergey) */
1512  if (cache->invert) {
1513  ups->draw_inverted = true;
1514  }
1515  else {
1516  ups->draw_inverted = false;
1517  }
1518 
1519  copy_v2_v2(cache->mouse, cache->initial_mouse);
1520  /* Truly temporary data that isn't stored in properties */
1521  cache->vc = vc;
1522  cache->brush = brush;
1523  cache->first_time = 1;
1524 
1525  /* cache projection matrix */
1526  ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
1527 
1528  invert_m4_m4(ob->imat, ob->obmat);
1529  copy_m3_m4(mat, cache->vc->rv3d->viewinv);
1530  mul_m3_v3(mat, view_dir);
1531  copy_m3_m4(mat, ob->imat);
1532  mul_m3_v3(mat, view_dir);
1533  normalize_v3_v3(cache->true_view_normal, view_dir);
1534 
1535  copy_v3_v3(cache->view_normal, cache->true_view_normal);
1536  cache->bstrength = BKE_brush_alpha_get(scene, brush);
1537  cache->is_last_valid = false;
1538 }
1539 
1540 /* Initialize the stroke cache variants from operator properties */
1542 {
1544  SculptSession *ss = ob->sculpt;
1545  StrokeCache *cache = ss->cache;
1546  Brush *brush = BKE_paint_brush(&vp->paint);
1547 
1548  /* This effects the actual brush radius, so things farther away
1549  * are compared with a larger radius and vice versa. */
1550  if (cache->first_time) {
1551  RNA_float_get_array(ptr, "location", cache->true_location);
1552  }
1553 
1554  RNA_float_get_array(ptr, "mouse", cache->mouse);
1555 
1556  /* XXX: Use pressure value from first brush step for brushes which don't
1557  * support strokes (grab, thumb). They depends on initial state and
1558  * brush coord/pressure/etc.
1559  * It's more an events design issue, which doesn't split coordinate/pressure/angle
1560  * changing events. We should avoid this after events system re-design */
1562  cache->pressure = RNA_float_get(ptr, "pressure");
1563  }
1564 
1565  /* Truly temporary data that isn't stored in properties */
1566  if (cache->first_time) {
1568  cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
1570  }
1571 
1572  if (BKE_brush_use_size_pressure(brush) &&
1574  cache->radius = cache->initial_radius * cache->pressure;
1575  }
1576  else {
1577  cache->radius = cache->initial_radius;
1578  }
1579 
1580  cache->radius_squared = cache->radius * cache->radius;
1581 
1582  if (ss->pbvh) {
1584  }
1585 }
1586 
1587 static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
1588 {
1590  struct PaintStroke *stroke = op->customdata;
1593  Mesh *me = BKE_mesh_from_object(ob);
1594  struct WPaintData *wpd;
1595  struct WPaintVGroupIndex vgroup_index;
1596  int defbase_tot, defbase_tot_sel;
1597  bool *defbase_sel;
1598  SculptSession *ss = ob->sculpt;
1601 
1602  if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
1603  return false;
1604  }
1605 
1606  {
1607  /* check if we are attempting to paint onto a locked vertex group,
1608  * and other options disallow it from doing anything useful */
1609  bDeformGroup *dg;
1610  dg = BLI_findlink(&ob->defbase, vgroup_index.active);
1611  if (dg->flag & DG_LOCK_WEIGHT) {
1612  BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
1613  return false;
1614  }
1615  if (vgroup_index.mirror != -1) {
1616  dg = BLI_findlink(&ob->defbase, vgroup_index.mirror);
1617  if (dg->flag & DG_LOCK_WEIGHT) {
1618  BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting");
1619  return false;
1620  }
1621  }
1622  }
1623 
1624  /* check that multipaint groups are unlocked */
1625  defbase_tot = BLI_listbase_count(&ob->defbase);
1626  defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel);
1627 
1628  if (ts->multipaint && defbase_tot_sel > 1) {
1629  int i;
1630  bDeformGroup *dg;
1631 
1634  ob, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
1635  }
1636 
1637  for (i = 0; i < defbase_tot; i++) {
1638  if (defbase_sel[i]) {
1639  dg = BLI_findlink(&ob->defbase, i);
1640  if (dg->flag & DG_LOCK_WEIGHT) {
1641  BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting");
1642  MEM_freeN(defbase_sel);
1643  return false;
1644  }
1645  }
1646  }
1647  }
1648 
1649  /* ALLOCATIONS! no return after this line */
1650  /* make mode data storage */
1651  wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
1652  paint_stroke_set_mode_data(stroke, wpd);
1655  vp->paint.brush->falloff_angle,
1656  (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
1657 
1658  wpd->active.index = vgroup_index.active;
1659  wpd->mirror.index = vgroup_index.mirror;
1660 
1661  /* multipaint */
1662  wpd->defbase_tot = defbase_tot;
1663  wpd->defbase_sel = defbase_sel;
1664  wpd->defbase_tot_sel = defbase_tot_sel > 1 ? defbase_tot_sel : 1;
1665  wpd->do_multipaint = (ts->multipaint && defbase_tot_sel > 1);
1666 
1667  /* set up auto-normalize, and generate map for detecting which
1668  * vgroups affect deform bones */
1670  if (ts->auto_normalize || ts->multipaint || wpd->lock_flags || ts->wpaint_lock_relative) {
1672  }
1673 
1674  /* Compute the set of all locked deform groups when Lock Relative is active. */
1675  if (ts->wpaint_lock_relative &&
1677  wpd->lock_flags, wpd->vgroup_validmap, wpd->active.index) &&
1679  defbase_tot, wpd->lock_flags, defbase_sel, defbase_tot_sel))) {
1680  wpd->do_lock_relative = true;
1681  }
1682 
1683  if (wpd->do_lock_relative || (ts->auto_normalize && wpd->lock_flags && !wpd->do_multipaint)) {
1684  bool *unlocked = MEM_dupallocN(wpd->vgroup_validmap);
1685 
1686  if (wpd->lock_flags) {
1687  bool *locked = MEM_mallocN(sizeof(bool) * wpd->defbase_tot, __func__);
1689  wpd->defbase_tot, wpd->lock_flags, wpd->vgroup_validmap, locked, unlocked);
1690  wpd->vgroup_locked = locked;
1691  }
1692 
1693  wpd->vgroup_unlocked = unlocked;
1694  }
1695 
1696  if (wpd->do_multipaint && ts->auto_normalize) {
1697  bool *tmpflags;
1698  tmpflags = MEM_mallocN(sizeof(bool) * defbase_tot, __func__);
1699  if (wpd->lock_flags) {
1700  BLI_array_binary_or(tmpflags, wpd->defbase_sel, wpd->lock_flags, wpd->defbase_tot);
1701  }
1702  else {
1703  memcpy(tmpflags, wpd->defbase_sel, sizeof(*tmpflags) * wpd->defbase_tot);
1704  }
1705  wpd->active.lock = tmpflags;
1706  }
1707  else if (ts->auto_normalize) {
1708  bool *tmpflags;
1709 
1710  tmpflags = wpd->lock_flags ? MEM_dupallocN(wpd->lock_flags) :
1711  MEM_callocN(sizeof(bool) * defbase_tot, __func__);
1712  tmpflags[wpd->active.index] = true;
1713  wpd->active.lock = tmpflags;
1714 
1715  tmpflags = wpd->lock_flags ? MEM_dupallocN(wpd->lock_flags) :
1716  MEM_callocN(sizeof(bool) * defbase_tot, __func__);
1717  tmpflags[(wpd->mirror.index != -1) ? wpd->mirror.index : wpd->active.index] = true;
1718  wpd->mirror.lock = tmpflags;
1719  }
1720 
1722  wpd->precomputed_weight = MEM_mallocN(sizeof(float) * me->totvert, __func__);
1723  }
1724 
1725  /* If not previously created, create vertex/weight paint mode session data */
1727  vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
1729 
1730  if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
1731  MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
1732  for (int i = 0; i < me->totvert; i++, dv++) {
1733  /* Use to show this isn't initialized, never apply to the mesh data. */
1734  dv->flag = 1;
1735  }
1736  }
1737 
1738  return true;
1739 }
1740 
1741 static float dot_vf3vs3(const float brushNormal[3], const short vertexNormal[3])
1742 {
1743  float normal[3];
1744  normal_short_to_float_v3(normal, vertexNormal);
1745  return dot_v3v3(brushNormal, normal);
1746 }
1747 
1748 static void get_brush_alpha_data(const Scene *scene,
1749  const SculptSession *ss,
1750  const Brush *brush,
1751  float *r_brush_size_pressure,
1752  float *r_brush_alpha_value,
1753  float *r_brush_alpha_pressure)
1754 {
1755  *r_brush_size_pressure = BKE_brush_size_get(scene, brush) *
1756  (BKE_brush_use_size_pressure(brush) ? ss->cache->pressure : 1.0f);
1757  *r_brush_alpha_value = BKE_brush_alpha_get(scene, brush);
1758  *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(brush) ? ss->cache->pressure : 1.0f);
1759 }
1760 
1761 static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi)
1762 {
1763  float weight;
1764 
1765  if (wpi->do_multipaint) {
1767  dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->is_normalized);
1768  }
1769  else {
1770  weight = BKE_defvert_find_weight(dv, wpi->active.index);
1771  }
1772 
1773  if (wpi->do_lock_relative) {
1775  weight, dv, wpi->defbase_tot, wpi->vgroup_locked, wpi->vgroup_unlocked);
1776  }
1777 
1778  CLAMP(weight, 0.0f, 1.0f);
1779  return weight;
1780 }
1781 
1782 static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata,
1783  const int n,
1784  const TaskParallelTLS *__restrict UNUSED(tls))
1785 {
1786  SculptThreadedTaskData *data = userdata;
1787  const MDeformVert *dv = &data->me->dvert[n];
1788 
1789  data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi);
1790 }
1791 
1793  bContext *C, Object *ob, Brush *brush, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me)
1794 {
1795  if (wpd->precomputed_weight_ready && !brush_use_accumulate_ex(brush, ob->mode)) {
1796  return;
1797  }
1798 
1799  /* threaded loop over vertices */
1801  .C = C,
1802  .ob = ob,
1803  .wpd = wpd,
1804  .wpi = wpi,
1805  .me = me,
1806  };
1807 
1808  TaskParallelSettings settings;
1811 
1812  wpd->precomputed_weight_ready = true;
1813 }
1814 
1815 static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
1816  const int n,
1817  const TaskParallelTLS *__restrict UNUSED(tls))
1818 {
1819  SculptThreadedTaskData *data = userdata;
1820  SculptSession *ss = data->ob->sculpt;
1821  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
1822  const bool has_grids = (pbvh_type == PBVH_GRIDS);
1823  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
1824 
1825  const Brush *brush = data->brush;
1826  const StrokeCache *cache = ss->cache;
1827  Scene *scene = CTX_data_scene(data->C);
1828 
1829  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
1831  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
1832  const bool use_normal = vwpaint_use_normal(data->vp);
1833  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1834  const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1835 
1836  SculptBrushTest test;
1838  ss, &test, data->brush->falloff_shape);
1839  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
1840  ss, data->brush->falloff_shape);
1841 
1842  /* For each vertex */
1843  PBVHVertexIter vd;
1844  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
1845  /* Test to see if the vertex coordinates are within the spherical brush region. */
1846  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
1847  /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
1848  * Otherwise, take the current vert. */
1849  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
1850  vd.vert_indices[vd.i];
1851  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
1852  const char v_flag = data->me->mvert[v_index].flag;
1853  /* If the vertex is selected */
1854  if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
1855  /* Get the average poly weight */
1856  int total_hit_loops = 0;
1857  float weight_final = 0.0f;
1858  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
1859  const int p_index = gmap->vert_to_poly[v_index].indices[j];
1860  const MPoly *mp = &data->me->mpoly[p_index];
1861 
1862  total_hit_loops += mp->totloop;
1863  for (int k = 0; k < mp->totloop; k++) {
1864  const int l_index = mp->loopstart + k;
1865  const MLoop *ml = &data->me->mloop[l_index];
1866  weight_final += data->wpd->precomputed_weight[ml->v];
1867  }
1868  }
1869 
1870  /* Apply the weight to the vertex. */
1871  if (total_hit_loops != 0) {
1872  float brush_strength = cache->bstrength;
1873  const float angle_cos = (use_normal && vd.no) ?
1874  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
1875  1.0f;
1876  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
1877  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
1879  &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
1880  const float brush_fade = BKE_brush_curve_strength(
1881  brush, sqrtf(test.dist), cache->radius);
1882  const float final_alpha = brush_fade * brush_strength * grid_alpha *
1883  brush_alpha_pressure;
1884 
1885  if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
1886  if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
1887  ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
1888  }
1889  else {
1890  continue;
1891  }
1892  }
1893 
1894  weight_final /= total_hit_loops;
1895  /* Only paint visible verts */
1897  data->vp, data->ob, data->wpi, v_index, final_alpha, weight_final);
1898  }
1899  }
1900  }
1901  }
1902  }
1904 }
1905 
1906 static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
1907  const int n,
1908  const TaskParallelTLS *__restrict UNUSED(tls))
1909 {
1910  SculptThreadedTaskData *data = userdata;
1911  SculptSession *ss = data->ob->sculpt;
1912  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
1913  const bool has_grids = (pbvh_type == PBVH_GRIDS);
1914  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
1915 
1916  const Brush *brush = data->brush;
1917  const Scene *scene = CTX_data_scene(data->C);
1918  const StrokeCache *cache = ss->cache;
1919  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
1921  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
1922  const bool use_normal = vwpaint_use_normal(data->vp);
1923  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1924  const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1925  float brush_dir[3];
1926 
1927  sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
1928  project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
1929 
1930  if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
1931 
1932  SculptBrushTest test;
1934  ss, &test, data->brush->falloff_shape);
1935  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
1936  ss, data->brush->falloff_shape);
1937 
1938  /* For each vertex */
1939  PBVHVertexIter vd;
1940  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
1941  /* Test to see if the vertex coordinates are within the spherical brush region. */
1942  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
1943  /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
1944  * Otherwise, take the current vert. */
1945  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
1946  vd.vert_indices[vd.i];
1947  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
1948  const MVert *mv_curr = &data->me->mvert[v_index];
1949 
1950  /* If the vertex is selected */
1951  if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
1952  float brush_strength = cache->bstrength;
1953  const float angle_cos = (use_normal && vd.no) ?
1954  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
1955  1.0f;
1956  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
1957  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
1959  &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
1960  bool do_color = false;
1961  /* Minimum dot product between brush direction and current
1962  * to neighbor direction is 0.0, meaning orthogonal. */
1963  float stroke_dot_max = 0.0f;
1964 
1965  /* Get the color of the loop in the opposite direction of the brush movement
1966  * (this callback is specifically for smear.) */
1967  float weight_final = 0.0;
1968  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
1969  const int p_index = gmap->vert_to_poly[v_index].indices[j];
1970  const MPoly *mp = &data->me->mpoly[p_index];
1971  const MLoop *ml_other = &data->me->mloop[mp->loopstart];
1972  for (int k = 0; k < mp->totloop; k++, ml_other++) {
1973  const uint v_other_index = ml_other->v;
1974  if (v_other_index != v_index) {
1975  const MVert *mv_other = &data->me->mvert[v_other_index];
1976 
1977  /* Get the direction from the selected vert to the neighbor. */
1978  float other_dir[3];
1979  sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
1980  project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
1981 
1982  normalize_v3(other_dir);
1983 
1984  const float stroke_dot = dot_v3v3(other_dir, brush_dir);
1985 
1986  if (stroke_dot > stroke_dot_max) {
1987  stroke_dot_max = stroke_dot;
1988  weight_final = data->wpd->precomputed_weight[v_other_index];
1989  do_color = true;
1990  }
1991  }
1992  }
1993  }
1994  /* Apply weight to vertex */
1995  if (do_color) {
1996  const float brush_fade = BKE_brush_curve_strength(
1997  brush, sqrtf(test.dist), cache->radius);
1998  const float final_alpha = brush_fade * brush_strength * grid_alpha *
1999  brush_alpha_pressure;
2000 
2001  if (final_alpha <= 0.0f) {
2002  continue;
2003  }
2004 
2006  data->vp, data->ob, data->wpi, v_index, final_alpha, (float)weight_final);
2007  }
2008  }
2009  }
2010  }
2011  }
2013  }
2014 }
2015 
2016 static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
2017  const int n,
2018  const TaskParallelTLS *__restrict UNUSED(tls))
2019 {
2020  SculptThreadedTaskData *data = userdata;
2021  SculptSession *ss = data->ob->sculpt;
2022  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
2023  const bool has_grids = (pbvh_type == PBVH_GRIDS);
2024  const Scene *scene = CTX_data_scene(data->C);
2025 
2026  const Brush *brush = data->brush;
2027  const StrokeCache *cache = ss->cache;
2028  /* note: normally `BKE_brush_weight_get(scene, brush)` is used,
2029  * however in this case we calculate a new weight each time. */
2030  const float paintweight = data->strength;
2031  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2033  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2034  const bool use_normal = vwpaint_use_normal(data->vp);
2035  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2036  const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
2037 
2038  SculptBrushTest test;
2040  ss, &test, data->brush->falloff_shape);
2041  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
2042  ss, data->brush->falloff_shape);
2043 
2044  /* For each vertex */
2045  PBVHVertexIter vd;
2046  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
2047  /* Test to see if the vertex coordinates are within the spherical brush region. */
2048  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
2049  /* Note: grids are 1:1 with corners (aka loops).
2050  * For multires, take the vert whose loop corresponds to the current grid.
2051  * Otherwise, take the current vert. */
2052  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
2053  vd.vert_indices[vd.i];
2054  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
2055 
2056  const char v_flag = data->me->mvert[v_index].flag;
2057  /* If the vertex is selected */
2058  if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
2059  float brush_strength = cache->bstrength;
2060  const float angle_cos = (use_normal && vd.no) ?
2061  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
2062  1.0f;
2063  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
2064  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
2066  &data->wpd->normal_angle_precalc, angle_cos, &brush_strength))) {
2067  const float brush_fade = BKE_brush_curve_strength(
2068  brush, sqrtf(test.dist), cache->radius);
2069  const float final_alpha = brush_fade * brush_strength * grid_alpha *
2070  brush_alpha_pressure;
2071 
2072  if ((brush->flag & BRUSH_ACCUMULATE) == 0) {
2073  if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
2074  ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
2075  }
2076  else {
2077  continue;
2078  }
2079  }
2080 
2081  do_weight_paint_vertex(data->vp, data->ob, data->wpi, v_index, final_alpha, paintweight);
2082  }
2083  }
2084  }
2085  }
2087 }
2088 
2090  void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
2091 {
2092  SculptThreadedTaskData *data = userdata;
2093  SculptSession *ss = data->ob->sculpt;
2094  StrokeCache *cache = ss->cache;
2095  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
2096  const bool has_grids = (pbvh_type == PBVH_GRIDS);
2097 
2098  const bool use_normal = vwpaint_use_normal(data->vp);
2099  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2100  const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
2101 
2102  struct WPaintAverageAccum *accum = (struct WPaintAverageAccum *)data->custom_data + n;
2103  accum->len = 0;
2104  accum->value = 0.0;
2105 
2106  SculptBrushTest test;
2108  ss, &test, data->brush->falloff_shape);
2109  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
2110  ss, data->brush->falloff_shape);
2111 
2112  /* For each vertex */
2113  PBVHVertexIter vd;
2114  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
2115  /* Test to see if the vertex coordinates are within the spherical brush region. */
2116  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
2117  const float angle_cos = (use_normal && vd.no) ? dot_vf3vs3(sculpt_normal_frontface, vd.no) :
2118  1.0f;
2119  if (angle_cos > 0.0 &&
2120  BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
2121  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
2122  vd.vert_indices[vd.i];
2123  // const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
2124  const char v_flag = data->me->mvert[v_index].flag;
2125 
2126  /* If the vertex is selected. */
2127  if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
2128  const MDeformVert *dv = &data->me->dvert[v_index];
2129  accum->len += 1;
2130  accum->value += wpaint_get_active_weight(dv, data->wpi);
2131  }
2132  }
2133  }
2134  }
2136 }
2137 
2139  PBVHNode **UNUSED(nodes),
2140  int totnode)
2141 {
2142  struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
2143  data->custom_data = accum;
2144 
2145  TaskParallelSettings settings;
2146  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
2148 
2149  uint accum_len = 0;
2150  double accum_weight = 0.0;
2151  for (int i = 0; i < totnode; i++) {
2152  accum_len += accum[i].len;
2153  accum_weight += accum[i].value;
2154  }
2155  if (accum_len != 0) {
2156  accum_weight /= accum_len;
2157  data->strength = (float)accum_weight;
2158  }
2159 
2160  MEM_SAFE_FREE(data->custom_data); /* 'accum' */
2161 }
2162 
2164  Object *ob,
2165  Sculpt *sd,
2166  VPaint *vp,
2167  struct WPaintData *wpd,
2168  WeightPaintInfo *wpi,
2169  Mesh *me,
2170  PBVHNode **nodes,
2171  int totnode)
2172 {
2174  const Brush *brush = ob->sculpt->cache->brush;
2175 
2176  /* threaded loop over nodes */
2178  .C = C,
2179  .sd = sd,
2180  .ob = ob,
2181  .brush = brush,
2182  .nodes = nodes,
2183  .vp = vp,
2184  .wpd = wpd,
2185  .wpi = wpi,
2186  .me = me,
2187  };
2188 
2189  /* Use this so average can modify its weight without touching the brush. */
2190  data.strength = BKE_brush_weight_get(scene, brush);
2191 
2192  /* NOTE: current mirroring code cannot be run in parallel */
2193  TaskParallelSettings settings;
2194  const bool use_threading = !ME_USING_MIRROR_X_VERTEX_GROUPS(me);
2195  BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode);
2196 
2197  switch ((eBrushWeightPaintTool)brush->weightpaint_tool) {
2198  case WPAINT_TOOL_AVERAGE:
2199  calculate_average_weight(&data, nodes, totnode);
2201  break;
2202  case WPAINT_TOOL_SMEAR:
2204  break;
2205  case WPAINT_TOOL_BLUR:
2207  break;
2208  case WPAINT_TOOL_DRAW:
2210  break;
2211  }
2212 }
2213 
2215  Object *ob, VPaint *wp, Sculpt *sd, Brush *brush, int *r_totnode)
2216 {
2217  SculptSession *ss = ob->sculpt;
2218  const bool use_normal = vwpaint_use_normal(wp);
2219  PBVHNode **nodes = NULL;
2220 
2221  /* Build a list of all nodes that are potentially within the brush's area of influence */
2222  if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
2224  .ss = ss,
2225  .sd = sd,
2226  .radius_squared = ss->cache->radius_squared,
2227  .original = true,
2228  };
2229  BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
2230  if (use_normal) {
2232  brush, ob, nodes, *r_totnode, true, ss->cache->sculpt_normal_symm);
2233  }
2234  else {
2236  }
2237  }
2238  else {
2239  struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
2241  &dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
2243  .ss = ss,
2244  .sd = sd,
2245  .radius_squared = ss->cache->radius_squared,
2246  .original = true,
2247  .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
2248  };
2249  BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode);
2250  if (use_normal) {
2252  }
2253  else {
2255  }
2256  }
2257  return nodes;
2258 }
2259 
2261  Object *ob,
2262  VPaint *wp,
2263  Sculpt *sd,
2264  struct WPaintData *wpd,
2265  WeightPaintInfo *wpi,
2266  Mesh *me,
2267  Brush *brush,
2268  const char symm,
2269  const int axis,
2270  const int i,
2271  const float angle)
2272 {
2273  SculptSession *ss = ob->sculpt;
2274  ss->cache->radial_symmetry_pass = i;
2275  SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
2276 
2277  int totnode;
2278  PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, wp, sd, brush, &totnode);
2279 
2280  wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes, totnode);
2281 
2282  if (nodes) {
2283  MEM_freeN(nodes);
2284  }
2285 }
2286 
2288  Object *ob,
2289  VPaint *wp,
2290  Sculpt *sd,
2291  struct WPaintData *wpd,
2292  WeightPaintInfo *wpi,
2293  Mesh *me,
2294  Brush *brush,
2295  const char symm,
2296  const int axis)
2297 {
2298  for (int i = 1; i < wp->radial_symm[axis - 'X']; i++) {
2299  const float angle = (2.0 * M_PI) * i / wp->radial_symm[axis - 'X'];
2300  wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, axis, i, angle);
2301  }
2302 }
2303 
2304 /* near duplicate of: sculpt.c's,
2305  * 'do_symmetrical_brush_actions' and 'vpaint_do_symmetrical_brush_actions'. */
2307  bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi)
2308 {
2309  Brush *brush = BKE_paint_brush(&wp->paint);
2310  Mesh *me = ob->data;
2311  SculptSession *ss = ob->sculpt;
2312  StrokeCache *cache = ss->cache;
2313  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
2314  int i = 0;
2315 
2316  /* initial stroke */
2317  cache->mirror_symmetry_pass = 0;
2318  wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X', 0, 0);
2319  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X');
2320  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Y');
2321  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Z');
2322 
2323  cache->symmetry = symm;
2324 
2326  /* We don't do any symmetry strokes when mirroring vertex groups. */
2328  cache->is_last_valid = true;
2329  return;
2330  }
2331 
2332  /* symm is a bit combination of XYZ - 1 is mirror
2333  * X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
2334  for (i = 1; i <= symm; i++) {
2335  if ((symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
2336  cache->mirror_symmetry_pass = i;
2337  cache->radial_symmetry_pass = 0;
2338  SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
2339 
2340  if (i & (1 << 0)) {
2341  wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
2342  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X');
2343  }
2344  if (i & (1 << 1)) {
2345  wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y', 0, 0);
2346  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y');
2347  }
2348  if (i & (1 << 2)) {
2349  wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z', 0, 0);
2350  wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z');
2351  }
2352  }
2353  }
2355  cache->is_last_valid = true;
2356 }
2357 
2358 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2359 {
2362  VPaint *wp = ts->wpaint;
2363  Brush *brush = BKE_paint_brush(&wp->paint);
2364  struct WPaintData *wpd = paint_stroke_mode_data(stroke);
2365  ViewContext *vc;
2367 
2368  SculptSession *ss = ob->sculpt;
2370 
2371  vwpaint_update_cache_variants(C, wp, ob, itemptr);
2372 
2373  float mat[4][4];
2374 
2375  const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
2376 
2377  /* intentionally don't initialize as NULL, make sure we initialize all members below */
2378  WeightPaintInfo wpi;
2379 
2380  /* cannot paint if there is no stroke data */
2381  if (wpd == NULL) {
2382  /* XXX: force a redraw here, since even though we can't paint,
2383  * at least view won't freeze until stroke ends */
2385  return;
2386  }
2387 
2388  vc = &wpd->vc;
2389  ob = vc->obact;
2390 
2393 
2394  /* load projection matrix */
2395  mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
2396 
2397  /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
2398  wpi.defbase_tot = wpd->defbase_tot;
2399  wpi.defbase_sel = wpd->defbase_sel;
2400  wpi.defbase_tot_sel = wpd->defbase_tot_sel;
2401 
2403  wpi.active = wpd->active;
2404  wpi.mirror = wpd->mirror;
2405  wpi.lock_flags = wpd->lock_flags;
2406  wpi.vgroup_validmap = wpd->vgroup_validmap;
2407  wpi.vgroup_locked = wpd->vgroup_locked;
2408  wpi.vgroup_unlocked = wpd->vgroup_unlocked;
2409  wpi.do_flip = RNA_boolean_get(itemptr, "pen_flip");
2410  wpi.do_multipaint = wpd->do_multipaint;
2411  wpi.do_auto_normalize = ((ts->auto_normalize != 0) && (wpi.vgroup_validmap != NULL) &&
2412  (wpi.do_multipaint || wpi.vgroup_validmap[wpi.active.index]));
2415  wpi.brush_alpha_value = brush_alpha_value;
2416  /* *** done setting up WeightPaintInfo *** */
2417 
2418  if (wpd->precomputed_weight) {
2419  precompute_weight_values(C, ob, brush, wpd, &wpi, ob->data);
2420  }
2421 
2422  wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi);
2423 
2424  swap_m4m4(vc->rv3d->persmat, mat);
2425 
2426  /* Calculate pivot for rotation around selection if needed.
2427  * also needed for "Frame Selected" on last stroke. */
2428  float loc_world[3];
2429  mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
2430  paint_last_stroke_update(scene, loc_world);
2431 
2433 
2434  DEG_id_tag_update(ob->data, 0);
2436  swap_m4m4(wpd->vc.rv3d->persmat, mat);
2437 
2438  rcti r;
2440  if (ss->cache) {
2441  ss->cache->current_r = r;
2442  }
2443 
2444  /* previous is not set in the current cache else
2445  * the partial rect will always grow */
2446  if (ss->cache) {
2447  if (!BLI_rcti_is_empty(&ss->cache->previous_r)) {
2448  BLI_rcti_union(&r, &ss->cache->previous_r);
2449  }
2450  }
2451 
2452  r.xmin += vc->region->winrct.xmin - 2;
2453  r.xmax += vc->region->winrct.xmin + 2;
2454  r.ymin += vc->region->winrct.ymin - 2;
2455  r.ymax += vc->region->winrct.ymin + 2;
2456  }
2458 }
2459 
2460 static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
2461 {
2463  struct WPaintData *wpd = paint_stroke_mode_data(stroke);
2464 
2465  if (wpd) {
2466  if (wpd->defbase_sel) {
2467  MEM_freeN((void *)wpd->defbase_sel);
2468  }
2469  if (wpd->vgroup_validmap) {
2470  MEM_freeN((void *)wpd->vgroup_validmap);
2471  }
2472  if (wpd->vgroup_locked) {
2473  MEM_freeN((void *)wpd->vgroup_locked);
2474  }
2475  if (wpd->vgroup_unlocked) {
2476  MEM_freeN((void *)wpd->vgroup_unlocked);
2477  }
2478  if (wpd->lock_flags) {
2479  MEM_freeN((void *)wpd->lock_flags);
2480  }
2481  if (wpd->active.lock) {
2482  MEM_freeN((void *)wpd->active.lock);
2483  }
2484  if (wpd->mirror.lock) {
2485  MEM_freeN((void *)wpd->mirror.lock);
2486  }
2487  if (wpd->precomputed_weight) {
2489  }
2490 
2491  MEM_freeN(wpd);
2492  }
2493 
2494  /* and particles too */
2495  if (ob->particlesystem.first) {
2496  ParticleSystem *psys;
2497  int i;
2498 
2499  for (psys = ob->particlesystem.first; psys; psys = psys->next) {
2500  for (i = 0; i < PSYS_TOT_VG; i++) {
2501  if (psys->vgroup[i] == ob->actdef) {
2502  psys->recalc |= ID_RECALC_PSYS_RESET;
2503  break;
2504  }
2505  }
2506  }
2507  }
2508 
2509  DEG_id_tag_update(ob->data, 0);
2510 
2512 
2514  ob->sculpt->cache = NULL;
2515 }
2516 
2517 static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2518 {
2519  int retval;
2520 
2522  op,
2526  NULL,
2528  event->type);
2529 
2530  if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
2531  paint_stroke_free(C, op);
2532  return OPERATOR_FINISHED;
2533  }
2534  /* add modal handler */
2536 
2537  OPERATOR_RETVAL_CHECK(retval);
2539 
2540  return OPERATOR_RUNNING_MODAL;
2541 }
2542 
2544 {
2546  op,
2550  NULL,
2552  0);
2553 
2554  /* frees op->customdata */
2555  paint_stroke_exec(C, op);
2556 
2557  return OPERATOR_FINISHED;
2558 }
2559 
2561 {
2563  if (ob->sculpt->cache) {
2565  ob->sculpt->cache = NULL;
2566  }
2567 
2568  paint_stroke_cancel(C, op);
2569 }
2570 
2572 {
2573  /* identifiers */
2574  ot->name = "Weight Paint";
2575  ot->idname = "PAINT_OT_weight_paint";
2576  ot->description = "Paint a stroke in the current vertex group's weights";
2577 
2578  /* api callbacks */
2579  ot->invoke = wpaint_invoke;
2581  ot->exec = wpaint_exec;
2583  ot->cancel = wpaint_cancel;
2584 
2585  /* flags */
2587 
2589 }
2590 
2593 /* -------------------------------------------------------------------- */
2601 {
2602  Main *bmain = CTX_data_main(C);
2603  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
2605  const int mode_flag = OB_MODE_VERTEX_PAINT;
2606  const bool is_mode_set = (ob->mode & mode_flag) != 0;
2609 
2610  if (!is_mode_set) {
2611  if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
2612  return OPERATOR_CANCELLED;
2613  }
2614  }
2615 
2616  Mesh *me = BKE_mesh_from_object(ob);
2617 
2618  /* toggle: end vpaint */
2619  if (is_mode_set) {
2621  }
2622  else {
2624  if (depsgraph) {
2626  }
2629  }
2630 
2632 
2633  /* update modifier stack for mapping requirements */
2634  DEG_id_tag_update(&me->id, 0);
2635 
2637 
2638  WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
2639 
2641 
2642  return OPERATOR_FINISHED;
2643 }
2644 
2646 {
2647  /* identifiers */
2648  ot->name = "Vertex Paint Mode";
2649  ot->idname = "PAINT_OT_vertex_paint_toggle";
2650  ot->description = "Toggle the vertex paint mode in 3D view";
2651 
2652  /* api callbacks */
2655 
2656  /* flags */
2658 }
2659 
2662 /* -------------------------------------------------------------------- */
2666 /* Implementation notes:
2667  *
2668  * Operator->invoke()
2669  * - Validate context (add #Mesh.mloopcol).
2670  * - Create custom-data storage.
2671  * - Call paint once (mouse click).
2672  * - Add modal handler.
2673  *
2674  * Operator->modal()
2675  * - For every mouse-move, apply vertex paint.
2676  * - Exit on mouse release, free custom-data.
2677  * (return OPERATOR_FINISHED also removes handler and operator)
2678  *
2679  * For future:
2680  * - implement a stroke event (or mouse-move with past positions).
2681  * - revise whether op->customdata should be added in object, in set_vpaint.
2682  */
2683 
2684 struct VPaintData {
2687 
2689 
2692 
2698 
2699  /* loops tagged as having been painted, to apply shared vertex color
2700  * blending only to modified loops */
2701  bool *mlooptag;
2702 
2704 
2705  /* Special storage for smear brush, avoid feedback loop - update each step. */
2706  struct {
2710 };
2711 
2712 static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
2713 {
2716  struct PaintStroke *stroke = op->customdata;
2717  VPaint *vp = ts->vpaint;
2718  Brush *brush = BKE_paint_brush(&vp->paint);
2719  struct VPaintData *vpd;
2721  Mesh *me;
2722  SculptSession *ss = ob->sculpt;
2724 
2725  /* context checks could be a poll() */
2726  me = BKE_mesh_from_object(ob);
2727  if (me == NULL || me->totpoly == 0) {
2728  return false;
2729  }
2730 
2732  if (me->mloopcol == NULL) {
2733  return false;
2734  }
2735 
2736  /* make mode data storage */
2737  vpd = MEM_callocN(sizeof(*vpd), "VPaintData");
2738  paint_stroke_set_mode_data(stroke, vpd);
2741  vp->paint.brush->falloff_angle,
2742  (vp->paint.brush->flag & BRUSH_FRONTFACE_FALLOFF) != 0);
2743 
2745  scene, vp, (RNA_enum_get(op->ptr, "mode") == BRUSH_STROKE_INVERT));
2746 
2747  vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex;
2748 
2749  /* are we painting onto a modified mesh?,
2750  * if not we can skip face map trickiness */
2752  vpd->use_fast_update = true;
2753  /* printf("Fast update!\n");*/
2754  }
2755  else {
2756  vpd->use_fast_update = false;
2757  /* printf("No fast update!\n");*/
2758  }
2759 
2760  /* to keep tracked of modified loops for shared vertex color blending */
2761  if (brush->vertexpaint_tool == VPAINT_TOOL_BLUR) {
2762  vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
2763  }
2764 
2765  if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) {
2766  vpd->smear.color_prev = MEM_mallocN(sizeof(uint) * me->totloop, __func__);
2767  memcpy(vpd->smear.color_prev, me->mloopcol, sizeof(uint) * me->totloop);
2769  }
2770 
2771  /* Create projection handle */
2772  if (vpd->is_texbrush) {
2773  ob->sculpt->building_vp_handle = true;
2775  ob->sculpt->building_vp_handle = false;
2776  }
2777 
2778  /* If not previously created, create vertex/weight paint mode session data */
2780  vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
2782 
2783  if (ob->sculpt->mode.vpaint.previous_color != NULL) {
2784  memset(ob->sculpt->mode.vpaint.previous_color, 0, sizeof(uint) * me->totloop);
2785  }
2786 
2787  return true;
2788 }
2789 
2790 static void do_vpaint_brush_calc_average_color_cb_ex(void *__restrict userdata,
2791  const int n,
2792  const TaskParallelTLS *__restrict UNUSED(tls))
2793 {
2794  SculptThreadedTaskData *data = userdata;
2795  SculptSession *ss = data->ob->sculpt;
2796  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
2797  const bool has_grids = (pbvh_type == PBVH_GRIDS);
2798  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2799 
2800  StrokeCache *cache = ss->cache;
2801  uint *lcol = data->lcol;
2802  char *col;
2803  const bool use_vert_sel = (data->me->editflag &
2805 
2806  struct VPaintAverageAccum *accum = (struct VPaintAverageAccum *)data->custom_data + n;
2807  accum->len = 0;
2808  memset(accum->value, 0, sizeof(accum->value));
2809 
2810  SculptBrushTest test;
2812  ss, &test, data->brush->falloff_shape);
2813 
2814  /* For each vertex */
2815  PBVHVertexIter vd;
2816  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
2817  /* Test to see if the vertex coordinates are within the spherical brush region. */
2818  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
2819  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
2820  vd.vert_indices[vd.i];
2821  if (BKE_brush_curve_strength(data->brush, 0.0, cache->radius) > 0.0) {
2822  /* If the vertex is selected for painting. */
2823  const MVert *mv = &data->me->mvert[v_index];
2824  if (!use_vert_sel || mv->flag & SELECT) {
2825  accum->len += gmap->vert_to_loop[v_index].count;
2826  /* if a vertex is within the brush region, then add its color to the blend. */
2827  for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
2828  const int l_index = gmap->vert_to_loop[v_index].indices[j];
2829  col = (char *)(&lcol[l_index]);
2830  /* Color is squared to compensate the sqrt color encoding. */
2831  accum->value[0] += col[0] * col[0];
2832  accum->value[1] += col[1] * col[1];
2833  accum->value[2] += col[2] * col[2];
2834  }
2835  }
2836  }
2837  }
2838  }
2840 }
2841 
2843  const float v_co[3],
2844  uint *r_color)
2845 {
2846  float rgba[4];
2847  float rgba_br[3];
2848  tex_color_alpha(data->vp, &data->vpd->vc, v_co, rgba);
2849  rgb_uchar_to_float(rgba_br, (const uchar *)&data->vpd->paintcol);
2850  mul_v3_v3(rgba_br, rgba);
2851  rgb_float_to_uchar((uchar *)r_color, rgba_br);
2852  return rgba[3];
2853 }
2854 
2855 static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
2856  const int n,
2857  const TaskParallelTLS *__restrict UNUSED(tls))
2858 {
2859  SculptThreadedTaskData *data = userdata;
2860  SculptSession *ss = data->ob->sculpt;
2861  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
2862  const bool has_grids = (pbvh_type == PBVH_GRIDS);
2863  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2864 
2865  const Brush *brush = data->brush;
2866  const StrokeCache *cache = ss->cache;
2867  uint *lcol = data->lcol;
2868  const Scene *scene = CTX_data_scene(data->C);
2869  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2871  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2872  const bool use_normal = vwpaint_use_normal(data->vp);
2873  const bool use_vert_sel = (data->me->editflag &
2875  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2876 
2877  SculptBrushTest test;
2879  ss, &test, data->brush->falloff_shape);
2880  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
2881  ss, data->brush->falloff_shape);
2882 
2883  /* For each vertex */
2884  PBVHVertexIter vd;
2885  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
2886  /* Test to see if the vertex coordinates are within the spherical brush region. */
2887  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
2888  /* Note: Grids are 1:1 with corners (aka loops).
2889  * For grid based pbvh, take the vert whose loop corresponds to the current grid.
2890  * Otherwise, take the current vert. */
2891  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
2892  vd.vert_indices[vd.i];
2893  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
2894  const MVert *mv = &data->me->mvert[v_index];
2895 
2896  /* If the vertex is selected for painting. */
2897  if (!use_vert_sel || mv->flag & SELECT) {
2898  /* Calc the dot prod. between ray norm on surf and current vert
2899  * (ie splash prevention factor), and only paint front facing verts. */
2900  float brush_strength = cache->bstrength;
2901  const float angle_cos = (use_normal && vd.no) ?
2902  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
2903  1.0f;
2904  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
2905  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
2907  &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
2908  const float brush_fade = BKE_brush_curve_strength(
2909  brush, sqrtf(test.dist), cache->radius);
2910  uint color_final = data->vpd->paintcol;
2911 
2912  /* If we're painting with a texture, sample the texture color and alpha. */
2913  float tex_alpha = 1.0;
2914  if (data->vpd->is_texbrush) {
2915  /* Note: we may want to paint alpha as vertex color alpha. */
2916  tex_alpha = tex_color_alpha_ubyte(
2917  data, data->vpd->vertexcosnos[v_index].co, &color_final);
2918  }
2919  /* For each poly owning this vert, paint each loop belonging to this vert. */
2920  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2921  const int p_index = gmap->vert_to_poly[v_index].indices[j];
2922  const int l_index = gmap->vert_to_loop[v_index].indices[j];
2923  BLI_assert(data->me->mloop[l_index].v == v_index);
2924  const MPoly *mp = &data->me->mpoly[p_index];
2925  if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2926  uint color_orig = 0; /* unused when array is NULL */
2927  if (ss->mode.vpaint.previous_color != NULL) {
2928  /* Get the previous loop color */
2929  if (ss->mode.vpaint.previous_color[l_index] == 0) {
2930  ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
2931  }
2932  color_orig = ss->mode.vpaint.previous_color[l_index];
2933  }
2934  const float final_alpha = 255 * brush_fade * brush_strength * tex_alpha *
2935  brush_alpha_pressure * grid_alpha;
2936 
2937  /* Mix the new color with the original based on final_alpha. */
2938  lcol[l_index] = vpaint_blend(data->vp,
2939  lcol[l_index],
2940  color_orig,
2941  color_final,
2942  final_alpha,
2943  255 * brush_strength);
2944  }
2945  }
2946  }
2947  }
2948  }
2949  }
2951 }
2952 
2953 static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata,
2954  const int n,
2955  const TaskParallelTLS *__restrict UNUSED(tls))
2956 {
2957  SculptThreadedTaskData *data = userdata;
2958  SculptSession *ss = data->ob->sculpt;
2959  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
2960  const bool has_grids = (pbvh_type == PBVH_GRIDS);
2961 
2962  Scene *scene = CTX_data_scene(data->C);
2963  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2964  const Brush *brush = data->brush;
2965  const StrokeCache *cache = ss->cache;
2966  uint *lcol = data->lcol;
2967  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2969  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2970  const bool use_normal = vwpaint_use_normal(data->vp);
2971  const bool use_vert_sel = (data->me->editflag &
2973  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2974 
2975  SculptBrushTest test;
2977  ss, &test, data->brush->falloff_shape);
2978  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
2979  ss, data->brush->falloff_shape);
2980 
2981  /* For each vertex */
2982  PBVHVertexIter vd;
2983  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
2984  /* Test to see if the vertex coordinates are within the spherical brush region. */
2985  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
2986  /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
2987  * Otherwise, take the current vert. */
2988  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
2989  vd.vert_indices[vd.i];
2990  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
2991  const MVert *mv = &data->me->mvert[v_index];
2992 
2993  /* If the vertex is selected for painting. */
2994  if (!use_vert_sel || mv->flag & SELECT) {
2995  float brush_strength = cache->bstrength;
2996  const float angle_cos = (use_normal && vd.no) ?
2997  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
2998  1.0f;
2999  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
3000  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
3002  &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
3003  const float brush_fade = BKE_brush_curve_strength(
3004  brush, sqrtf(test.dist), cache->radius);
3005 
3006  /* Get the average poly color */
3007  uint color_final = 0;
3008  int total_hit_loops = 0;
3009  uint blend[4] = {0};
3010  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
3011  int p_index = gmap->vert_to_poly[v_index].indices[j];
3012  const MPoly *mp = &data->me->mpoly[p_index];
3013  if (!use_face_sel || mp->flag & ME_FACE_SEL) {
3014  total_hit_loops += mp->totloop;
3015  for (int k = 0; k < mp->totloop; k++) {
3016  const uint l_index = mp->loopstart + k;
3017  const char *col = (const char *)(&lcol[l_index]);
3018  /* Color is squared to compensate the sqrt color encoding. */
3019  blend[0] += (uint)col[0] * (uint)col[0];
3020  blend[1] += (uint)col[1] * (uint)col[1];
3021  blend[2] += (uint)col[2] * (uint)col[2];
3022  blend[3] += (uint)col[3] * (uint)col[3];
3023  }
3024  }
3025  }
3026  if (total_hit_loops != 0) {
3027  /* Use rgb^2 color averaging. */
3028  char *col = (char *)(&color_final);
3029  col[0] = round_fl_to_uchar(sqrtf(divide_round_i(blend[0], total_hit_loops)));
3030  col[1] = round_fl_to_uchar(sqrtf(divide_round_i(blend[1], total_hit_loops)));
3031  col[2] = round_fl_to_uchar(sqrtf(divide_round_i(blend[2], total_hit_loops)));
3032  col[3] = round_fl_to_uchar(sqrtf(divide_round_i(blend[3], total_hit_loops)));
3033 
3034  /* For each poly owning this vert,
3035  * paint each loop belonging to this vert. */
3036  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
3037  const int p_index = gmap->vert_to_poly[v_index].indices[j];
3038  const int l_index = gmap->vert_to_loop[v_index].indices[j];
3039  BLI_assert(data->me->mloop[l_index].v == v_index);
3040  const MPoly *mp = &data->me->mpoly[p_index];
3041  if (!use_face_sel || mp->flag & ME_FACE_SEL) {
3042  uint color_orig = 0; /* unused when array is NULL */
3043  if (ss->mode.vpaint.previous_color != NULL) {
3044  /* Get the previous loop color */
3045  if (ss->mode.vpaint.previous_color[l_index] == 0) {
3046  ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
3047  }
3048  color_orig = ss->mode.vpaint.previous_color[l_index];
3049  }
3050  const float final_alpha = 255 * brush_fade * brush_strength *
3051  brush_alpha_pressure * grid_alpha;
3052  /* Mix the new color with the original
3053  * based on the brush strength and the curve. */
3054  lcol[l_index] = vpaint_blend(data->vp,
3055  lcol[l_index],
3056  color_orig,
3057  *((uint *)col),
3058  final_alpha,
3059  255 * brush_strength);
3060  }
3061  }
3062  }
3063  }
3064  }
3065  }
3066  }
3068 }
3069 
3070 static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata,
3071  const int n,
3072  const TaskParallelTLS *__restrict UNUSED(tls))
3073 {
3074  SculptThreadedTaskData *data = userdata;
3075  SculptSession *ss = data->ob->sculpt;
3076  const PBVHType pbvh_type = BKE_pbvh_type(ss->pbvh);
3077  const bool has_grids = (pbvh_type == PBVH_GRIDS);
3078 
3079  Scene *scene = CTX_data_scene(data->C);
3080  const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
3081  const Brush *brush = data->brush;
3082  const StrokeCache *cache = ss->cache;
3083  uint *lcol = data->lcol;
3084  float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
3086  scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
3087  float brush_dir[3];
3088  const bool use_normal = vwpaint_use_normal(data->vp);
3089  const bool use_vert_sel = (data->me->editflag &
3091  const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
3092 
3093  sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
3094  project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
3095 
3096  if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
3097 
3098  SculptBrushTest test;
3100  ss, &test, data->brush->falloff_shape);
3101  const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
3102  ss, data->brush->falloff_shape);
3103 
3104  /* For each vertex */
3105  PBVHVertexIter vd;
3106  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
3107  /* Test to see if the vertex coordinates are within the spherical brush region. */
3108  if (sculpt_brush_test_sq_fn(&test, vd.co)) {
3109  /* For grid based pbvh, take the vert whose loop corresponds to the current grid.
3110  * Otherwise, take the current vert. */
3111  const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v :
3112  vd.vert_indices[vd.i];
3113  const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f;
3114  const MVert *mv_curr = &data->me->mvert[v_index];
3115 
3116  /* if the vertex is selected for painting. */
3117  if (!use_vert_sel || mv_curr->flag & SELECT) {
3118  /* Calc the dot prod. between ray norm on surf and current vert
3119  * (ie splash prevention factor), and only paint front facing verts. */
3120  float brush_strength = cache->bstrength;
3121  const float angle_cos = (use_normal && vd.no) ?
3122  dot_vf3vs3(sculpt_normal_frontface, vd.no) :
3123  1.0f;
3124  if (((brush->flag & BRUSH_FRONTFACE) == 0 || (angle_cos > 0.0f)) &&
3125  ((brush->flag & BRUSH_FRONTFACE_FALLOFF) == 0 ||
3127  &data->vpd->normal_angle_precalc, angle_cos, &brush_strength))) {
3128  const float brush_fade = BKE_brush_curve_strength(
3129  brush, sqrtf(test.dist), cache->radius);
3130 
3131  bool do_color = false;
3132  /* Minimum dot product between brush direction and current
3133  * to neighbor direction is 0.0, meaning orthogonal. */
3134  float stroke_dot_max = 0.0f;
3135 
3136  /* Get the color of the loop in the opposite
3137  * direction of the brush movement */
3138  uint color_final = 0;
3139  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
3140  const int p_index = gmap->vert_to_poly[v_index].indices[j];
3141  const int l_index = gmap->vert_to_loop[v_index].indices[j];
3142  BLI_assert(data->me->mloop[l_index].v == v_index);
3143  UNUSED_VARS_NDEBUG(l_index);
3144  const MPoly *mp = &data->me->mpoly[p_index];
3145  if (!use_face_sel || mp->flag & ME_FACE_SEL) {
3146  const MLoop *ml_other = &data->me->mloop[mp->loopstart];
3147  for (int k = 0; k < mp->totloop; k++, ml_other++) {
3148  const uint v_other_index = ml_other->v;
3149  if (v_other_index != v_index) {
3150  const MVert *mv_other = &data->me->mvert[v_other_index];
3151 
3152  /* Get the direction from the
3153  * selected vert to the neighbor. */
3154  float other_dir[3];
3155  sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
3156  project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
3157 
3158  normalize_v3(other_dir);
3159 
3160  const float stroke_dot = dot_v3v3(other_dir, brush_dir);
3161 
3162  if (stroke_dot > stroke_dot_max) {
3163  stroke_dot_max = stroke_dot;
3164  color_final = data->vpd->smear.color_prev[mp->loopstart + k];
3165  do_color = true;
3166  }
3167  }
3168  }
3169  }
3170  }
3171 
3172  if (do_color) {
3173  const float final_alpha = 255 * brush_fade * brush_strength * brush_alpha_pressure *
3174  grid_alpha;
3175 
3176  /* For each poly owning this vert,
3177  * paint each loop belonging to this vert. */
3178  for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
3179  const int p_index = gmap->vert_to_poly[v_index].indices[j];
3180  const int l_index = gmap->vert_to_loop[v_index].indices[j];
3181  BLI_assert(data->me->mloop[l_index].v == v_index);
3182  const MPoly *mp = &data->me->mpoly[p_index];
3183  if (!use_face_sel || mp->flag & ME_FACE_SEL) {
3184  /* Get the previous loop color */
3185  uint color_orig = 0; /* unused when array is NULL */
3186  if (ss->mode.vpaint.previous_color != NULL) {
3187  /* Get the previous loop color */
3188  if (ss->mode.vpaint.previous_color[l_index] == 0) {
3189  ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
3190  }
3191  color_orig = ss->mode.vpaint.previous_color[l_index];
3192  }
3193  /* Mix the new color with the original
3194  * based on the brush strength and the curve. */
3195  lcol[l_index] = vpaint_blend(data->vp,
3196  lcol[l_index],
3197  color_orig,
3198  color_final,
3199  final_alpha,
3200  255 * brush_strength);
3201 
3202  data->vpd->smear.color_curr[l_index] = lcol[l_index];
3203  }
3204  }
3205  }
3206  }
3207  }
3208  }
3209  }
3211  }
3212 }
3213 
3215  PBVHNode **UNUSED(nodes),
3216  int totnode)
3217 {
3218  struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
3219  data->custom_data = accum;
3220 
3221  TaskParallelSettings settings;
3222  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
3224 
3225  uint accum_len = 0;
3226  uint accum_value[3] = {0};
3227  uchar blend[4] = {0};
3228  for (int i = 0; i < totnode; i++) {
3229  accum_len += accum[i].len;
3230  accum_value[0] += accum[i].value[0];
3231  accum_value[1] += accum[i].value[1];
3232  accum_value[2] += accum[i].value[2];
3233  }
3234  if (accum_len != 0) {
3235  blend[0] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[0], accum_len)));
3236  blend[1] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[1], accum_len)));
3237  blend[2] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[2], accum_len)));
3238  blend[3] = 255;
3239  data->vpd->paintcol = *((uint *)blend);
3240  }
3241 
3242  MEM_SAFE_FREE(data->custom_data); /* 'accum' */
3243 }
3244 
3246  Sculpt *sd,
3247  VPaint *vp,
3248  struct VPaintData *vpd,
3249  Object *ob,
3250  Mesh *me,
3251  PBVHNode **nodes,
3252  int totnode)
3253 {
3254  const Brush *brush = ob->sculpt->cache->brush;
3255 
3257  .C = C,
3258  .sd = sd,
3259  .ob = ob,
3260  .brush = brush,
3261  .nodes = nodes,
3262  .vp = vp,
3263  .vpd = vpd,
3264  .lcol = (uint *)me->mloopcol,
3265  .me = me,
3266  };
3267  TaskParallelSettings settings;
3268  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
3269  switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) {
3270  case VPAINT_TOOL_AVERAGE:
3271  calculate_average_color(&data, nodes, totnode);
3273  break;
3274  case VPAINT_TOOL_BLUR:
3276  break;
3277  case VPAINT_TOOL_SMEAR:
3279  break;
3280  case VPAINT_TOOL_DRAW:
3282  break;
3283  }
3284 }
3285 
3287  Sculpt *sd,
3288  VPaint *vp,
3289  struct VPaintData *vpd,
3290  Object *ob,
3291  Mesh *me,
3292  Brush *brush,
3293  const char symm,
3294  const int axis,
3295  const int i,
3296  const float angle)
3297 {
3298  SculptSession *ss = ob->sculpt;
3299  ss->cache->radial_symmetry_pass = i;
3300  SCULPT_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
3301 
3302  int totnode;
3303  PBVHNode **nodes = vwpaint_pbvh_gather_generic(ob, vp, sd, brush, &totnode);
3304 
3305  /* Paint those leaves. */
3306  vpaint_paint_leaves(C, sd, vp, vpd, ob, me, nodes, totnode);
3307 
3308  if (nodes) {
3309  MEM_freeN(nodes);
3310  }
3311 }
3312 
3314  Sculpt *sd,
3315  VPaint *vp,
3316  struct VPaintData *vpd,
3317  Object *ob,
3318  Mesh *me,
3319  Brush *brush,
3320  const char symm,
3321  const int axis)
3322 {
3323  for (int i = 1; i < vp->radial_symm[axis - 'X']; i++) {
3324  const float angle = (2.0 * M_PI) * i / vp->radial_symm[axis - 'X'];
3325  vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, symm, axis, i, angle);
3326  }
3327 }
3328 
3329 /* near duplicate of: sculpt.c's,
3330  * 'do_symmetrical_brush_actions' and 'wpaint_do_symmetrical_brush_actions'. */
3332  bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob)
3333 {
3334  Brush *brush = BKE_paint_brush(&vp->paint);
3335  Mesh *me = ob->data;
3336  SculptSession *ss = ob->sculpt;
3337  StrokeCache *cache = ss->cache;
3338  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
3339  int i = 0;
3340 
3341  /* initial stroke */
3342  cache->mirror_symmetry_pass = 0;
3343  vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
3344  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
3345  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
3346  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
3347 
3348  cache->symmetry = symm;
3349 
3350  /* symm is a bit combination of XYZ - 1 is mirror
3351  * X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
3352  for (i = 1; i <= symm; i++) {
3353  if (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) {
3354  cache->mirror_symmetry_pass = i;
3355  cache->radial_symmetry_pass = 0;
3356  SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
3357 
3358  if (i & (1 << 0)) {
3359  vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
3360  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'X');
3361  }
3362  if (i & (1 << 1)) {
3363  vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Y', 0, 0);
3364  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Y');
3365  }
3366  if (i & (1 << 2)) {
3367  vpaint_do_paint(C, sd, vp, vpd, ob, me, brush, i, 'Z', 0, 0);
3368  vpaint_do_radial_symmetry(C, sd, vp, vpd, ob, me, brush, i, 'Z');
3369  }
3370  }
3371  }
3372 
3374  cache->is_last_valid = true;
3375 }
3376 
3377 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
3378 {
3381  struct VPaintData *vpd = paint_stroke_mode_data(stroke);
3382  VPaint *vp = ts->vpaint;
3383  ViewContext *vc = &vpd->vc;
3384  Object *ob = vc->obact;
3385  SculptSession *ss = ob->sculpt;
3387 
3388  vwpaint_update_cache_variants(C, vp, ob, itemptr);
3389 
3390  float mat[4][4];
3391 
3393 
3394  /* load projection matrix */
3395  mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
3396 
3397  swap_m4m4(vc->rv3d->persmat, mat);
3398 
3399  vpaint_do_symmetrical_brush_actions(C, sd, vp, vpd, ob);
3400 
3401  swap_m4m4(vc->rv3d->persmat, mat);
3402 
3404 
3406  memcpy(
3407  vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop);
3408  }
3409 
3410  /* Calculate pivot for rotation around selection if needed.
3411  * also needed for "Frame Selected" on last stroke. */
3412  float loc_world[3];
3413  mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location);
3414  paint_last_stroke_update(scene, loc_world);
3415 
3417 
3418  if (vpd->use_fast_update == false) {
3419  /* recalculate modifier stack to get new colors, slow,
3420  * avoid this if we can! */
3421  DEG_id_tag_update(ob->data, 0);
3422  }
3423  else {
3424  /* Flush changes through DEG. */
3426  }
3427 }
3428 
3429 static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
3430 {
3431  struct VPaintData *vpd = paint_stroke_mode_data(stroke);
3432  ViewContext *vc = &vpd->vc;
3433  Object *ob = vc->obact;
3434 
3435  if (vpd->is_texbrush) {
3437  }
3438 
3439  if (vpd->mlooptag) {
3440  MEM_freeN(vpd->mlooptag);
3441  }
3442  if (vpd->smear.color_prev) {
3443  MEM_freeN(vpd->smear.color_prev);
3444  }
3445  if (vpd->smear.color_curr) {
3446  MEM_freeN(vpd->smear.color_curr);
3447  }
3448 
3450 
3451  MEM_freeN(vpd);
3452 
3454  ob->sculpt->cache = NULL;
3455 }
3456 
3457 static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
3458 {
3459  int retval;
3460 
3462  op,
3466  NULL,
3468  event->type);
3469 
3470  if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
3471  paint_stroke_free(C, op);
3472  return OPERATOR_FINISHED;
3473  }
3474 
3475  /* add modal handler */
3477 
3478  OPERATOR_RETVAL_CHECK(retval);
3480 
3481  return OPERATOR_RUNNING_MODAL;
3482 }
3483 
3485 {
3487  op,
3491  NULL,
3493  0);
3494 
3495  /* frees op->customdata */
3496  paint_stroke_exec(C, op);
3497 
3498  return OPERATOR_FINISHED;
3499 }
3500 
3502 {
3504  if (ob->sculpt->cache) {
3506  ob->sculpt->cache = NULL;
3507  }
3508 
3509  paint_stroke_cancel(C, op);
3510 }
3511 
3513 {
3514  /* identifiers */
3515  ot->name = "Vertex Paint";
3516  ot->idname = "PAINT_OT_vertex_paint";
3517  ot->description = "Paint a stroke in the active vertex color layer";
3518 
3519  /* api callbacks */
3520  ot->invoke = vpaint_invoke;
3522  ot->exec = vpaint_exec;
3524  ot->cancel = vpaint_cancel;
3525 
3526  /* flags */
3528 
3530 }
3531 
typedef float(TangentPoint)[2]
bool BKE_brush_use_size_pressure(const struct Brush *brush)
float BKE_brush_weight_get(const struct Scene *scene, const struct Brush *brush)
const float * BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.c:2216
float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush)
const float * BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.c:2210
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len)
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
void BKE_brush_unprojected_radius_set(struct Scene *scene, struct Brush *brush, float unprojected_radius)
Definition: brush.c:2294
float BKE_brush_sample_tex_3d(const struct Scene *scene, const struct Brush *br, const float point[3], float rgba[4], const int thread, struct ImagePool *pool)
bool BKE_brush_use_alpha_pressure(const struct Brush *brush)
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
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 Depsgraph * CTX_data_depsgraph_on_load(const bContext *C)
Definition: context.c:1432
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct wmMsgBus * CTX_wm_message_bus(const bContext *C)
Definition: context.c:746
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
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 RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:769
void * CustomData_get_layer(const struct CustomData *data, int type)
support for deformation groups and hooks.
float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, int defbase_tot, const bool *defbase_sel)
Definition: deform.c:835
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_calc_lock_relative_weight(float weight, float locked_weight, float unlocked_weight)
Definition: deform.c:887
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
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_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src)
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
#define VERTEX_WEIGHT_LOCK_EPSILON
Definition: BKE_deform.h:84
void BKE_mesh_flush_select_from_verts(struct Mesh *me)
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
void BKE_mesh_batch_cache_dirty_tag(struct Mesh *me, eMeshBatchDirtyMode mode)
Definition: mesh_runtime.c:251
void BKE_mesh_flush_select_from_polys(struct Mesh *me)
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *mpoly, const struct MLoop *mloop, int totvert, int totpoly, int totloop)
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *mpoly, const struct MLoop *mloop, int totvert, int totpoly, int totloop)
@ BKE_MESH_BATCH_DIRTY_ALL
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(struct Object *object)
Definition: object.c:4459
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.
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 Paint * BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode)
Definition: paint.c:354
void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
Definition: paint.c:1895
const char PAINT_CURSOR_VERTEX_PAINT[3]
Definition: paint.c:233
void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors)
Definition: paint.c:1817
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:604
void BKE_paint_init(struct Main *bmain, struct Scene *sce, ePaintMode mode, const char col[3])
Definition: paint.c:1115
bool BKE_paint_ensure(struct ToolSettings *ts, struct Paint **r_paint)
Definition: paint.c:1032
void BKE_sculptsession_free(struct Object *ob)
Definition: paint.c:1466
const char PAINT_CURSOR_WEIGHT_PAINT[3]
Definition: paint.c:234
void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint)
ePaintMode
Definition: BKE_paint.h:78
@ PAINT_MODE_SCULPT
Definition: BKE_paint.h:79
@ PAINT_MODE_WEIGHT
Definition: BKE_paint.h:82
@ PAINT_MODE_VERTEX
Definition: BKE_paint.h:81
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:384
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
PBVHType
Definition: BKE_pbvh.h:209
@ PBVH_GRIDS
Definition: BKE_pbvh.h:211
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3042
void BKE_pbvh_update_bounds(PBVH *pbvh, int flags)
Definition: pbvh.c:1410
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:843
@ PBVH_UpdateBB
Definition: BKE_pbvh.h:67
@ PBVH_UpdateRedraw
Definition: BKE_pbvh.h:70
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
Generic array manipulation API.
#define BLI_array_binary_or(arr, arr_a, arr_b, arr_len)
#define BLI_assert(a)
Definition: BLI_assert.h:58
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE unsigned char round_fl_to_uchar(float a)
#define M_PI_2
Definition: BLI_math_base.h:41
MINLINE int divide_round_i(int a, int b)
#define M_PI
Definition: BLI_math_base.h:38
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
Definition: math_color.c:407
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:422
void dist_squared_ray_to_aabb_v3_precalc(struct DistRayAABB_Precalc *neasrest_precalc, const float ray_origin[3], const float ray_direction[3])
Definition: math_geom.c:696
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void swap_m4m4(float m1[4][4], float m2[4][4])
Definition: math_matrix.c:236
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
#define RAD2DEGF(_rad)
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:740
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v4(float r[4])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void zero_v2(float r[2])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_rcti_union(struct rcti *rct1, const struct rcti *rct2)
bool BLI_rcti_is_empty(const struct rcti *rect)
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define MIN2(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_PSYS_RESET
Definition: DNA_ID.h:620
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
@ BRUSH_LOCK_ALPHA
@ BRUSH_FRONTFACE
@ BRUSH_ACCUMULATE
@ BRUSH_FRONTFACE_FALLOFF
eBrushWeightPaintTool
@ WPAINT_TOOL_BLUR
@ WPAINT_TOOL_AVERAGE
@ WPAINT_TOOL_SMEAR
@ WPAINT_TOOL_DRAW
eBrushVertexPaintTool
@ VPAINT_TOOL_BLUR
@ VPAINT_TOOL_DRAW
@ VPAINT_TOOL_SMEAR
@ VPAINT_TOOL_AVERAGE
@ PAINT_FALLOFF_SHAPE_SPHERE
@ CD_MLOOPCOL
#define ME_USING_MIRROR_X_VERTEX_GROUPS(_me)
@ ME_EDIT_MIRROR_VERTEX_GROUPS
@ ME_EDIT_PAINT_VERT_SEL
@ ME_EDIT_PAINT_FACE_SEL
@ ME_EDIT_MIRROR_TOPO
@ ME_FACE_SEL
eObjectMode
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_VERTEX_PAINT
Object is a sort of wrapper for general info.
#define DG_LOCK_WEIGHT
@ OB_MESH
#define PSYS_TOT_VG
@ VP_FLAG_VGROUP_RESTRICT
@ RGN_TYPE_WINDOW
@ RGN_TYPE_HUD
@ SPACE_VIEW3D
#define MTEX_MAP_MODE_3D
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
#define OPERATOR_RETVAL_CHECK(ret)
void ED_mesh_mirror_topo_table_end(struct Object *ob)
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_vgroup_sync_from_pose(struct Object *ob)
bool ED_mesh_color_ensure(struct Mesh *me, const char *name)
Definition: mesh_data.c:433
void ED_mesh_mirror_spatial_table_end(struct Object *ob)
void ED_object_posemode_set_for_weight_paint(struct bContext *C, struct Main *bmain, struct Object *ob, const bool is_mode_set)
Definition: object_modes.c:361
bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, eObjectMode mode, struct ReportList *reports)
Definition: object_modes.c:165
void ED_region_tag_redraw_partial(struct ARegion *region, const struct rcti *rct, bool rebuild)
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
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float r_pmat[4][4])
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 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 GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
IMB_BlendMode
Definition: IMB_imbuf.h:197
@ IMB_BLEND_ERASE_ALPHA
Definition: IMB_imbuf.h:204
@ IMB_BLEND_ADD_ALPHA
Definition: IMB_imbuf.h:205
@ IMB_BLEND_DARKEN
Definition: IMB_imbuf.h:203
@ IMB_BLEND_LIGHTEN
Definition: IMB_imbuf.h:202
@ IMB_BLEND_MIX
Definition: IMB_imbuf.h:198
@ IMB_BLEND_ADD
Definition: IMB_imbuf.h:199
@ IMB_BLEND_SUB
Definition: IMB_imbuf.h:200
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group RGB to Bright Vector Camera CLAMP
#define C
Definition: RandGen.cpp:39
#define ND_DRAW
Definition: WM_types.h:362
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_MODE
Definition: WM_types.h:345
#define NC_SCENE
Definition: WM_types.h:279
#define NC_OBJECT
Definition: WM_types.h:280
static T sum(const btAlignedObjectArray< T > &items)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define SELECT
Scene scene
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
uint col
IconTextureDrawCall normal
#define cosf(x)
#define acosf(x)
#define sqrtf(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 void area(int d1, int d2, int e1, int e2, float weights[2])
bool active
all scheduled work for the GPU.
void paint_cursor_delete_textures(void)
Definition: paint_cursor.c:102
void paint_cursor_start(Paint *p, bool(*poll)(bContext *C))
bool ED_wpaint_ensure_data(struct bContext *C, struct ReportList *reports, enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index)
struct PaintStroke * paint_stroke_new(struct bContext *C, struct wmOperator *op, StrokeGetLocation get_location, StrokeTestStart test_start, StrokeUpdateStep update_step, StrokeRedraw redraw, StrokeDone done, int event_type)
Definition: paint_stroke.c:889
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event)
float ED_wpaint_blend_tool(const int tool, const float weight, const float paintval, const float alpha)
@ BRUSH_STROKE_SMOOTH
Definition: paint_intern.h:313
@ BRUSH_STROKE_INVERT
Definition: paint_intern.h:312
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data)
@ WPAINT_ENSURE_MIRROR
Definition: paint_intern.h:137
int paint_stroke_exec(struct bContext *C, struct wmOperator *op)
void paint_stroke_free(struct bContext *C, struct wmOperator *op)
Definition: paint_stroke.c:948
float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius)
Definition: paint_utils.c:151
void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle)
struct VertProjHandle * ED_vpaint_proj_handle_create(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct CoNo **r_vcosnos)
bool paint_supports_dynamic_size(struct Brush *br, enum ePaintMode mode)
void * paint_stroke_mode_data(struct PaintStroke *stroke)
unsigned int ED_vpaint_blend_tool(const int tool, const uint col, const uint paintcol, const int alpha_i)
struct ViewContext * paint_stroke_view_context(struct PaintStroke *stroke)
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op)
void paint_stroke_operator_properties(struct wmOperatorType *ot)
Definition: paint_utils.c:210
static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void wpaint_do_radial_symmetry(bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me, Brush *brush, const char symm, const int axis)
static int wpaint_exec(bContext *C, wmOperator *op)
static void wpaint_do_symmetrical_brush_actions(bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi)
static float wpaint_blend(const VPaint *wp, float weight, const float alpha, float paintval, const float UNUSED(brush_alpha_value), const short do_flip)
Definition: paint_vertex.c:362
void ED_object_wpaintmode_exit_ex(Object *ob)
void ED_object_vpaintmode_exit_ex(Object *ob)
static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
static void do_weight_paint_normalize_all(MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap)
Definition: paint_vertex.c:444
void ED_object_vpaintmode_exit(struct bContext *C)
void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
static void view_angle_limits_init(struct NormalAnglePrecalc *a, float angle, bool do_mask_normal)
Definition: paint_vertex.c:108
static void vpaint_do_symmetrical_brush_actions(bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob)
static void vertex_paint_init_stroke(Depsgraph *depsgraph, Object *ob)
static uint vpaint_blend(const VPaint *vp, uint color_curr, uint color_orig, uint color_paint, const int alpha_i, const int brush_alpha_value_i)
Definition: paint_vertex.c:285
void PAINT_OT_weight_paint(wmOperatorType *ot)
static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
static PBVHNode ** vwpaint_pbvh_gather_generic(Object *ob, VPaint *wp, Sculpt *sd, Brush *brush, int *r_totnode)
void PAINT_OT_vertex_paint(wmOperatorType *ot)
static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi)
static void get_brush_alpha_data(const Scene *scene, const SculptSession *ss, const Brush *brush, float *r_brush_size_pressure, float *r_brush_alpha_value, float *r_brush_alpha_pressure)
static void wpaint_do_paint(bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
static bool weight_paint_poll_ex(bContext *C, bool check_tool)
Definition: paint_vertex.c:245
static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
bool weight_paint_mode_poll(bContext *C)
Definition: paint_vertex.c:238
static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool vertex_paint_poll_ex(bContext *C, bool check_tool)
Definition: paint_vertex.c:212
bool weight_paint_poll(bContext *C)
Definition: paint_vertex.c:263
static void vpaint_do_paint(bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob, Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
uint vpaint_get_current_col(Scene *scene, VPaint *vp, bool secondary)
Definition: paint_vertex.c:273
static void wpaint_paint_leaves(bContext *C, Object *ob, Sculpt *sd, VPaint *vp, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me, PBVHNode **nodes, int totnode)
static bool brush_use_accumulate_ex(const Brush *brush, const int ob_mode)
Definition: paint_vertex.c:153
static bool multipaint_verify_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
Definition: paint_vertex.c:644
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
static int vpaint_exec(bContext *C, wmOperator *op)
static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
bool vertex_paint_poll_ignore_tool(bContext *C)
Definition: paint_vertex.c:233
static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void ED_object_vpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
static bool paint_mode_toggle_poll_test(bContext *C)
static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void calculate_average_color(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
static void do_weight_paint_vertex(const VPaint *wp, Object *ob, const WeightPaintInfo *wpi, const uint index, float alpha, float paintweight)
static float wpaint_clamp_monotonic(float oldval, float curval, float newval)
Definition: paint_vertex.c:401
static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static bool vwpaint_use_normal(const VPaint *vp)
Definition: paint_vertex.c:147
static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
static float dot_vf3vs3(const float brushNormal[3], const short vertexNormal[3])
static void paint_last_stroke_update(Scene *scene, const float location[3])
Definition: paint_vertex.c:194
static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static float wpaint_undo_lock_relative(float weight, float old_weight, float locked_weight, float free_weight, bool auto_normalize)
Definition: paint_vertex.c:412
static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
bool vertex_paint_mode_poll(bContext *C)
Definition: paint_vertex.c:205
bool weight_paint_poll_ignore_tool(bContext *C)
Definition: paint_vertex.c:268
static void vwpaint_update_cache_invariants(bContext *C, const VPaint *vp, SculptSession *ss, wmOperator *op, const float mouse[2])
static void vpaint_paint_leaves(bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob, Mesh *me, PBVHNode **nodes, int totnode)
static void do_vpaint_brush_calc_average_color_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void tex_color_alpha(VPaint *vp, const ViewContext *vc, const float co[3], float r_rgba[4])
Definition: paint_vertex.c:340
static void wpaint_cancel(bContext *C, wmOperator *op)
static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode)
static bool brush_use_accumulate(const VPaint *vp)
Definition: paint_vertex.c:160
void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
static void do_weight_paint_vertex_multi(const VPaint *wp, Object *ob, const WeightPaintInfo *wpi, const uint index, float alpha, float paintweight)
Definition: paint_vertex.c:960
static void multipaint_apply_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
Definition: paint_vertex.c:672
static void do_weight_paint_vertex_single(const VPaint *wp, Object *ob, const WeightPaintInfo *wpi, const uint index, float alpha, float paintweight)
Definition: paint_vertex.c:747
static void calculate_average_weight(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
static void multipaint_clamp_change(MDeformVert *dvert, const int defbase_tot, const bool *defbase_sel, float *change_p)
Definition: paint_vertex.c:619
static void vpaint_do_radial_symmetry(bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd, Object *ob, Mesh *me, Brush *brush, const char symm, const int axis)
void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
void ED_object_wpaintmode_exit(struct bContext *C)
static float view_angle_limits_apply_falloff(const struct NormalAnglePrecalc *a, float angle_cos, float *mask_p)
Definition: paint_vertex.c:132
static bool vertex_paint_use_fast_update_check(Object *ob)
Definition: paint_vertex.c:180
static void do_weight_paint_normalize_all_locked_try_active(MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap, const bool *lock_flags, const bool *lock_with_active)
Definition: paint_vertex.c:574
static MDeformVert * defweight_prev_init(MDeformVert *dvert_prev, MDeformVert *dvert_curr, int index)
Definition: paint_vertex.c:165
static void ed_vwpaintmode_enter_generic(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag)
static float tex_color_alpha_ubyte(SculptThreadedTaskData *data, const float v_co[3], uint *r_color)
static void do_wpaint_brush_calc_average_weight_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void vpaint_cancel(bContext *C, wmOperator *op)
static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
struct WeightPaintInfo WeightPaintInfo
void ED_object_vpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
bool vertex_paint_poll(bContext *C)
Definition: paint_vertex.c:228
static void ed_vwpaintmode_exit_generic(Object *ob, const eObjectMode mode_flag)
static void precompute_weight_values(bContext *C, Object *ob, Brush *brush, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me)
static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, PointerRNA *ptr)
void ED_object_wpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
static bool do_weight_paint_normalize_all_locked(MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap, const bool *lock_flags)
Definition: paint_vertex.c:488
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:6378
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
bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2])
Definition: sculpt.c:7584
bool SCULPT_pbvh_calc_area_normal(const Brush *brush, Object *ob, PBVHNode **nodes, int totnode, bool use_threading, float r_area_no[3])
Definition: sculpt.c:2205
void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache, const char symm, const char axis, const float angle)
Definition: sculpt.c:6397
const float * SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss, char falloff_shape)
Definition: sculpt.c:1787
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, char falloff_shape)
Definition: sculpt.c:1770
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
Definition: sculpt.c:2561
static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups)
Definition: sculpt.c:2312
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:323
bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v)
Definition: sculpt.c:2608
void SCULPT_cache_free(StrokeCache *cache)
Definition: sculpt.c:6708
bool SCULPT_get_redraw_rect(ARegion *region, RegionView3D *rv3d, Object *ob, rcti *rect)
Definition: sculpt.c:1573
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
short regiontype
float falloff_angle
struct MTex mtex
char vertexpaint_tool
char falloff_shape
short blend
char weightpaint_tool
void * first
Definition: DNA_listBase.h:47
struct MDeformWeight * dw
unsigned int def_nr
unsigned int v
char brush_map_mode
struct Tex * tex
float co[3]
Definition: BKE_main.h:116
struct CustomData pdata ldata
struct MLoopCol * mloopcol
struct MDeformVert * dvert
char editflag
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
ListBase particlesystem
ListBase defbase
float imat[4][4]
unsigned short actdef
float obmat[4][4]
struct SculptSession * sculpt
void * data
int * grid_indices
Definition: BKE_pbvh.h:353
short * no
Definition: BKE_pbvh.h:375
float * co
Definition: BKE_pbvh.h:374
const int * vert_indices
Definition: BKE_pbvh.h:360
Brush * brush
Definition: paint_stroke.c:83
unsigned short ob_mode
struct Paint_Runtime runtime
struct Brush * brush
struct ParticleSystem * next
float persmat[4][4]
float viewinv[4][4]
struct ToolSettings * toolsettings
struct SculptSession::@54::@55 vpaint
union SculptSession::@54 mode
eObjectMode mode_type
Definition: BKE_paint.h:600
struct StrokeCache * cache
Definition: BKE_paint.h:518
struct SculptSession::@54::@56 wpaint
bool building_vp_handle
Definition: BKE_paint.h:603
struct PBVH * pbvh
Definition: BKE_paint.h:504
struct MeshElemMap * vert_to_loop
Definition: BKE_paint.h:235
struct MeshElemMap * vert_to_poly
Definition: BKE_paint.h:237
float true_location[3]
float initial_radius
float initial_mouse[2]
const struct Brush * brush
float mouse[2]
float true_view_normal[3]
float radius_squared
float projection_mat[4][4]
float last_location[3]
int mirror_symmetry_pass
float view_normal[3]
struct ViewContext * vc
float sculpt_normal_symm[3]
float location[3]
int radial_symmetry_pass
float true_last_location[3]
bool is_last_valid
struct UnifiedPaintSettings unified_paint_settings
uint * color_prev
struct CoNo * vertexcosnos
bool is_texbrush
struct NormalAnglePrecalc normal_angle_precalc
bool use_fast_update
struct VPaintData::@485 smear
ViewContext vc
struct VertProjHandle * vp_handle
uint * color_curr
bool * mlooptag
int radial_symm[3]
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 RegionView3D * rv3d
Definition: ED_view3d.h:83
struct WeightPaintGroupData active mirror
struct NormalAnglePrecalc normal_angle_precalc
const bool * vgroup_unlocked
const bool * lock_flags
ViewContext vc
bool do_lock_relative
const bool * vgroup_validmap
const bool * defbase_sel
const bool * vgroup_locked
bool do_multipaint
bool precomputed_weight_ready
float * precomputed_weight
int defbase_tot_sel
const bool * lock_flags
Definition: paint_vertex.c:726
const bool * vgroup_locked
Definition: paint_vertex.c:735
float brush_alpha_value
Definition: paint_vertex.c:744
struct WeightPaintGroupData active mirror
Definition: paint_vertex.c:722
const bool * vgroup_unlocked
Definition: paint_vertex.c:736
const bool * defbase_sel
Definition: paint_vertex.c:729
const bool * vgroup_validmap
Definition: paint_vertex.c:732
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
short type
Definition: WM_types.h:577
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
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
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
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)
bool WM_toolsystem_active_tool_is_brush(const bContext *C)
void WM_toolsystem_update_from_context_view3d(bContext *C)