7b534e12f31d4ebd143446a57630185e38d13859
[blender-staging.git] / source / blender / editors / sculpt_paint / paint_vertex.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/sculpt_paint/paint_vertex.c
29  *  \ingroup edsculpt
30  *
31  * Used for vertex color & weight paint and mode switching.
32  *
33  * \note This file is already big,
34  * use `paint_vertex_color_ops.c` & `paint_vertex_weight_ops.c` for general purpose operators.
35  */
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_listbase.h"
40 #include "BLI_rect.h"
41 #include "BLI_math.h"
42 #include "BLI_array_utils.h"
43 #include "BLI_task.h"
44
45 #include "DNA_armature_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_particle_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_brush_types.h"
50 #include "DNA_object_types.h"
51
52 #include "RNA_access.h"
53 #include "RNA_define.h"
54
55 #include "BKE_brush.h"
56 #include "BKE_context.h"
57 #include "BKE_depsgraph.h"
58 #include "BKE_deform.h"
59 #include "BKE_mesh.h"
60 #include "BKE_mesh_mapping.h"
61 #include "BKE_object_deform.h"
62 #include "BKE_paint.h"
63 #include "BKE_report.h"
64 #include "BKE_subsurf.h"
65
66 #include "WM_api.h"
67 #include "WM_types.h"
68
69 #include "ED_object.h"
70 #include "ED_mesh.h"
71 #include "ED_screen.h"
72 #include "ED_view3d.h"
73
74 #include "bmesh.h"
75 #include "BKE_ccg.h"
76
77 #include "sculpt_intern.h"
78 #include "paint_intern.h"  /* own include */
79
80 /* Use for 'blur' brush, align with PBVH nodes, created and freed on each update. */
81 struct VPaintAverageAccum {
82         uint len;
83         uint value[3];
84 };
85
86 struct WPaintAverageAccum {
87         uint len;
88         double value;
89 };
90
91 static void defweight_prev_restore_or_init(MDeformVert *dvert_prev, MDeformVert *dvert_curr, int index)
92 {
93         MDeformVert *dv_curr = &dvert_curr[index];
94         MDeformVert *dv_prev = &dvert_prev[index];
95         if (dv_prev->flag == 1) {
96                 dv_prev->flag = 0;
97                 defvert_copy(dv_prev, dv_curr);
98         }
99         else {
100                 defvert_copy(dv_curr, dv_prev);
101         }
102 }
103
104 /* check if we can do partial updates and have them draw realtime
105  * (without rebuilding the 'derivedFinal') */
106 static bool vertex_paint_use_fast_update_check(Object *ob)
107 {
108         DerivedMesh *dm = ob->derivedFinal;
109
110         if (dm) {
111                 Mesh *me = BKE_mesh_from_object(ob);
112                 if (me && me->mloopcol) {
113                         return (me->mloopcol == CustomData_get_layer(&dm->loopData, CD_MLOOPCOL));
114                 }
115         }
116
117         return false;
118 }
119
120 static void paint_last_stroke_update(Scene *scene, ARegion *ar, const float mval[2])
121 {
122         const int mval_i[2] = {mval[0], mval[1]};
123         float world[3];
124
125         if (ED_view3d_autodist_simple(ar, mval_i, world, 0, NULL)) {
126                 UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
127                 ups->average_stroke_counter++;
128                 add_v3_v3(ups->average_stroke_accum, world);
129                 ups->last_stroke_valid = true;
130         }
131 }
132
133 /* polling - retrieve whether cursor should be set or operator should be done */
134
135 /* Returns true if vertex paint mode is active */
136 int vertex_paint_mode_poll(bContext *C)
137 {
138         Object *ob = CTX_data_active_object(C);
139
140         return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
141 }
142
143 int vertex_paint_poll(bContext *C)
144 {
145         if (vertex_paint_mode_poll(C) &&
146             BKE_paint_brush(&CTX_data_tool_settings(C)->vpaint->paint))
147         {
148                 ScrArea *sa = CTX_wm_area(C);
149                 if (sa && sa->spacetype == SPACE_VIEW3D) {
150                         ARegion *ar = CTX_wm_region(C);
151                         if (ar->regiontype == RGN_TYPE_WINDOW)
152                                 return 1;
153                 }
154         }
155         return 0;
156 }
157
158 int weight_paint_mode_poll(bContext *C)
159 {
160         Object *ob = CTX_data_active_object(C);
161
162         return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
163 }
164
165 int weight_paint_poll(bContext *C)
166 {
167         Object *ob = CTX_data_active_object(C);
168         ScrArea *sa;
169
170         if ((ob != NULL) &&
171             (ob->mode & OB_MODE_WEIGHT_PAINT) &&
172             (BKE_paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
173             (sa = CTX_wm_area(C)) &&
174             (sa->spacetype == SPACE_VIEW3D))
175         {
176                 ARegion *ar = CTX_wm_region(C);
177                 if (ar->regiontype == RGN_TYPE_WINDOW) {
178                         return 1;
179                 }
180         }
181         return 0;
182 }
183
184 static VPaint *new_vpaint(int wpaint)
185 {
186         VPaint *vp = MEM_callocN(sizeof(VPaint), "VPaint");
187
188         vp->flag = (wpaint) ? 0 : VP_SPRAY;
189         vp->paint.flags |= PAINT_SHOW_BRUSH;
190
191         return vp;
192 }
193
194 uint vpaint_get_current_col(Scene *scene, VPaint *vp)
195 {
196         Brush *brush = BKE_paint_brush(&vp->paint);
197         uchar col[4];
198         rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush));
199         col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
200         return *(uint *)col;
201 }
202
203 /* wpaint has 'wpaint_blend' */
204 static uint vpaint_blend(
205         VPaint *vp, uint color_curr, uint color_orig,
206         uint color_paint, const int alpha_i,
207         /* pre scaled from [0-1] --> [0-255] */
208         const int brush_alpha_value_i)
209 {
210         Brush *brush = BKE_paint_brush(&vp->paint);
211         const int tool = brush->vertexpaint_tool;
212
213         uint color_blend = ED_vpaint_blend_tool(tool, color_curr, color_paint, alpha_i);
214
215         /* if no spray, clip color adding with colorig & orig alpha */
216         if ((vp->flag & VP_SPRAY) == 0) {
217                 uint color_test, a;
218                 char *cp, *ct, *co;
219
220                 color_test = ED_vpaint_blend_tool(tool, color_orig, color_paint, brush_alpha_value_i);
221
222                 cp = (char *)&color_blend;
223                 ct = (char *)&color_test;
224                 co = (char *)&color_orig;
225
226                 for (a = 0; a < 4; a++) {
227                         if (ct[a] < co[a]) {
228                                 if (cp[a] < ct[a]) cp[a] = ct[a];
229                                 else if (cp[a] > co[a]) cp[a] = co[a];
230                         }
231                         else {
232                                 if (cp[a] < co[a]) cp[a] = co[a];
233                                 else if (cp[a] > ct[a]) cp[a] = ct[a];
234                         }
235                 }
236         }
237
238         if ((brush->flag & BRUSH_LOCK_ALPHA) &&
239             !ELEM(tool, PAINT_BLEND_ALPHA_SUB, PAINT_BLEND_ALPHA_ADD))
240         {
241                 char *cp, *cc;
242                 cp = (char *)&color_blend;
243                 cc = (char *)&color_curr;
244                 cp[3] = cc[3];
245         }
246
247         return color_blend;
248 }
249
250
251 /* whats _dl mean? */
252 static float calc_vp_strength_col_dl(
253         VPaint *vp, const ViewContext *vc, const float co[3],
254         const float mval[2], const float brush_size_pressure, float rgba[4])
255 {
256         float co_ss[2];  /* screenspace */
257
258         if (ED_view3d_project_float_object(
259                 vc->ar,
260                 co, co_ss,
261                 V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
262         {
263                 const float dist_sq = len_squared_v2v2(mval, co_ss);
264
265                 if (dist_sq <= SQUARE(brush_size_pressure)) {
266                         Brush *brush = BKE_paint_brush(&vp->paint);
267                         const float dist = sqrtf(dist_sq);
268                         float factor;
269
270                         if (brush->mtex.tex && rgba) {
271                                 if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
272                                         BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL);
273                                 }
274                                 else {
275                                         const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f};  /* we need a 3rd empty value */
276                                         BKE_brush_sample_tex_3D(vc->scene, brush, co_ss_3d, rgba, 0, NULL);
277                                 }
278                                 factor = rgba[3];
279                         }
280                         else {
281                                 factor = 1.0f;
282                         }
283                         return factor * BKE_brush_curve_strength_clamped(brush, dist, brush_size_pressure);
284                 }
285         }
286         if (rgba)
287                 zero_v4(rgba);
288         return 0.0f;
289 }
290
291 static float calc_vp_alpha_col_dl(
292         VPaint *vp, const ViewContext *vc,
293         float vpimat[3][3], const DMCoNo *v_co_no,
294         const float mval[2],
295         const float brush_size_pressure, const float brush_alpha_pressure, float rgba[4])
296 {
297         float strength = calc_vp_strength_col_dl(vp, vc, v_co_no->co, mval, brush_size_pressure, rgba);
298
299         if (strength > 0.0f) {
300                 float alpha = brush_alpha_pressure * strength;
301
302                 if (vp->flag & VP_NORMALS) {
303                         float dvec[3];
304
305                         /* transpose ! */
306                         dvec[2] = dot_v3v3(vpimat[2], v_co_no->no);
307                         if (dvec[2] > 0.0f) {
308                                 dvec[0] = dot_v3v3(vpimat[0], v_co_no->no);
309                                 dvec[1] = dot_v3v3(vpimat[1], v_co_no->no);
310
311                                 alpha *= dvec[2] / len_v3(dvec);
312                         }
313                         else {
314                                 return 0.0f;
315                         }
316                 }
317
318                 return alpha;
319         }
320
321         return 0.0f;
322 }
323
324 /* vpaint has 'vpaint_blend' */
325 static float wpaint_blend(
326         VPaint *wp, float weight,
327         const float alpha, float paintval,
328         const float UNUSED(brush_alpha_value),
329         const short do_flip)
330 {
331         Brush *brush = BKE_paint_brush(&wp->paint);
332         int tool = brush->vertexpaint_tool;
333
334         if (do_flip) {
335                 switch (tool) {
336                         case PAINT_BLEND_MIX:
337                                 paintval = 1.f - paintval; break;
338                         case PAINT_BLEND_ADD:
339                                 tool = PAINT_BLEND_SUB; break;
340                         case PAINT_BLEND_SUB:
341                                 tool = PAINT_BLEND_ADD; break;
342                         case PAINT_BLEND_LIGHTEN:
343                                 tool = PAINT_BLEND_DARKEN; break;
344                         case PAINT_BLEND_DARKEN:
345                                 tool = PAINT_BLEND_LIGHTEN; break;
346                 }
347         }
348
349         weight = ED_wpaint_blend_tool(tool, weight, paintval, alpha);
350
351         CLAMP(weight, 0.0f, 1.0f);
352
353         return weight;
354 }
355
356 /* ----------------------------------------------------- */
357
358 static void do_weight_paint_normalize_all(MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap)
359 {
360         float sum = 0.0f, fac;
361         uint i, tot = 0;
362         MDeformWeight *dw;
363
364         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
365                 if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
366                         tot++;
367                         sum += dw->weight;
368                 }
369         }
370
371         if ((tot == 0) || (sum == 1.0f)) {
372                 return;
373         }
374
375         if (sum != 0.0f) {
376                 fac = 1.0f / sum;
377
378                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
379                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
380                                 dw->weight *= fac;
381                         }
382                 }
383         }
384         else {
385                 /* hrmf, not a factor in this case */
386                 fac = 1.0f / tot;
387
388                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
389                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
390                                 dw->weight = fac;
391                         }
392                 }
393         }
394 }
395
396 /**
397  * A version of #do_weight_paint_normalize_all that includes locked weights
398  * but only changes unlocked weights.
399  */
400 static bool do_weight_paint_normalize_all_locked(
401         MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
402         const bool *lock_flags)
403 {
404         float sum = 0.0f, fac;
405         float sum_unlock = 0.0f;
406         float lock_weight = 0.0f;
407         uint i, tot = 0;
408         MDeformWeight *dw;
409
410         if (lock_flags == NULL) {
411                 do_weight_paint_normalize_all(dvert, defbase_tot, vgroup_validmap);
412                 return true;
413         }
414
415         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
416                 if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
417                         sum += dw->weight;
418
419                         if (lock_flags[dw->def_nr]) {
420                                 lock_weight += dw->weight;
421                         }
422                         else {
423                                 tot++;
424                                 sum_unlock += dw->weight;
425                         }
426                 }
427         }
428
429         if (sum == 1.0f) {
430                 return true;
431         }
432
433         if (tot == 0) {
434                 return false;
435         }
436
437         if (lock_weight >= 1.0f) {
438                 /* locked groups make it impossible to fully normalize,
439                  * zero out what we can and return false */
440                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
441                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
442                                 if (lock_flags[dw->def_nr] == false) {
443                                         dw->weight = 0.0f;
444                                 }
445                         }
446                 }
447
448                 return (lock_weight == 1.0f);
449         }
450         else if (sum_unlock != 0.0f) {
451                 fac = (1.0f - lock_weight) / sum_unlock;
452
453                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
454                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
455                                 if (lock_flags[dw->def_nr] == false) {
456                                         dw->weight *= fac;
457                                         /* paranoid but possibly with float error */
458                                         CLAMP(dw->weight, 0.0f, 1.0f);
459                                 }
460                         }
461                 }
462         }
463         else {
464                 /* hrmf, not a factor in this case */
465                 fac = (1.0f - lock_weight) / tot;
466                 /* paranoid but possibly with float error */
467                 CLAMP(fac, 0.0f, 1.0f);
468
469                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
470                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
471                                 if (lock_flags[dw->def_nr] == false) {
472                                         dw->weight = fac;
473                                 }
474                         }
475                 }
476         }
477
478         return true;
479 }
480
481 /**
482  * \note same as function above except it does a second pass without active group
483  * if normalize fails with it.
484  */
485 static void do_weight_paint_normalize_all_locked_try_active(
486         MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
487         const bool *lock_flags, const bool *lock_with_active)
488 {
489         /* first pass with both active and explicitly locked groups restricted from change */
490
491         bool success = do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_with_active);
492
493         if (!success) {
494                 /**
495                  * Locks prevented the first pass from full completion, so remove restriction on active group; e.g:
496                  *
497                  * - With 1.0 weight painted into active:
498                  *   nonzero locked weight; first pass zeroed out unlocked weight; scale 1 down to fit.
499                  * - With 0.0 weight painted into active:
500                  *   no unlocked groups; first pass did nothing; increase 0 to fit.
501                  */
502                 do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
503         }
504 }
505
506 #if 0 /* UNUSED */
507 static bool has_unselected_unlocked_bone_group(
508         int defbase_tot, bool *defbase_sel, int selected,
509         const bool *lock_flags, const bool *vgroup_validmap)
510 {
511         int i;
512         if (defbase_tot == selected) {
513                 return false;
514         }
515         for (i = 0; i < defbase_tot; i++) {
516                 if (vgroup_validmap[i] && !defbase_sel[i] && !lock_flags[i]) {
517                         return true;
518                 }
519         }
520         return false;
521 }
522 #endif
523
524 static void multipaint_clamp_change(
525         MDeformVert *dvert, const int defbase_tot, const bool *defbase_sel,
526         float *change_p)
527 {
528         int i;
529         MDeformWeight *dw;
530         float val;
531         float change = *change_p;
532
533         /* verify that the change does not cause values exceeding 1 and clamp it */
534         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
535                 if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
536                         if (dw->weight) {
537                                 val = dw->weight * change;
538                                 if (val > 1) {
539                                         change = 1.0f / dw->weight;
540                                 }
541                         }
542                 }
543         }
544
545         *change_p = change;
546 }
547
548 static bool multipaint_verify_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
549 {
550         int i;
551         MDeformWeight *dw;
552         float val;
553
554         /* in case the change is reduced, you need to recheck
555          * the earlier values to make sure they are not 0
556          * (precision error) */
557         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
558                 if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
559                         if (dw->weight) {
560                                 val = dw->weight * change;
561                                 /* the value should never reach zero while multi-painting if it
562                                  * was nonzero beforehand */
563                                 if (val <= 0) {
564                                         return false;
565                                 }
566                         }
567                 }
568         }
569
570         return true;
571 }
572
573 static void multipaint_apply_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
574 {
575         int i;
576         MDeformWeight *dw;
577
578         /* apply the valid change */
579         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
580                 if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
581                         if (dw->weight) {
582                                 dw->weight = dw->weight * change;
583                                 CLAMP(dw->weight, 0.0f, 1.0f);
584                         }
585                 }
586         }
587 }
588
589 /**
590  * Variables stored both for 'active' and 'mirror' sides.
591  */
592 struct WeightPaintGroupData {
593         /** index of active group or its mirror
594          *
595          * - 'active' is always `ob->actdef`.
596          * - 'mirror' is -1 when 'ME_EDIT_MIRROR_X' flag id disabled,
597          *   otherwise this will be set to the mirror or the active group (if the group isn't mirrored).
598          */
599         int index;
600         /** lock that includes the 'index' as locked too
601          *
602          * - 'active' is set of locked or active/selected groups
603          * - 'mirror' is set of locked or mirror groups
604          */
605         const bool *lock;
606 };
607
608 /* struct to avoid passing many args each call to do_weight_paint_vertex()
609  * this _could_ be made a part of the operators 'WPaintData' struct, or at
610  * least a member, but for now keep its own struct, initialized on every
611  * paint stroke update - campbell */
612 typedef struct WeightPaintInfo {
613
614         int defbase_tot;
615
616         /* both must add up to 'defbase_tot' */
617         int defbase_tot_sel;
618         int defbase_tot_unsel;
619
620         struct WeightPaintGroupData active, mirror;
621
622         /* boolean array for locked bones,
623          * length of defbase_tot */
624         const bool *lock_flags;
625         /* boolean array for selected bones,
626          * length of defbase_tot, cant be const because of how its passed */
627         const bool *defbase_sel;
628         /* same as WeightPaintData.vgroup_validmap,
629          * only added here for convenience */
630         const bool *vgroup_validmap;
631
632         bool do_flip;
633         bool do_multipaint;
634         bool do_auto_normalize;
635
636         float brush_alpha_value;  /* result of BKE_brush_alpha_get() */
637 } WeightPaintInfo;
638
639 static void do_weight_paint_vertex_single(
640         /* vars which remain the same for every vert */
641         VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
642         /* vars which change on each stroke */
643         const uint index, float alpha, float paintweight)
644 {
645         Mesh *me = ob->data;
646         MDeformVert *dv = &me->dvert[index];
647         bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
648
649         MDeformWeight *dw;
650
651         /* mirror vars */
652         int index_mirr;
653         int vgroup_mirr;
654
655         MDeformVert *dv_mirr;
656         MDeformWeight *dw_mirr;
657
658         /* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
659         if (me->editflag & ME_EDIT_MIRROR_X) {
660                 index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
661                 vgroup_mirr = wpi->mirror.index;
662
663                 /* another possible error - mirror group _and_ active group are the same (which is fine),
664                  * but we also are painting onto a center vertex - this would paint the same weight twice */
665                 if (index_mirr == index && vgroup_mirr == wpi->active.index) {
666                         index_mirr = vgroup_mirr = -1;
667                 }
668         }
669         else {
670                 index_mirr = vgroup_mirr = -1;
671         }
672
673         if ((wp->flag & VP_SPRAY) == 0) {
674                 struct MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
675                 defweight_prev_restore_or_init(dvert_prev, me->dvert, index);
676                 if (index_mirr != -1) {
677                         defweight_prev_restore_or_init(dvert_prev, me->dvert, index_mirr);
678                 }
679         }
680
681         if (wp->flag & VP_ONLYVGROUP) {
682                 dw = defvert_find_index(dv, wpi->active.index);
683         }
684         else {
685                 dw = defvert_verify_index(dv, wpi->active.index);
686         }
687
688         if (dw == NULL) {
689                 return;
690         }
691
692         /* get the mirror def vars */
693         if (index_mirr != -1) {
694                 dv_mirr = &me->dvert[index_mirr];
695                 if (wp->flag & VP_ONLYVGROUP) {
696                         dw_mirr = defvert_find_index(dv_mirr, vgroup_mirr);
697
698                         if (dw_mirr == NULL) {
699                                 index_mirr = vgroup_mirr = -1;
700                                 dv_mirr = NULL;
701                         }
702                 }
703                 else {
704                         if (index != index_mirr) {
705                                 dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
706                         }
707                         else {
708                                 /* dv and dv_mirr are the same */
709                                 int totweight_prev = dv_mirr->totweight;
710                                 int dw_offset = (int)(dw - dv_mirr->dw);
711                                 dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
712
713                                 /* if we added another, get our old one back */
714                                 if (totweight_prev != dv_mirr->totweight) {
715                                         dw = &dv_mirr->dw[dw_offset];
716                                 }
717                         }
718                 }
719         }
720         else {
721                 dv_mirr = NULL;
722                 dw_mirr = NULL;
723         }
724
725         /* If there are no normalize-locks or multipaint,
726          * then there is no need to run the more complicated checks */
727
728         {
729                 dw->weight = wpaint_blend(
730                         wp, dw->weight, alpha, paintweight,
731                         wpi->brush_alpha_value, wpi->do_flip);
732
733                 /* WATCH IT: take care of the ordering of applying mirror -> normalize,
734                  * can give wrong results [#26193], least confusing if normalize is done last */
735
736                 /* apply mirror */
737                 if (index_mirr != -1) {
738                         /* copy, not paint again */
739                         dw_mirr->weight = dw->weight;
740                 }
741
742                 /* apply normalize */
743                 if (wpi->do_auto_normalize) {
744                         /* note on normalize - this used to be applied after painting and normalize all weights,
745                          * in some ways this is good because there is feedback where the more weights involved would
746                          * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active.
747                          *
748                          * However this gave a problem since applying mirror, then normalize both verts
749                          * the resulting weight wont match on both sides.
750                          *
751                          * If this 'resisting', slower normalize is nicer, we could call
752                          * do_weight_paint_normalize_all() and only use...
753                          * do_weight_paint_normalize_all_active() when normalizing the mirror vertex.
754                          * - campbell
755                          */
756                         do_weight_paint_normalize_all_locked_try_active(
757                                 dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
758
759                         if (index_mirr != -1) {
760                                 /* only normalize if this is not a center vertex, else we get a conflict, normalizing twice */
761                                 if (index != index_mirr) {
762                                         do_weight_paint_normalize_all_locked_try_active(
763                                                 dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->mirror.lock);
764                                 }
765                                 else {
766                                         /* this case accounts for...
767                                          * - painting onto a center vertex of a mesh
768                                          * - x mirror is enabled
769                                          * - auto normalize is enabled
770                                          * - the group you are painting onto has a L / R version
771                                          *
772                                          * We want L/R vgroups to have the same weight but this cant be if both are over 0.5,
773                                          * We _could_ have special check for that, but this would need its own normalize function which
774                                          * holds 2 groups from changing at once.
775                                          *
776                                          * So! just balance out the 2 weights, it keeps them equal and everything normalized.
777                                          *
778                                          * While it wont hit the desired weight immediately as the user waggles their mouse,
779                                          * constant painting and re-normalizing will get there. this is also just simpler logic.
780                                          * - campbell */
781                                         dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f;
782                                 }
783                         }
784                 }
785         }
786 }
787
788 static void do_weight_paint_vertex_multi(
789         /* vars which remain the same for every vert */
790         VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
791         /* vars which change on each stroke */
792         const uint index, float alpha, float paintweight)
793 {
794         Mesh *me = ob->data;
795         MDeformVert *dv = &me->dvert[index];
796         bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
797
798         /* mirror vars */
799         int index_mirr = -1;
800         MDeformVert *dv_mirr = NULL;
801
802         /* weights */
803         float curw, neww, change, curw_mirr, change_mirr;
804
805         /* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
806         if (me->editflag & ME_EDIT_MIRROR_X) {
807                 index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
808
809                 if (index_mirr != -1 && index_mirr != index) {
810                         dv_mirr = &me->dvert[index_mirr];
811                 }
812                 else {
813                         index_mirr = -1;
814                 }
815         }
816
817         if ((wp->flag & VP_SPRAY) == 0) {
818                 struct MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev;
819                 defweight_prev_restore_or_init(dvert_prev, me->dvert, index);
820                 if (index_mirr != -1) {
821                         defweight_prev_restore_or_init(dvert_prev, me->dvert, index_mirr);
822                 }
823         }
824
825         /* compute weight change by applying the brush to average or sum of group weights */
826         curw = BKE_defvert_multipaint_collective_weight(
827                 dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
828
829         if (curw == 0.0f) {
830                 /* note: no weight to assign to this vertex, could add all groups? */
831                 return;
832         }
833
834         neww = wpaint_blend(wp, curw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip);
835
836         change = neww / curw;
837
838         /* verify for all groups that 0 < result <= 1 */
839         multipaint_clamp_change(dv, wpi->defbase_tot, wpi->defbase_sel, &change);
840
841         if (dv_mirr != NULL) {
842                 curw_mirr = BKE_defvert_multipaint_collective_weight(
843                         dv_mirr, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
844
845                 if (curw_mirr == 0.0f) {
846                         /* can't mirror into a zero weight vertex */
847                         dv_mirr = NULL;
848                 }
849                 else {
850                         /* mirror is changed to achieve the same collective weight value */
851                         float orig = change_mirr = curw * change / curw_mirr;
852
853                         multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
854
855                         if (!multipaint_verify_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel)) {
856                                 return;
857                         }
858
859                         change *= change_mirr / orig;
860                 }
861         }
862
863         if (!multipaint_verify_change(dv, wpi->defbase_tot, change, wpi->defbase_sel)) {
864                 return;
865         }
866
867         /* apply validated change to vertex and mirror */
868         multipaint_apply_change(dv, wpi->defbase_tot, change, wpi->defbase_sel);
869
870         if (dv_mirr != NULL) {
871                 multipaint_apply_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel);
872         }
873
874         /* normalize */
875         if (wpi->do_auto_normalize) {
876                 do_weight_paint_normalize_all_locked_try_active(
877                         dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
878
879                 if (dv_mirr != NULL) {
880                         do_weight_paint_normalize_all_locked_try_active(
881                                 dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
882                 }
883         }
884 }
885
886 static void do_weight_paint_vertex(
887         /* vars which remain the same for every vert */
888         VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
889         /* vars which change on each stroke */
890         const uint index, float alpha, float paintweight)
891 {
892         if (wpi->do_multipaint) {
893                 do_weight_paint_vertex_multi(wp, ob, wpi, index, alpha, paintweight);
894         }
895         else {
896                 do_weight_paint_vertex_single(wp, ob, wpi, index, alpha, paintweight);
897         }
898 }
899
900
901 /* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
902 static void vertex_paint_init_session(Scene *scene, Object *ob)
903 {
904         if (ob->sculpt == NULL) {
905                 ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
906                 BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false);
907         }
908 }
909
910 static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
911 {
912         /* Create maps */
913         struct SculptVertexPaintGeomMap *gmap = NULL;
914         const Brush *brush = NULL;
915         if (ob->mode == OB_MODE_VERTEX_PAINT) {
916                 gmap = &ob->sculpt->mode.vpaint.gmap;
917                 brush = BKE_paint_brush(&ts->vpaint->paint);
918                 ob->sculpt->mode_type = OB_MODE_VERTEX_PAINT;
919         }
920         else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
921                 gmap = &ob->sculpt->mode.wpaint.gmap;
922                 brush = BKE_paint_brush(&ts->wpaint->paint);
923                 ob->sculpt->mode_type = OB_MODE_WEIGHT_PAINT;
924         }
925         else {
926                 ob->sculpt->mode_type = 0;
927                 BLI_assert(0);
928                 return;
929         }
930
931         Mesh *me = ob->data;
932
933         if (gmap->vert_to_loop == NULL) {
934                 gmap->vert_map_mem = NULL;
935                 gmap->vert_to_loop = NULL;
936                 gmap->poly_map_mem = NULL;
937                 gmap->vert_to_poly = NULL;
938                 BKE_mesh_vert_loop_map_create(
939                         &gmap->vert_to_loop,
940                         &gmap->vert_map_mem,
941                         me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
942                 BKE_mesh_vert_poly_map_create(
943                         &gmap->vert_to_poly,
944                         &gmap->poly_map_mem,
945                         me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
946         }
947
948         /* Create average brush arrays */
949         if (ob->mode == OB_MODE_VERTEX_PAINT) {
950                 if ((ts->vpaint->flag & VP_SPRAY) == 0) {
951                         if (ob->sculpt->mode.vpaint.previous_color == NULL) {
952                                 ob->sculpt->mode.vpaint.previous_color =
953                                         MEM_callocN(me->totloop * sizeof(uint), __func__);
954                         }
955                 }
956                 else {
957                         MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_color);
958                 }
959
960                 if (brush && brush->flag & BRUSH_ACCUMULATE) {
961                         if (ob->sculpt->mode.vpaint.previous_accum == NULL) {
962                                 ob->sculpt->mode.vpaint.previous_accum =
963                                         MEM_callocN(me->totloop * sizeof(float), __func__);
964                         }
965                 }
966                 else {
967                         MEM_SAFE_FREE(ob->sculpt->mode.vpaint.previous_accum);
968                 }
969         }
970         else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
971                 if ((ts->wpaint->flag & VP_SPRAY) == 0) {
972                         if (ob->sculpt->mode.wpaint.alpha_weight == NULL) {
973                                 ob->sculpt->mode.wpaint.alpha_weight =
974                                         MEM_callocN(me->totvert * sizeof(float), __func__);
975                         }
976                         if (ob->sculpt->mode.wpaint.dvert_prev == NULL) {
977                                 ob->sculpt->mode.wpaint.dvert_prev =
978                                         MEM_callocN(me->totvert * sizeof(MDeformVert), __func__);
979                                 MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
980                                 for (int i = 0; i < me->totvert; i++, dv++) {
981                                         /* Use to show this isn't initialized, never apply to the mesh data. */
982                                         dv->flag = 1;
983                                 }
984                         }
985                 }
986                 else {
987                         MEM_SAFE_FREE(ob->sculpt->mode.wpaint.alpha_weight);
988                         if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
989                                 BKE_defvert_array_free_elems(ob->sculpt->mode.wpaint.dvert_prev, me->totvert);
990                                 MEM_freeN(ob->sculpt->mode.wpaint.dvert_prev);
991                                 ob->sculpt->mode.wpaint.dvert_prev = NULL;
992                         }
993                 }
994                 if (brush && brush->flag & BRUSH_ACCUMULATE) {
995                         if (ob->sculpt->mode.wpaint.previous_accum == NULL) {
996                                 ob->sculpt->mode.wpaint.previous_accum =
997                                         MEM_callocN(me->totvert * sizeof(float), __func__);
998                         }
999                 }
1000                 else {
1001                         MEM_SAFE_FREE(ob->sculpt->mode.wpaint.previous_accum);
1002                 }
1003         }
1004
1005 }
1006
1007 /* *************** set wpaint operator ****************** */
1008
1009 /**
1010  * \note Keep in sync with #vpaint_mode_toggle_exec
1011  */
1012 static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
1013 {
1014         Object *ob = CTX_data_active_object(C);
1015         const int mode_flag = OB_MODE_WEIGHT_PAINT;
1016         const bool is_mode_set = (ob->mode & mode_flag) != 0;
1017         Scene *scene = CTX_data_scene(C);
1018         VPaint *wp = scene->toolsettings->wpaint;
1019         Mesh *me;
1020
1021         if (!is_mode_set) {
1022                 if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
1023                         return OPERATOR_CANCELLED;
1024                 }
1025         }
1026
1027         me = BKE_mesh_from_object(ob);
1028
1029         if (ob->mode & mode_flag) {
1030                 ob->mode &= ~mode_flag;
1031
1032                 if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
1033                         BKE_mesh_flush_select_from_verts(me);
1034                 }
1035                 else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
1036                         BKE_mesh_flush_select_from_polys(me);
1037                 }
1038
1039                 /* weight paint specific */
1040                 ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
1041                 ED_mesh_mirror_topo_table(NULL, NULL, 'e');
1042
1043                 /* If the cache is not released by a cancel or a done, free it now. */
1044                 if (ob->sculpt->cache) {
1045                         sculpt_cache_free(ob->sculpt->cache);
1046                         ob->sculpt->cache = NULL;
1047                 }
1048
1049                 BKE_sculptsession_free(ob);
1050
1051                 paint_cursor_delete_textures();
1052         }
1053         else {
1054                 ob->mode |= mode_flag;
1055
1056                 if (wp == NULL)
1057                         wp = scene->toolsettings->wpaint = new_vpaint(1);
1058
1059                 paint_cursor_start(C, weight_paint_poll);
1060
1061                 BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
1062
1063                 /* weight paint specific */
1064                 ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
1065                 ED_vgroup_sync_from_pose(ob);
1066
1067                 /* Create vertex/weight paint mode session data */
1068                 if (ob->sculpt) {
1069                         BKE_sculptsession_free(ob);
1070                 }
1071                 vertex_paint_init_session(scene, ob);
1072         }
1073
1074         /* Weightpaint works by overriding colors in mesh,
1075          * so need to make sure we recalc on enter and
1076          * exit (exit needs doing regardless because we
1077          * should redeform).
1078          */
1079         DAG_id_tag_update(&me->id, 0);
1080
1081         WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
1082
1083         return OPERATOR_FINISHED;
1084 }
1085
1086 /* for switching to/from mode */
1087 static int paint_poll_test(bContext *C)
1088 {
1089         Object *ob = CTX_data_active_object(C);
1090         if (ob == NULL || ob->type != OB_MESH)
1091                 return 0;
1092         if (!ob->data || ID_IS_LINKED_DATABLOCK(ob->data))
1093                 return 0;
1094         if (CTX_data_edit_object(C))
1095                 return 0;
1096         return 1;
1097 }
1098
1099 void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
1100 {
1101
1102         /* identifiers */
1103         ot->name = "Weight Paint Mode";
1104         ot->idname = "PAINT_OT_weight_paint_toggle";
1105         ot->description = "Toggle weight paint mode in 3D view";
1106
1107         /* api callbacks */
1108         ot->exec = wpaint_mode_toggle_exec;
1109         ot->poll = paint_poll_test;
1110
1111         /* flags */
1112         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1113 }
1114
1115 /* ************ weight paint operator ********** */
1116
1117 struct WPaintData {
1118         ViewContext vc;
1119
1120         struct WeightPaintGroupData active, mirror;
1121
1122         void *vp_handle;
1123         DMCoNo *vertexcosnos;
1124
1125         float wpimat[3][3];
1126
1127         /* variables for auto normalize */
1128         const bool *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
1129         const bool *lock_flags;
1130
1131         /* variables for multipaint */
1132         const bool *defbase_sel;      /* set of selected groups */
1133         int defbase_tot_sel;          /* number of selected groups */
1134         bool do_multipaint;           /* true if multipaint enabled and multiple groups selected */
1135
1136         int defbase_tot;
1137 };
1138
1139 /* Initialize the stroke cache invariants from operator properties */
1140 static void vwpaint_update_cache_invariants(
1141         bContext *C, VPaint *vd, SculptSession *ss, wmOperator *op, const float mouse[2])
1142 {
1143         StrokeCache *cache;
1144         Scene *scene = CTX_data_scene(C);
1145         UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
1146         Brush *brush = BKE_paint_brush(&vd->paint);
1147         ViewContext *vc = paint_stroke_view_context(op->customdata);
1148         Object *ob = CTX_data_active_object(C);
1149         float mat[3][3];
1150         float view_dir[3] = {0.0f, 0.0f, 1.0f};
1151         int mode;
1152
1153         /* VW paint needs to allocate stroke cache before update is called. */
1154         if (!ss->cache) {
1155                 cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
1156                 ss->cache = cache;
1157         }
1158         else {
1159                 cache = ss->cache;
1160         }
1161
1162         /* Initial mouse location */
1163         if (mouse)
1164                 copy_v2_v2(cache->initial_mouse, mouse);
1165         else
1166                 zero_v2(cache->initial_mouse);
1167
1168         mode = RNA_enum_get(op->ptr, "mode");
1169         cache->invert = mode == BRUSH_STROKE_INVERT;
1170         cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
1171         /* not very nice, but with current events system implementation
1172         * we can't handle brush appearance inversion hotkey separately (sergey) */
1173         if (cache->invert) ups->draw_inverted = true;
1174         else ups->draw_inverted = false;
1175
1176         copy_v2_v2(cache->mouse, cache->initial_mouse);
1177         /* Truly temporary data that isn't stored in properties */
1178         cache->vc = vc;
1179         cache->brush = brush;
1180         cache->first_time = 1;
1181
1182         /* cache projection matrix */
1183         ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
1184
1185         invert_m4_m4(ob->imat, ob->obmat);
1186         copy_m3_m4(mat, cache->vc->rv3d->viewinv);
1187         mul_m3_v3(mat, view_dir);
1188         copy_m3_m4(mat, ob->imat);
1189         mul_m3_v3(mat, view_dir);
1190         normalize_v3_v3(cache->true_view_normal, view_dir);
1191
1192         copy_v3_v3(cache->view_normal, cache->true_view_normal);
1193         cache->bstrength = BKE_brush_alpha_get(scene, brush);
1194         cache->is_last_valid = false;
1195 }
1196
1197 /* Initialize the stroke cache variants from operator properties */
1198 static void vwpaint_update_cache_variants(bContext *C, VPaint *vd, Object *ob, PointerRNA *ptr)
1199 {
1200         Scene *scene = CTX_data_scene(C);
1201         SculptSession *ss = ob->sculpt;
1202         StrokeCache *cache = ss->cache;
1203         Brush *brush = BKE_paint_brush(&vd->paint);
1204
1205         /* This effects the actual brush radius, so things farther away
1206          * are compared with a larger radius and vise versa. */
1207         if (cache->first_time) {
1208                 RNA_float_get_array(ptr, "location", cache->true_location);
1209         }
1210
1211         RNA_float_get_array(ptr, "mouse", cache->mouse);
1212
1213         /* XXX: Use pressure value from first brush step for brushes which don't
1214          * support strokes (grab, thumb). They depends on initial state and
1215          * brush coord/pressure/etc.
1216          * It's more an events design issue, which doesn't split coordinate/pressure/angle
1217          * changing events. We should avoid this after events system re-design */
1218         if (paint_supports_dynamic_size(brush, ePaintSculpt) || cache->first_time) {
1219                 cache->pressure = RNA_float_get(ptr, "pressure");
1220         }
1221
1222         /* Truly temporary data that isn't stored in properties */
1223         if (cache->first_time) {
1224                 if (!BKE_brush_use_locked_size(scene, brush)) {
1225                         cache->initial_radius = paint_calc_object_space_radius(
1226                                 cache->vc, cache->true_location, BKE_brush_size_get(scene, brush));
1227                         BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
1228                 }
1229                 else {
1230                         cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
1231                 }
1232         }
1233
1234         if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, ePaintSculpt)) {
1235                 cache->radius = cache->initial_radius * cache->pressure;
1236         }
1237         else {
1238                 cache->radius = cache->initial_radius;
1239         }
1240
1241         cache->radius_squared = cache->radius * cache->radius;
1242
1243         if (ss->pbvh) {
1244                 BKE_pbvh_update(ss->pbvh, PBVH_UpdateRedraw, NULL);
1245                 BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
1246         }
1247 }
1248
1249 static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
1250 {
1251         Scene *scene = CTX_data_scene(C);
1252         struct PaintStroke *stroke = op->customdata;
1253         ToolSettings *ts = scene->toolsettings;
1254         Object *ob = CTX_data_active_object(C);
1255         Mesh *me = BKE_mesh_from_object(ob);
1256         struct WPaintData *wpd;
1257         struct WPaintVGroupIndex vgroup_index;
1258         int defbase_tot, defbase_tot_sel;
1259         bool *defbase_sel;
1260         SculptSession *ss = ob->sculpt;
1261         VPaint *vd = CTX_data_tool_settings(C)->wpaint;
1262
1263         float mat[4][4], imat[4][4];
1264
1265         if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
1266                 return false;
1267         }
1268
1269         {
1270                 /* check if we are attempting to paint onto a locked vertex group,
1271                  * and other options disallow it from doing anything useful */
1272                 bDeformGroup *dg;
1273                 dg = BLI_findlink(&ob->defbase, vgroup_index.active);
1274                 if (dg->flag & DG_LOCK_WEIGHT) {
1275                         BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
1276                         return false;
1277                 }
1278                 if (vgroup_index.mirror != -1) {
1279                         dg = BLI_findlink(&ob->defbase, vgroup_index.mirror);
1280                         if (dg->flag & DG_LOCK_WEIGHT) {
1281                                 BKE_report(op->reports, RPT_WARNING, "Mirror group is locked, aborting");
1282                                 return false;
1283                         }
1284                 }
1285         }
1286
1287         /* check that multipaint groups are unlocked */
1288         defbase_tot = BLI_listbase_count(&ob->defbase);
1289         defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_tot_sel);
1290
1291         if (ts->multipaint && defbase_tot_sel > 1) {
1292                 int i;
1293                 bDeformGroup *dg;
1294
1295                 if (me->editflag & ME_EDIT_MIRROR_X) {
1296                         BKE_object_defgroup_mirror_selection(ob, defbase_tot, defbase_sel, defbase_sel, &defbase_tot_sel);
1297                 }
1298
1299                 for (i = 0; i < defbase_tot; i++) {
1300                         if (defbase_sel[i]) {
1301                                 dg = BLI_findlink(&ob->defbase, i);
1302                                 if (dg->flag & DG_LOCK_WEIGHT) {
1303                                         BKE_report(op->reports, RPT_WARNING, "Multipaint group is locked, aborting");
1304                                         MEM_freeN(defbase_sel);
1305                                         return false;
1306                                 }
1307                         }
1308                 }
1309         }
1310
1311         /* ALLOCATIONS! no return after this line */
1312         /* make mode data storage */
1313         wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
1314         paint_stroke_set_mode_data(stroke, wpd);
1315         view3d_set_viewcontext(C, &wpd->vc);
1316
1317         wpd->active.index = vgroup_index.active;
1318         wpd->mirror.index = vgroup_index.mirror;
1319
1320         /* multipaint */
1321         wpd->defbase_tot = defbase_tot;
1322         wpd->defbase_sel = defbase_sel;
1323         wpd->defbase_tot_sel = defbase_tot_sel > 1 ? defbase_tot_sel : 1;
1324         wpd->do_multipaint = (ts->multipaint && defbase_tot_sel > 1);
1325
1326         /* set up auto-normalize, and generate map for detecting which
1327          * vgroups affect deform bones */
1328         wpd->lock_flags = BKE_object_defgroup_lock_flags_get(ob, wpd->defbase_tot);
1329         if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) {
1330                 wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot);
1331         }
1332
1333         if (wpd->do_multipaint && ts->auto_normalize) {
1334                 bool *tmpflags;
1335                 tmpflags = MEM_mallocN(sizeof(bool) * defbase_tot, __func__);
1336                 if (wpd->lock_flags) {
1337                         BLI_array_binary_or(tmpflags, wpd->defbase_sel, wpd->lock_flags, wpd->defbase_tot);
1338                 }
1339                 else {
1340                         memcpy(tmpflags, wpd->defbase_sel, sizeof(*tmpflags) * wpd->defbase_tot);
1341                 }
1342                 wpd->active.lock = tmpflags;
1343         }
1344         else if (ts->auto_normalize) {
1345                 bool *tmpflags;
1346
1347                 tmpflags = wpd->lock_flags ?
1348                         MEM_dupallocN(wpd->lock_flags) :
1349                         MEM_callocN(sizeof(bool) * defbase_tot, __func__);
1350                 tmpflags[wpd->active.index] = true;
1351                 wpd->active.lock = tmpflags;
1352
1353                 tmpflags = wpd->lock_flags ?
1354                         MEM_dupallocN(wpd->lock_flags) :
1355                         MEM_callocN(sizeof(bool) * defbase_tot, __func__);
1356                 tmpflags[(wpd->mirror.index != -1) ? wpd->mirror.index : wpd->active.index] = true;
1357                 wpd->mirror.lock = tmpflags;
1358         }
1359
1360         /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1361         ob->sculpt->building_vp_handle = true;
1362         wpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &wpd->vertexcosnos);
1363         ob->sculpt->building_vp_handle = false;
1364
1365         /* imat for normals */
1366         mul_m4_m4m4(mat, wpd->vc.rv3d->viewmat, ob->obmat);
1367         invert_m4_m4(imat, mat);
1368         copy_m3_m4(wpd->wpimat, imat);
1369
1370         /* If not previously created, create vertex/weight paint mode session data */
1371         vertex_paint_init_session(scene, ob);
1372         vwpaint_update_cache_invariants(C, vd, ss, op, mouse);
1373         vertex_paint_init_session_data(ts, ob);
1374
1375         if (ob->sculpt->mode.wpaint.dvert_prev != NULL) {
1376                 MDeformVert *dv = ob->sculpt->mode.wpaint.dvert_prev;
1377                 for (int i = 0; i < me->totvert; i++, dv++) {
1378                         /* Use to show this isn't initialized, never apply to the mesh data. */
1379                         dv->flag = 1;
1380                 }
1381         }
1382
1383         return true;
1384 }
1385
1386 static float dot_vf3vs3(const float brushNormal[3], const short vertexNormal[3])
1387 {
1388         float normal[3];
1389         normal_short_to_float_v3(normal, vertexNormal);
1390         return dot_v3v3(brushNormal, normal);
1391 }
1392
1393 static void get_brush_alpha_data(
1394         Scene *scene, SculptSession *ss, Brush *brush,
1395         float *r_brush_size_pressure, float *r_brush_alpha_value, float *r_brush_alpha_pressure)
1396 {
1397         *r_brush_size_pressure =
1398                 BKE_brush_size_get(scene, brush) *
1399                 (BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure : 1.0f);
1400         *r_brush_alpha_value =
1401                 BKE_brush_alpha_get(scene, brush);
1402         *r_brush_alpha_pressure =
1403                 (BKE_brush_use_alpha_pressure(scene, brush) ? ss->cache->pressure : 1.0f);
1404 }
1405
1406 static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi)
1407 {
1408         if (wpi->do_multipaint) {
1409                 float weight = BKE_defvert_multipaint_collective_weight(
1410                      dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
1411
1412                 CLAMP(weight, 0.0f, 1.0f);
1413                 return weight;
1414         }
1415         else {
1416                 return defvert_find_weight(dv, wpi->active.index);
1417         }
1418 }
1419
1420 static void do_wpaint_brush_blur_task_cb_ex(
1421         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
1422 {
1423         SculptThreadedTaskData *data = userdata;
1424         SculptSession *ss = data->ob->sculpt;
1425         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
1426         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
1427
1428         Brush *brush = data->brush;
1429         StrokeCache *cache = ss->cache;
1430         Scene *scene = CTX_data_scene(data->C);
1431
1432         const float brush_strength = cache->bstrength;
1433         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
1434         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
1435         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1436         const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1437
1438         SculptBrushTest test;
1439         sculpt_brush_test_init(ss, &test);
1440
1441         /* For each vertex */
1442         PBVHVertexIter vd;
1443         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
1444         {
1445                 /* Test to see if the vertex coordinates are within the spherical brush region. */
1446                 if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
1447                         /* For grid based pbvh, take the vert whose loop coopresponds to the current grid.
1448                          * Otherwise, take the current vert. */
1449                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
1450                         const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
1451                         const char v_flag = data->me->mvert[v_index].flag;
1452                         /* If the vertex is selected */
1453                         if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
1454                                 /* Get the average poly weight */
1455                                 int total_hit_loops = 0;
1456                                 float weight_final = 0.0f;
1457                                 for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
1458                                         const int p_index = gmap->vert_to_poly[v_index].indices[j];
1459                                         const MPoly *mp = &data->me->mpoly[p_index];
1460
1461                                         total_hit_loops += mp->totloop;
1462                                         for (int k = 0; k < mp->totloop; k++) {
1463                                                 const int l_index = mp->loopstart + k;
1464                                                 const MLoop *ml = &data->me->mloop[l_index];
1465                                                 const MDeformVert *dv = &data->me->dvert[ml->v];
1466                                                 weight_final += wpaint_get_active_weight(dv, data->wpi);
1467                                         }
1468                                 }
1469
1470                                 /* Apply the weight to the vertex. */
1471                                 if (total_hit_loops != 0) {
1472                                         const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
1473                                         if (view_dot > 0.0f) {
1474                                                 const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
1475                                                 float final_alpha =
1476                                                         brush_fade * brush_strength *
1477                                                         grid_alpha * brush_alpha_pressure;
1478
1479                                                 if (data->vp->flag & VP_NORMALS) {
1480                                                         final_alpha *= view_dot;
1481                                                 }
1482                                                 if (brush->flag & BRUSH_ACCUMULATE) {
1483                                                         float mask_accum = ss->mode.wpaint.previous_accum[v_index];
1484                                                         final_alpha = min_ff(final_alpha + mask_accum, brush_strength);
1485                                                         ss->mode.wpaint.previous_accum[v_index] = final_alpha;
1486                                                 }
1487
1488                                                 weight_final /= total_hit_loops;
1489                                                 /* Only paint visable verts */
1490                                                 do_weight_paint_vertex(
1491                                                         data->vp, data->ob, data->wpi,
1492                                                         v_index, final_alpha, weight_final);
1493                                         }
1494                                 }
1495                         }
1496                 }
1497         }
1498         BKE_pbvh_vertex_iter_end;
1499 }
1500
1501 static void do_wpaint_brush_smear_task_cb_ex(
1502         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
1503 {
1504         SculptThreadedTaskData *data = userdata;
1505         SculptSession *ss = data->ob->sculpt;
1506         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
1507         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.wpaint.gmap;
1508
1509         Brush *brush = data->brush;
1510         Scene *scene = CTX_data_scene(data->C);
1511         StrokeCache *cache = ss->cache;
1512         const float brush_strength = cache->bstrength;
1513         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
1514         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
1515         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1516         const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1517         float brush_dir[3];
1518
1519         sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
1520         project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
1521
1522         if (normalize_v3(brush_dir) != 0.0f) {
1523
1524                 SculptBrushTest test;
1525                 sculpt_brush_test_init(ss, &test);
1526
1527                 /* For each vertex */
1528                 PBVHVertexIter vd;
1529                 BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
1530                 {
1531                         /* Test to see if the vertex coordinates are within the spherical brush region. */
1532                         if (sculpt_brush_test_sphere_fast(&test, vd.co)) {
1533                                 const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
1534                                 if (view_dot > 0.0f) {
1535                                         bool do_color = false;
1536
1537                                         /* For grid based pbvh, take the vert whose loop cooresponds to the current grid.
1538                                          * Otherwise, take the current vert. */
1539                                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
1540                                         const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
1541                                         const MVert *mv_curr = &data->me->mvert[v_index];
1542
1543                                         /* If the vertex is selected */
1544                                         if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) {
1545                                                 /* Minimum dot product between brush direction and current
1546                                                  * to neighbor direction is 0.0, meaning orthogonal. */
1547                                                 float stroke_dot_max = 0.0f;
1548
1549                                                 /* Get the color of the loop in the opposite direction of the brush movement
1550                                                  * (this callback is specifically for smear.) */
1551                                                 float weight_final = 0.0;
1552                                                 for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
1553                                                         const int p_index = gmap->vert_to_poly[v_index].indices[j];
1554                                                         const MPoly *mp = &data->me->mpoly[p_index];
1555                                                         const MLoop *ml_other = &data->me->mloop[mp->loopstart];
1556                                                         for (int k = 0; k < mp->totloop; k++, ml_other++) {
1557                                                                 const uint v_other_index = ml_other->v;
1558                                                                 if (v_other_index != v_index) {
1559                                                                         const MVert *mv_other = &data->me->mvert[v_other_index];
1560
1561                                                                         /* Get the direction from the selected vert to the neighbor. */
1562                                                                         float other_dir[3];
1563                                                                         sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
1564                                                                         project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
1565
1566                                                                         normalize_v3(other_dir);
1567
1568                                                                         const float stroke_dot = dot_v3v3(other_dir, brush_dir);
1569
1570                                                                         if (stroke_dot > stroke_dot_max) {
1571                                                                                 stroke_dot_max = stroke_dot;
1572                                                                                 MDeformVert *dv = &data->me->dvert[v_other_index];
1573                                                                                 weight_final = wpaint_get_active_weight(dv, data->wpi);
1574                                                                                 do_color = true;
1575                                                                         }
1576                                                                 }
1577                                                         }
1578                                                 }
1579                                                 /* Apply weight to vertex */
1580                                                 if (do_color) {
1581                                                         const float brush_fade = BKE_brush_curve_strength(brush, test.dist, cache->radius);
1582                                                         float final_alpha =
1583                                                                 brush_fade * brush_strength *
1584                                                                 grid_alpha * brush_alpha_pressure;
1585
1586                                                         if (data->vp->flag & VP_NORMALS) {
1587                                                                 final_alpha *= view_dot;
1588                                                         }
1589                                                         do_weight_paint_vertex(
1590                                                                 data->vp, data->ob, data->wpi,
1591                                                                 v_index, final_alpha, (float)weight_final);
1592                                                 }
1593                                         }
1594                                 }
1595                         }
1596                 }
1597                 BKE_pbvh_vertex_iter_end;
1598         }
1599 }
1600
1601 static void do_wpaint_brush_draw_task_cb_ex(
1602         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
1603 {
1604         SculptThreadedTaskData *data = userdata;
1605         SculptSession *ss = data->ob->sculpt;
1606         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
1607         Scene *scene = CTX_data_scene(data->C);
1608
1609         Brush *brush = data->brush;
1610         StrokeCache *cache = ss->cache;
1611         const float brush_strength = cache->bstrength;
1612         const float paintweight = BKE_brush_weight_get(scene, brush);
1613         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
1614         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
1615         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1616         const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1617
1618         SculptBrushTest test;
1619         sculpt_brush_test_init(ss, &test);
1620
1621         /* For each vertex */
1622         PBVHVertexIter vd;
1623         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
1624         {
1625                 /* Test to see if the vertex coordinates are within the spherical brush region. */
1626                 if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
1627                         /* Note: grids are 1:1 with corners (aka loops).
1628                          * For multires, take the vert whose loop cooresponds to the current grid.
1629                          * Otherwise, take the current vert. */
1630                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
1631                         const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
1632
1633                         const char v_flag = data->me->mvert[v_index].flag;
1634                         /* If the vertex is selected */
1635                         if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
1636                                 const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
1637                                 if (view_dot > 0.0f) {
1638                                         const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
1639                                         float final_alpha = brush_fade * brush_strength * grid_alpha * brush_alpha_pressure;
1640
1641                                         if (data->vp->flag & VP_NORMALS) {
1642                                                 final_alpha *= view_dot;
1643                                         }
1644                                         if (brush->flag & BRUSH_ACCUMULATE) {
1645                                                 float mask_accum = ss->mode.wpaint.previous_accum[v_index];
1646                                                 final_alpha = min_ff(final_alpha + mask_accum, brush_strength);
1647                                                 ss->mode.wpaint.previous_accum[v_index] = final_alpha;
1648                                         }
1649
1650                                         /* Non-spray logic. */
1651                                         if ((data->vp->flag & VP_SPRAY) == 0) {
1652                                                 /* Only paint if we have greater alpha. */
1653                                                 if (ss->mode.wpaint.alpha_weight[v_index] < final_alpha) {
1654                                                         ss->mode.wpaint.alpha_weight[v_index] = final_alpha;
1655                                                 }
1656                                                 else {
1657                                                         continue;
1658                                                 }
1659                                         }
1660
1661                                         do_weight_paint_vertex(
1662                                                 data->vp, data->ob, data->wpi,
1663                                                 v_index, final_alpha, paintweight);
1664                                 }
1665                         }
1666                 }
1667         }
1668         BKE_pbvh_vertex_iter_end;
1669 }
1670
1671 static void do_wpaint_brush_calc_average_weight_cb_ex(
1672         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
1673 {
1674         SculptThreadedTaskData *data = userdata;
1675         SculptSession *ss = data->ob->sculpt;
1676         StrokeCache *cache = ss->cache;
1677         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
1678
1679         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
1680         const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1681
1682         struct WPaintAverageAccum *accum = (struct WPaintAverageAccum *)data->custom_data + n;
1683         accum->len = 0;
1684         accum->value = 0.0;
1685
1686         SculptBrushTest test;
1687         sculpt_brush_test_init(ss, &test);
1688
1689         /* For each vertex */
1690         PBVHVertexIter vd;
1691         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
1692         {
1693                 /* Test to see if the vertex coordinates are within the spherical brush region. */
1694                 if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
1695                         const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
1696                         if (view_dot > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) {
1697                                 const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
1698                                 // const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
1699                                 const char v_flag = data->me->mvert[v_index].flag;
1700
1701                                 /* If the vertex is selected. */
1702                                 if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) {
1703                                         const MDeformVert *dv = &data->me->dvert[v_index];
1704                                         accum->len += 1;
1705                                         accum->value += wpaint_get_active_weight(dv, data->wpi);
1706                                 }
1707                         }
1708                 }
1709         }
1710         BKE_pbvh_vertex_iter_end;
1711 }
1712
1713 static void calculate_average_weight(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
1714 {
1715         Scene *scene = CTX_data_scene(data->C);
1716         UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
1717
1718         struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
1719         data->custom_data = accum;
1720
1721         BLI_task_parallel_range_ex(
1722                 0, totnode, data, NULL, 0, do_wpaint_brush_calc_average_weight_cb_ex,
1723                 ((data->sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT), false);
1724
1725         uint accum_len = 0;
1726         double accum_weight = 0.0;
1727         for (int i = 0; i < totnode; i++) {
1728                 accum_len += accum[i].len;
1729                 accum_weight += accum[i].value;
1730         }
1731         if (accum_len != 0) {
1732                 accum_weight /= accum_len;
1733                 if (ups->flag & UNIFIED_PAINT_WEIGHT)
1734                         ups->weight = (float)accum_weight;
1735                 else
1736                         data->brush->weight = (float)accum_weight;
1737         }
1738
1739         MEM_SAFE_FREE(data->custom_data);  /* 'accum' */
1740 }
1741
1742
1743 static void wpaint_paint_leaves(
1744         bContext *C, Object *ob, Sculpt *sd, VPaint *vp, struct WPaintData *wpd, WeightPaintInfo *wpi,
1745         Mesh *me, PBVHNode **nodes, int totnode)
1746 {
1747         Brush *brush = ob->sculpt->cache->brush;
1748
1749         /* threaded loop over nodes */
1750         SculptThreadedTaskData data = {
1751                 .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .wpd = wpd, .wpi = wpi, .me = me, .C = C,
1752         };
1753
1754         switch (brush->vertexpaint_tool) {
1755                 case PAINT_BLEND_AVERAGE:
1756                         calculate_average_weight(&data, nodes, totnode);
1757                         BLI_task_parallel_range_ex(
1758                                 0, totnode, &data, NULL, 0,
1759                                 do_wpaint_brush_draw_task_cb_ex, true, false);
1760                         break;
1761                 case PAINT_BLEND_SMEAR:
1762                         BLI_task_parallel_range_ex(
1763                                 0, totnode, &data, NULL, 0,
1764                                 do_wpaint_brush_smear_task_cb_ex, true, false);
1765                         break;
1766                 case PAINT_BLEND_BLUR:
1767                         BLI_task_parallel_range_ex(
1768                                 0, totnode, &data, NULL, 0,
1769                                 do_wpaint_brush_blur_task_cb_ex, true, false);
1770                         break;
1771                 default:
1772                         BLI_task_parallel_range_ex(
1773                                 0, totnode, &data, NULL, 0,
1774                                 do_wpaint_brush_draw_task_cb_ex, true, false);
1775                         break;
1776         }
1777 }
1778
1779 static void wpaint_do_paint(
1780         bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi,
1781         Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
1782 {
1783         SculptSession *ss = ob->sculpt;
1784         ss->cache->radial_symmetry_pass = i;
1785         sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
1786
1787         SculptSearchSphereData data;
1788         PBVHNode **nodes = NULL;
1789         int totnode;
1790
1791
1792         /* Build a list of all nodes that are potentially within the brush's area of influence */
1793         data.ss = ss;
1794         data.sd = sd;
1795         data.radius_squared = ss->cache->radius_squared;
1796         data.original = true;
1797         BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
1798
1799         sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, ss->cache->sculpt_normal_symm);
1800         wpaint_paint_leaves(C, ob, sd, wp, wpd, wpi, me, nodes, totnode);
1801
1802         if (nodes)
1803                 MEM_freeN(nodes);
1804 }
1805
1806 static void wpaint_do_radial_symmetry(
1807         bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi,
1808         Mesh *me, Brush *brush, const char symm, const int axis)
1809 {
1810         for (int i = 1; i < wp->radial_symm[axis - 'X']; i++) {
1811                 const float angle = (2.0 * M_PI) * i / wp->radial_symm[axis - 'X'];
1812                 wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, axis, i, angle);
1813         }
1814 }
1815
1816 /* near duplicate of: sculpt.c's, 'do_symmetrical_brush_actions' and 'vpaint_do_symmetrical_brush_actions'. */
1817 static void wpaint_do_symmetrical_brush_actions(
1818         bContext *C, Object *ob, VPaint *wp, Sculpt *sd, struct WPaintData *wpd, WeightPaintInfo *wpi)
1819 {
1820         Brush *brush = BKE_paint_brush(&wp->paint);
1821         Mesh *me = ob->data;
1822         SculptSession *ss = ob->sculpt;
1823         StrokeCache *cache = ss->cache;
1824         const char symm = wp->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
1825         int i = 0;
1826
1827         /* initial stroke */
1828         wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X', 0, 0);
1829         wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X');
1830         wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Y');
1831         wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Z');
1832
1833         cache->symmetry = symm;
1834
1835         /* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
1836         for (i = 1; i <= symm; i++) {
1837                 if ((symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
1838                         cache->mirror_symmetry_pass = i;
1839                         cache->radial_symmetry_pass = 0;
1840                         sculpt_cache_calc_brushdata_symm(cache, i, 0, 0);
1841
1842                         if (i & (1 << 0)) {
1843                                 wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
1844                                 wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X');
1845                         }
1846                         if (i & (1 << 1)) {
1847                                 wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y', 0, 0);
1848                                 wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y');
1849                         }
1850                         if (i & (1 << 2)) {
1851                                 wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z', 0, 0);
1852                                 wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z');
1853                         }
1854                 }
1855         }
1856         copy_v3_v3(cache->true_last_location, cache->true_location);
1857         cache->is_last_valid = true;
1858 }
1859
1860 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
1861 {
1862         Scene *scene = CTX_data_scene(C);
1863         ToolSettings *ts = CTX_data_tool_settings(C);
1864         VPaint *wp = ts->wpaint;
1865         Brush *brush = BKE_paint_brush(&wp->paint);
1866         struct WPaintData *wpd = paint_stroke_mode_data(stroke);
1867         ViewContext *vc;
1868         Object *ob = CTX_data_active_object(C);
1869
1870         SculptSession *ss = ob->sculpt;
1871         Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
1872
1873         vwpaint_update_cache_variants(C, wp, ob, itemptr);
1874
1875         float mat[4][4];
1876         float mval[2];
1877
1878         const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
1879
1880         /* intentionally don't initialize as NULL, make sure we initialize all members below */
1881         WeightPaintInfo wpi;
1882
1883         /* cannot paint if there is no stroke data */
1884         if (wpd == NULL) {
1885                 /* XXX: force a redraw here, since even though we can't paint,
1886                  * at least view won't freeze until stroke ends */
1887                 ED_region_tag_redraw(CTX_wm_region(C));
1888                 return;
1889         }
1890
1891         vc = &wpd->vc;
1892         ob = vc->obact;
1893
1894         view3d_operator_needs_opengl(C);
1895         ED_view3d_init_mats_rv3d(ob, vc->rv3d);
1896
1897         /* load projection matrix */
1898         mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
1899
1900
1901         /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
1902         wpi.defbase_tot =        wpd->defbase_tot;
1903         wpi.defbase_sel =        wpd->defbase_sel;
1904         wpi.defbase_tot_sel =    wpd->defbase_tot_sel;
1905
1906         wpi.defbase_tot_unsel =  wpi.defbase_tot - wpi.defbase_tot_sel;
1907         wpi.active =             wpd->active;
1908         wpi.mirror =             wpd->mirror;
1909         wpi.lock_flags =         wpd->lock_flags;
1910         wpi.vgroup_validmap =    wpd->vgroup_validmap;
1911         wpi.do_flip =            RNA_boolean_get(itemptr, "pen_flip");
1912         wpi.do_multipaint =      wpd->do_multipaint;
1913         wpi.do_auto_normalize =  ((ts->auto_normalize != 0) && (wpi.vgroup_validmap != NULL));
1914         wpi.brush_alpha_value =  brush_alpha_value;
1915         /* *** done setting up WeightPaintInfo *** */
1916
1917         wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi);
1918
1919         swap_m4m4(vc->rv3d->persmat, mat);
1920
1921         /* calculate pivot for rotation around seletion if needed */
1922         /* also needed for "View Selected" on last stroke */
1923         paint_last_stroke_update(scene, vc->ar, mval);
1924
1925         DAG_id_tag_update(ob->data, 0);
1926         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
1927         swap_m4m4(wpd->vc.rv3d->persmat, mat);
1928
1929         rcti r;
1930         if (sculpt_get_redraw_rect(vc->ar, CTX_wm_region_view3d(C), ob, &r)) {
1931                 if (ss->cache) {
1932                         ss->cache->current_r = r;
1933                 }
1934
1935                 /* previous is not set in the current cache else
1936                  * the partial rect will always grow */
1937                 if (ss->cache) {
1938                         if (!BLI_rcti_is_empty(&ss->cache->previous_r))
1939                                 BLI_rcti_union(&r, &ss->cache->previous_r);
1940                 }
1941
1942                 r.xmin += vc->ar->winrct.xmin - 2;
1943                 r.xmax += vc->ar->winrct.xmin + 2;
1944                 r.ymin += vc->ar->winrct.ymin - 2;
1945                 r.ymax += vc->ar->winrct.ymin + 2;
1946
1947                 ss->partial_redraw = 1;
1948         }
1949         ED_region_tag_redraw_partial(vc->ar, &r);
1950 }
1951
1952 static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
1953 {
1954         Object *ob = CTX_data_active_object(C);
1955         struct WPaintData *wpd = paint_stroke_mode_data(stroke);
1956
1957         if (wpd) {
1958                 ED_vpaint_proj_handle_free(wpd->vp_handle);
1959
1960                 if (wpd->defbase_sel)
1961                         MEM_freeN((void *)wpd->defbase_sel);
1962                 if (wpd->vgroup_validmap)
1963                         MEM_freeN((void *)wpd->vgroup_validmap);
1964                 if (wpd->lock_flags)
1965                         MEM_freeN((void *)wpd->lock_flags);
1966                 if (wpd->active.lock)
1967                         MEM_freeN((void *)wpd->active.lock);
1968                 if (wpd->mirror.lock)
1969                         MEM_freeN((void *)wpd->mirror.lock);
1970
1971                 MEM_freeN(wpd);
1972         }
1973
1974         /* and particles too */
1975         if (ob->particlesystem.first) {
1976                 ParticleSystem *psys;
1977                 int i;
1978
1979                 for (psys = ob->particlesystem.first; psys; psys = psys->next) {
1980                         for (i = 0; i < PSYS_TOT_VG; i++) {
1981                                 if (psys->vgroup[i] == ob->actdef) {
1982                                         psys->recalc |= PSYS_RECALC_RESET;
1983                                         break;
1984                                 }
1985                         }
1986                 }
1987         }
1988
1989         DAG_id_tag_update(ob->data, 0);
1990
1991         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
1992
1993         sculpt_cache_free(ob->sculpt->cache);
1994         ob->sculpt->cache = NULL;
1995 }
1996
1997
1998 static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1999 {
2000         int retval;
2001
2002         op->customdata = paint_stroke_new(
2003                 C, op, sculpt_stroke_get_location, wpaint_stroke_test_start,
2004                 wpaint_stroke_update_step, NULL,
2005                 wpaint_stroke_done, event->type);
2006
2007         if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
2008                 paint_stroke_data_free(op);
2009                 return OPERATOR_FINISHED;
2010         }
2011         /* add modal handler */
2012         WM_event_add_modal_handler(C, op);
2013
2014         OPERATOR_RETVAL_CHECK(retval);
2015         BLI_assert(retval == OPERATOR_RUNNING_MODAL);
2016
2017         return OPERATOR_RUNNING_MODAL;
2018 }
2019
2020 static int wpaint_exec(bContext *C, wmOperator *op)
2021 {
2022         op->customdata = paint_stroke_new(
2023                 C, op, sculpt_stroke_get_location, wpaint_stroke_test_start,
2024                 wpaint_stroke_update_step, NULL,
2025                 wpaint_stroke_done, 0);
2026
2027         /* frees op->customdata */
2028         paint_stroke_exec(C, op);
2029
2030         return OPERATOR_FINISHED;
2031 }
2032
2033 static void wpaint_cancel(bContext *C, wmOperator *op)
2034 {
2035         Object *ob = CTX_data_active_object(C);
2036         if (ob->sculpt->cache) {
2037                 sculpt_cache_free(ob->sculpt->cache);
2038                 ob->sculpt->cache = NULL;
2039         }
2040
2041         paint_stroke_cancel(C, op);
2042 }
2043
2044 void PAINT_OT_weight_paint(wmOperatorType *ot)
2045 {
2046         /* identifiers */
2047         ot->name = "Weight Paint";
2048         ot->idname = "PAINT_OT_weight_paint";
2049         ot->description = "Paint a stroke in the current vertex group's weights";
2050
2051         /* api callbacks */
2052         ot->invoke = wpaint_invoke;
2053         ot->modal = paint_stroke_modal;
2054         ot->exec = wpaint_exec;
2055         ot->poll = weight_paint_poll;
2056         ot->cancel = wpaint_cancel;
2057
2058         /* flags */
2059         ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
2060
2061         paint_stroke_operator_properties(ot);
2062 }
2063
2064 /* ************ set / clear vertex paint mode ********** */
2065
2066 /**
2067  * \note Keep in sync with #wpaint_mode_toggle_exec
2068  */
2069 static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
2070 {
2071         Object *ob = CTX_data_active_object(C);
2072         const int mode_flag = OB_MODE_VERTEX_PAINT;
2073         const bool is_mode_set = (ob->mode & mode_flag) != 0;
2074         Scene *scene = CTX_data_scene(C);
2075         VPaint *vp = scene->toolsettings->vpaint;
2076         Mesh *me;
2077
2078         if (!is_mode_set) {
2079                 if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
2080                         return OPERATOR_CANCELLED;
2081                 }
2082         }
2083
2084         me = BKE_mesh_from_object(ob);
2085
2086         /* toggle: end vpaint */
2087         if (is_mode_set) {
2088                 ob->mode &= ~mode_flag;
2089
2090                 if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
2091                         BKE_mesh_flush_select_from_polys(me);
2092                 }
2093                 else if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
2094                         BKE_mesh_flush_select_from_verts(me);
2095                 }
2096
2097                 /* If the cache is not released by a cancel or a done, free it now. */
2098                 if (ob->sculpt->cache) {
2099                         sculpt_cache_free(ob->sculpt->cache);
2100                         ob->sculpt->cache = NULL;
2101                 }
2102
2103                 BKE_sculptsession_free(ob);
2104
2105                 paint_cursor_delete_textures();
2106         }
2107         else {
2108                 ob->mode |= mode_flag;
2109
2110                 ED_mesh_color_ensure(me, NULL);
2111
2112                 if (vp == NULL)
2113                         vp = scene->toolsettings->vpaint = new_vpaint(0);
2114
2115                 paint_cursor_start(C, vertex_paint_poll);
2116
2117                 BKE_paint_init(scene, ePaintVertex, PAINT_CURSOR_VERTEX_PAINT);
2118
2119                 /* Create vertex/weight paint mode session data */
2120                 if (ob->sculpt) {
2121                         if (ob->sculpt->cache) {
2122                                 sculpt_cache_free(ob->sculpt->cache);
2123                                 ob->sculpt->cache = NULL;
2124                         }
2125                         BKE_sculptsession_free(ob);
2126                 }
2127                 vertex_paint_init_session(scene, ob);
2128         }
2129
2130         /* update modifier stack for mapping requirements */
2131         DAG_id_tag_update(&me->id, 0);
2132
2133         WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
2134
2135         return OPERATOR_FINISHED;
2136 }
2137
2138 void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
2139 {
2140         /* identifiers */
2141         ot->name = "Vertex Paint Mode";
2142         ot->idname = "PAINT_OT_vertex_paint_toggle";
2143         ot->description = "Toggle the vertex paint mode in 3D view";
2144
2145         /* api callbacks */
2146         ot->exec = vpaint_mode_toggle_exec;
2147         ot->poll = paint_poll_test;
2148
2149         /* flags */
2150         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2151 }
2152
2153
2154
2155 /* ********************** vertex paint operator ******************* */
2156
2157 /* Implementation notes:
2158  *
2159  * Operator->invoke()
2160  * - validate context (add mcol)
2161  * - create customdata storage
2162  * - call paint once (mouse click)
2163  * - add modal handler
2164  *
2165  * Operator->modal()
2166  * - for every mousemove, apply vertex paint
2167  * - exit on mouse release, free customdata
2168  *   (return OPERATOR_FINISHED also removes handler and operator)
2169  *
2170  * For future:
2171  * - implement a stroke event (or mousemove with past positons)
2172  * - revise whether op->customdata should be added in object, in set_vpaint
2173  */
2174
2175 typedef struct PolyFaceMap {
2176         struct PolyFaceMap *next, *prev;
2177         int facenr;
2178 } PolyFaceMap;
2179
2180 struct VPaintData {
2181         ViewContext vc;
2182         uint paintcol;
2183
2184         struct VertProjHandle *vp_handle;
2185         struct DMCoNo *vertexcosnos;
2186
2187         float vpimat[3][3];
2188
2189         /* modify 'me->mcol' directly, since the derived mesh is drawing from this
2190          * array, otherwise we need to refresh the modifier stack */
2191         bool use_fast_update;
2192
2193         /* loops tagged as having been painted, to apply shared vertex color
2194          * blending only to modified loops */
2195         bool *mlooptag;
2196
2197         bool is_texbrush;
2198 };
2199
2200 static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
2201 {
2202         Scene *scene = CTX_data_scene(C);
2203         ToolSettings *ts = scene->toolsettings;
2204         struct PaintStroke *stroke = op->customdata;
2205         VPaint *vp = ts->vpaint;
2206         Brush *brush = BKE_paint_brush(&vp->paint);
2207         struct VPaintData *vpd;
2208         Object *ob = CTX_data_active_object(C);
2209         Mesh *me;
2210         float mat[4][4], imat[4][4];
2211         SculptSession *ss = ob->sculpt;
2212
2213         /* context checks could be a poll() */
2214         me = BKE_mesh_from_object(ob);
2215         if (me == NULL || me->totpoly == 0)
2216                 return false;
2217
2218         ED_mesh_color_ensure(me, NULL);
2219         if (me->mloopcol == NULL)
2220                 return false;
2221
2222         /* make mode data storage */
2223         vpd = MEM_callocN(sizeof(*vpd), "VPaintData");
2224         paint_stroke_set_mode_data(stroke, vpd);
2225         view3d_set_viewcontext(C, &vpd->vc);
2226
2227         vpd->paintcol = vpaint_get_current_col(scene, vp);
2228
2229         vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
2230                            brush->mtex.tex;
2231
2232         /* are we painting onto a modified mesh?,
2233          * if not we can skip face map trickiness */
2234         if (vertex_paint_use_fast_update_check(ob)) {
2235                 vpd->use_fast_update = true;
2236 /*              printf("Fast update!\n");*/
2237         }
2238         else {
2239                 vpd->use_fast_update = false;
2240 /*              printf("No fast update!\n");*/
2241         }
2242
2243         /* to keep tracked of modified loops for shared vertex color blending */
2244         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2245                 vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
2246         }
2247
2248         /* Create projection handle */
2249         if (vpd->is_texbrush) {
2250                 ob->sculpt->building_vp_handle = true;
2251                 vpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &vpd->vertexcosnos);
2252                 ob->sculpt->building_vp_handle = false;
2253         }
2254
2255         /* some old cruft to sort out later */
2256         mul_m4_m4m4(mat, vpd->vc.rv3d->viewmat, ob->obmat);
2257         invert_m4_m4(imat, mat);
2258         copy_m3_m4(vpd->vpimat, imat);
2259
2260         /* If not previously created, create vertex/weight paint mode session data */
2261         vertex_paint_init_session(scene, ob);
2262         vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
2263         vertex_paint_init_session_data(ts, ob);
2264
2265         if (ob->sculpt->mode.vpaint.previous_color != NULL) {
2266                 memset(ob->sculpt->mode.vpaint.previous_color, 0, sizeof(uint) * me->totloop);
2267         }
2268
2269         return 1;
2270 }
2271
2272 static void do_vpaint_brush_calc_average_color_cb_ex(
2273         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
2274 {
2275         SculptThreadedTaskData *data = userdata;
2276         SculptSession *ss = data->ob->sculpt;
2277         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
2278         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2279
2280         StrokeCache *cache = ss->cache;
2281         uint *lcol = data->lcol;
2282         char *col;
2283         const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
2284
2285         struct VPaintAverageAccum *accum = (struct VPaintAverageAccum *)data->custom_data + n;
2286         accum->len = 0;
2287         memset(accum->value, 0, sizeof(accum->value));
2288
2289         SculptBrushTest test;
2290         sculpt_brush_test_init(ss, &test);
2291
2292         /* For each vertex */
2293         PBVHVertexIter vd;
2294         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
2295         {
2296                 /* Test to see if the vertex coordinates are within the spherical brush region. */
2297                 if (sculpt_brush_test_sphere_fast(&test, vd.co)) {
2298                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
2299                         if (BKE_brush_curve_strength(data->brush, test.dist, cache->radius) > 0.0) {
2300                                 /* If the vertex is selected for painting. */
2301                                 const MVert *mv = &data->me->mvert[v_index];
2302                                 if (!use_vert_sel || mv->flag & SELECT) {
2303                                         accum->len += gmap->vert_to_loop[v_index].count;
2304                                         /* if a vertex is within the brush region, then add it's color to the blend. */
2305                                         for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) {
2306                                                 const int l_index = gmap->vert_to_loop[v_index].indices[j];
2307                                                 col = (char *)(&lcol[l_index]);
2308                                                 /* Color is squared to compensate the sqrt color encoding. */
2309                                                 accum->value[0] += col[0] * col[0];
2310                                                 accum->value[1] += col[1] * col[1];
2311                                                 accum->value[2] += col[2] * col[2];
2312                                         }
2313                                 }
2314                         }
2315                 }
2316         }
2317         BKE_pbvh_vertex_iter_end;
2318 }
2319
2320 static void handle_texture_brush(
2321         SculptThreadedTaskData *data, PBVHVertexIter vd, float size_pressure, float alpha_pressure,
2322         float *r_alpha, uint *r_color)
2323 {
2324         SculptSession *ss = data->ob->sculpt;
2325         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
2326         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
2327
2328         float rgba[4];
2329         float rgba_br[3];
2330
2331         *r_alpha = calc_vp_alpha_col_dl(
2332                 data->vp, &data->vpd->vc, data->vpd->vpimat,
2333                 &data->vpd->vertexcosnos[v_index], ss->cache->mouse, size_pressure, alpha_pressure, rgba);
2334         rgb_uchar_to_float(rgba_br, (const uchar *)&data->vpd->paintcol);
2335         mul_v3_v3(rgba_br, rgba);
2336         rgb_float_to_uchar((uchar *)r_color, rgba_br);
2337 }
2338
2339 static void do_vpaint_brush_draw_task_cb_ex(
2340         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
2341 {
2342         SculptThreadedTaskData *data = userdata;
2343         SculptSession *ss = data->ob->sculpt;
2344         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
2345         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2346
2347         Brush *brush = data->brush;
2348         StrokeCache *cache = ss->cache;
2349         const float brush_strength = cache->bstrength;
2350         uint *lcol = data->lcol;
2351         Scene *scene = CTX_data_scene(data->C);
2352         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2353         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2354         const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
2355         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2356
2357         SculptBrushTest test;
2358         sculpt_brush_test_init(ss, &test);
2359
2360         /* For each vertex */
2361         PBVHVertexIter vd;
2362         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
2363         {
2364                 /* Test to see if the vertex coordinates are within the spherical brush region. */
2365                 if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
2366                         /* Note: Grids are 1:1 with corners (aka loops).
2367                          * For grid based pbvh, take the vert whose loop cooresponds to the current grid.
2368                          * Otherwise, take the current vert. */
2369                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
2370                         const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
2371                         const MVert *mv = &data->me->mvert[v_index];
2372
2373                         /* If the vertex is selected for painting. */
2374                         if (!use_vert_sel || mv->flag & SELECT) {
2375                                 /* Calc the dot prod. between ray norm on surf and current vert
2376                                  * (ie splash prevention factor), and only paint front facing verts. */
2377                                 const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
2378                                 if (view_dot > 0.0f) {
2379                                         const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
2380                                         uint color_final = data->vpd->paintcol;
2381
2382                                         /* If we're painting with a texture, sample the texture color and alpha. */
2383                                         float tex_alpha = 1.0;
2384                                         if (data->vpd->is_texbrush) {
2385                                                 handle_texture_brush(
2386                                                         data, vd, brush_size_pressure, brush_alpha_pressure,
2387                                                         &tex_alpha, &color_final);
2388                                         }
2389                                         /* For each poly owning this vert, paint each loop belonging to this vert. */
2390                                         for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2391                                                 const int p_index = gmap->vert_to_poly[v_index].indices[j];
2392                                                 const int l_index = gmap->vert_to_loop[v_index].indices[j];
2393                                                 BLI_assert(data->me->mloop[l_index].v == v_index);
2394                                                 const MPoly *mp = &data->me->mpoly[p_index];
2395                                                 if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2396                                                         uint color_orig = 0;  /* unused when array is NULL */
2397                                                         if (ss->mode.vpaint.previous_color != NULL) {
2398                                                                 /* Get the previous loop color */
2399                                                                 if (ss->mode.vpaint.previous_color[l_index] == 0) {
2400                                                                         ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
2401                                                                 }
2402                                                                 color_orig = ss->mode.vpaint.previous_color[l_index];
2403                                                         }
2404                                                         float final_alpha =
2405                                                                 255 * brush_fade * brush_strength *
2406                                                                 tex_alpha * brush_alpha_pressure * grid_alpha;
2407
2408                                                         if (data->vp->flag & VP_NORMALS) {
2409                                                                 final_alpha *= view_dot;
2410                                                         }
2411                                                         if (brush->flag & BRUSH_ACCUMULATE) {
2412                                                                 float mask_accum = ss->mode.vpaint.previous_accum[l_index];
2413                                                                 final_alpha = min_ff(final_alpha + mask_accum, 255.0f * brush_strength);
2414                                                                 ss->mode.vpaint.previous_accum[l_index] = final_alpha;
2415                                                         }
2416
2417                                                         /* Mix the new color with the original based on final_alpha. */
2418                                                         lcol[l_index] = vpaint_blend(
2419                                                                 data->vp, lcol[l_index], color_orig, color_final,
2420                                                                 final_alpha, 255 * brush_strength);
2421                                                 }
2422                                         }
2423                                 }
2424                         }
2425                 }
2426         }
2427         BKE_pbvh_vertex_iter_end;
2428 }
2429
2430 static void do_vpaint_brush_blur_task_cb_ex(
2431         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
2432 {
2433         SculptThreadedTaskData *data = userdata;
2434         SculptSession *ss = data->ob->sculpt;
2435         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
2436
2437         Scene *scene = CTX_data_scene(data->C);
2438         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2439         Brush *brush = data->brush;
2440         StrokeCache *cache = ss->cache;
2441         const float brush_strength = cache->bstrength;
2442         uint *lcol = data->lcol;
2443         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2444         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2445         const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
2446         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2447
2448         SculptBrushTest test;
2449         sculpt_brush_test_init(ss, &test);
2450
2451         /* For each vertex */
2452         PBVHVertexIter vd;
2453         BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
2454         {
2455                 /* Test to see if the vertex coordinates are within the spherical brush region. */
2456                 if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
2457                         /* For grid based pbvh, take the vert whose loop cooresponds to the current grid.
2458                          * Otherwise, take the current vert. */
2459                         const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
2460                         const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
2461                         const MVert *mv = &data->me->mvert[v_index];
2462
2463                         const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
2464                         if (view_dot > 0.0f) {
2465                                 const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
2466
2467                                 /* If the vertex is selected for painting. */
2468                                 if (!use_vert_sel || mv->flag & SELECT) {
2469                                         /* Get the average poly color */
2470                                         uint color_final = 0;
2471                                         int total_hit_loops = 0;
2472                                         uint blend[4] = {0};
2473                                         for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2474                                                 int p_index = gmap->vert_to_poly[v_index].indices[j];
2475                                                 const MPoly *mp = &data->me->mpoly[p_index];
2476                                                 if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2477                                                         total_hit_loops += mp->totloop;
2478                                                         for (int k = 0; k < mp->totloop; k++) {
2479                                                                 const uint l_index = mp->loopstart + k;
2480                                                                 const char *col = (const char *)(&lcol[l_index]);
2481                                                                 /* Color is squared to compensate the sqrt color encoding. */
2482                                                                 blend[0] += (uint)col[0] * (uint)col[0];
2483                                                                 blend[1] += (uint)col[1] * (uint)col[1];
2484                                                                 blend[2] += (uint)col[2] * (uint)col[2];
2485                                                                 blend[3] += (uint)col[3] * (uint)col[3];
2486                                                         }
2487                                                 }
2488                                         }
2489                                         if (total_hit_loops != 0) {
2490                                                 /* Use rgb^2 color averaging. */
2491                                                 char *col = (char *)(&color_final);
2492                                                 col[0] = round_fl_to_uchar(sqrtf(divide_round_i(blend[0], total_hit_loops)));
2493                                                 col[1] = round_fl_to_uchar(sqrtf(divide_round_i(blend[1], total_hit_loops)));
2494                                                 col[2] = round_fl_to_uchar(sqrtf(divide_round_i(blend[2], total_hit_loops)));
2495                                                 col[3] = round_fl_to_uchar(sqrtf(divide_round_i(blend[3], total_hit_loops)));
2496
2497                                                 /* For each poly owning this vert, paint each loop belonging to this vert. */
2498                                                 for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2499                                                         const int p_index = gmap->vert_to_poly[v_index].indices[j];
2500                                                         const int l_index = gmap->vert_to_loop[v_index].indices[j];
2501                                                         BLI_assert(data->me->mloop[l_index].v == v_index);
2502                                                         const MPoly *mp = &data->me->mpoly[p_index];
2503                                                         if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2504                                                                 uint color_orig = 0;  /* unused when array is NULL */
2505                                                                 if (ss->mode.vpaint.previous_color != NULL) {
2506                                                                         /* Get the previous loop color */
2507                                                                         if (ss->mode.vpaint.previous_color[l_index] == 0) {
2508                                                                                 ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
2509                                                                         }
2510                                                                         color_orig = ss->mode.vpaint.previous_color[l_index];
2511                                                                 }
2512                                                                 float final_alpha =
2513                                                                         255 * brush_fade * brush_strength *
2514                                                                         brush_alpha_pressure * grid_alpha;
2515
2516                                                                 if (data->vp->flag & VP_NORMALS) {
2517                                                                         final_alpha *= view_dot;
2518                                                                 }
2519                                                                 /* Mix the new color with the original
2520                                                                  * based on the brush strength and the curve. */
2521                                                                 lcol[l_index] = vpaint_blend(
2522                                                                         data->vp, lcol[l_index], color_orig, *((uint *)col),
2523                                                                         final_alpha, 255 * brush_strength);
2524                                                         }
2525                                                 }
2526                                         }
2527                                 }
2528                         }
2529                 }
2530         }
2531         BKE_pbvh_vertex_iter_end;
2532 }
2533
2534 static void do_vpaint_brush_smear_task_cb_ex(
2535         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
2536 {
2537         SculptThreadedTaskData *data = userdata;
2538         SculptSession *ss = data->ob->sculpt;
2539         CCGDerivedMesh *ccgdm = BKE_pbvh_get_ccgdm(ss->pbvh);
2540
2541         Scene *scene = CTX_data_scene(data->C);
2542         const struct SculptVertexPaintGeomMap *gmap = &ss->mode.vpaint.gmap;
2543         Brush *brush = data->brush;
2544         StrokeCache *cache = ss->cache;
2545         const float brush_strength = cache->bstrength;
2546         uint *lcol = data->lcol;
2547         float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
2548         get_brush_alpha_data(scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
2549         float brush_dir[3];
2550         const bool use_vert_sel = (data->me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
2551         const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2552
2553         sub_v3_v3v3(brush_dir, cache->location, cache->last_location);
2554         project_plane_v3_v3v3(brush_dir, brush_dir, cache->view_normal);
2555
2556         if (normalize_v3(brush_dir) != 0.0f) {
2557
2558                 SculptBrushTest test;
2559                 sculpt_brush_test_init(ss, &test);
2560
2561                 /* For each vertex */
2562                 PBVHVertexIter vd;
2563                 BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
2564                 {
2565                         /* Test to see if the vertex coordinates are within the spherical brush region. */
2566                         if (sculpt_brush_test_sphere_sq(&test, vd.co)) {
2567                                 /* For grid based pbvh, take the vert whose loop cooresponds to the current grid.
2568                                  * Otherwise, take the current vert. */
2569                                 const int v_index = ccgdm ? data->me->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i];
2570                                 const float grid_alpha = ccgdm ? 1.0f / vd.gridsize : 1.0f;
2571                                 const MVert *mv_curr = &data->me->mvert[v_index];
2572
2573                                 /* if the vertex is selected for painting. */
2574                                 if (!use_vert_sel || mv_curr->flag & SELECT) {
2575                                         /* Calc the dot prod. between ray norm on surf and current vert
2576                                          * (ie splash prevention factor), and only paint front facing verts. */
2577                                         const float view_dot = (vd.no) ? dot_vf3vs3(cache->sculpt_normal_symm, vd.no) : 1.0;
2578                                         if (view_dot > 0.0f) {
2579                                                 const float brush_fade = BKE_brush_curve_strength(brush, sqrtf(test.dist), cache->radius);
2580
2581                                                 bool do_color = false;
2582                                                 /* Minimum dot product between brush direction and current
2583                                                  * to neighbor direction is 0.0, meaning orthogonal. */
2584                                                 float stroke_dot_max = 0.0f;
2585
2586                                                 /* Get the color of the loop in the opposite direction of the brush movement */
2587                                                 uint color_final = 0;
2588                                                 for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2589                                                         const int p_index = gmap->vert_to_poly[v_index].indices[j];
2590                                                         const int l_index = gmap->vert_to_loop[v_index].indices[j];
2591                                                         BLI_assert(data->me->mloop[l_index].v == v_index);
2592                                                         const MPoly *mp = &data->me->mpoly[p_index];
2593                                                         if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2594                                                                 const MLoop *ml_other = &data->me->mloop[mp->loopstart];
2595                                                                 for (int k = 0; k < mp->totloop; k++, ml_other++) {
2596                                                                         const uint v_other_index = ml_other->v;
2597                                                                         if (v_other_index != v_index) {
2598                                                                                 const MVert *mv_other = &data->me->mvert[v_other_index];
2599
2600                                                                                 /* Get the direction from the selected vert to the neighbor. */
2601                                                                                 float other_dir[3];
2602                                                                                 sub_v3_v3v3(other_dir, mv_curr->co, mv_other->co);
2603                                                                                 project_plane_v3_v3v3(other_dir, other_dir, cache->view_normal);
2604
2605                                                                                 normalize_v3(other_dir);
2606
2607                                                                                 const float stroke_dot = dot_v3v3(other_dir, brush_dir);
2608
2609                                                                                 if (stroke_dot > stroke_dot_max) {
2610                                                                                         stroke_dot_max = stroke_dot;
2611                                                                                         color_final = lcol[mp->loopstart + k];
2612                                                                                         do_color = true;
2613                                                                                 }
2614                                                                         }
2615                                                                 }
2616                                                         }
2617                                                 }
2618
2619                                                 if (do_color) {
2620                                                         /* For each poly owning this vert, paint each loop belonging to this vert. */
2621                                                         for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) {
2622                                                                 const int p_index = gmap->vert_to_poly[v_index].indices[j];
2623                                                                 const int l_index = gmap->vert_to_loop[v_index].indices[j];
2624                                                                 BLI_assert(data->me->mloop[l_index].v == v_index);
2625                                                                 const MPoly *mp = &data->me->mpoly[p_index];
2626                                                                 if (!use_face_sel || mp->flag & ME_FACE_SEL) {
2627                                                                         /* Get the previous loop color */
2628                                                                         uint color_orig = 0;  /* unused when array is NULL */
2629                                                                         if (ss->mode.vpaint.previous_color != NULL) {
2630                                                                                 /* Get the previous loop color */
2631                                                                                 if (ss->mode.vpaint.previous_color[l_index] == 0) {
2632                                                                                         ss->mode.vpaint.previous_color[l_index] = lcol[l_index];
2633                                                                                 }
2634                                                                                 color_orig = ss->mode.vpaint.previous_color[l_index];
2635                                                                         }
2636                                                                         float final_alpha =
2637                                                                                 255 * brush_fade * brush_strength *
2638                                                                                 brush_alpha_pressure * grid_alpha;
2639
2640                                                                         if (data->vp->flag & VP_NORMALS) {
2641                                                                                 final_alpha *= view_dot;
2642                                                                         }
2643                                                                         /* Mix the new color with the original
2644                                                                          * based on the brush strength and the curve. */
2645                                                                         lcol[l_index] = vpaint_blend(
2646                                                                                 data->vp, lcol[l_index], color_orig, color_final,
2647                                                                                 final_alpha, 255 * brush_strength);
2648                                                                 }
2649                                                         }
2650                                                 }
2651                                         }
2652                                 }
2653                         }
2654                 }
2655                 BKE_pbvh_vertex_iter_end;
2656         }
2657 }
2658
2659 static void calculate_average_color(SculptThreadedTaskData *data, PBVHNode **UNUSED(nodes), int totnode)
2660 {
2661         struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__);
2662         data->custom_data = accum;
2663
2664         BLI_task_parallel_range_ex(
2665                 0, totnode, data, NULL, 0, do_vpaint_brush_calc_average_color_cb_ex,
2666                 true, false);
2667
2668         uint accum_len = 0;
2669         uint accum_value[3] = {0};
2670         uchar blend[4] = {0};
2671         for (int i = 0; i < totnode; i++) {
2672                 accum_len += accum[i].len;
2673                 accum_value[0] += accum[i].value[0];
2674                 accum_value[1] += accum[i].value[1];
2675                 accum_value[2] += accum[i].value[2];
2676         }
2677         if (accum_len != 0) {
2678                 blend[0] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[0], accum_len)));
2679                 blend[1] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[1], accum_len)));
2680                 blend[2] = round_fl_to_uchar(sqrtf(divide_round_i(accum_value[2], accum_len)));
2681                 blend[3] = 255;
2682                 data->vpd->paintcol = *((uint *)blend);
2683         }
2684
2685         MEM_SAFE_FREE(data->custom_data);  /* 'accum' */
2686 }
2687
2688 static void vpaint_paint_leaves(
2689         bContext *C, Sculpt *sd, VPaint *vp, struct VPaintData *vpd,
2690         Object *ob, Mesh *me, PBVHNode **nodes, int totnode)
2691 {
2692         Brush *brush = ob->sculpt->cache->brush;
2693
2694         SculptThreadedTaskData data = {
2695                 .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
2696                 .lcol = (uint *)me->mloopcol, .me = me, .C = C,
2697         };
2698         switch (brush->vertexpaint_tool) {
2699                 case PAINT_BLEND_AVERAGE:
2700                         calculate_average_color(&data, nodes, totnode);
2701                         BLI_task_parallel_range_ex(
2702                             0, totnode, &data, NULL, 0,
2703                             do_vpaint_brush_draw_task_cb_ex, true, false);
2704                         break;
2705                 case PAINT_BLEND_BLUR:
2706                         BLI_task_parallel_range_ex(
2707                             0, totnode, &data, NULL, 0,
2708                             do_vpaint_brush_blur_task_cb_ex, true, false);
2709                         break;
2710                 case PAINT_BLEND_SMEAR:
2711                         BLI_task_parallel_range_ex(
2712                             0, totnode, &data, NULL, 0,
2713                             do_vpaint_brush_smear_task_cb_ex, true, false);
2714                         break;
2715                 default:
2716                         BLI_task_parallel_range_ex(
2717                             0, totnode, &data, NULL, 0,
2718                             do_vpaint_brush_draw_task_cb_ex, true, false);
2719                         break;
2720         }
2721 }
2722
2723 static void vpaint_do_paint(
2724         bContext *C, Sculpt *sd, VPaint *vd, struct VPaintData *vpd,
2725         Object *ob, Mesh *me, Brush *brush, const char symm, const int axis, const int i, const float angle)
2726 {
2727         SculptSession *ss = ob->sculpt;
2728         ss->cache->radial_symmetry_pass = i;
2729         sculpt_cache_calc_brushdata_symm(ss->cache, symm, axis, angle);
2730         SculptSearchSphereData data;
2731         PBVHNode **nodes = NULL;
2732         int totnode;
2733
2734         /* Build a list of all nodes that are potentially within the brush's area of influence */
2735         data.ss = ss;
2736         data.sd = sd;
2737         data.radius_squared = ss->cache->radius_squared;
2738         data.original = true;
2739         BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
2740
2741         sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, ss->cache->sculpt_normal_symm);
2742
2743         /* Paint those leaves. */
2744         vpaint_paint_leaves(C, sd, vd, vpd, ob, me, nodes, totnode);
2745
2746         if (nodes) {
2747                 MEM_freeN(nodes);
2748         }
2749 }
2750
2751 static void vpaint_do_radial_symmetry(
2752         bContext *C, Sculpt *sd, VPaint *vd, struct VPaintData *vpd, Object *ob, Mesh *me,
2753         Brush *brush, const char symm, const int axis)
2754 {
2755         for (int i = 1; i < vd->radial_symm[axis - 'X']; i++) {
2756                 const float angle = (2.0 * M_PI) * i / vd->radial_symm[axis - 'X'];
2757                 vpaint_do_paint(C, sd, vd, vpd, ob, me, brush, symm, axis, i, angle);
2758         }
2759 }
2760
2761 /* near duplicate of: sculpt.c's, 'do_symmetrical_brush_actions' and 'wpaint_do_symmetrical_brush_actions'. */
2762 static void vpaint_do_symmetrical_brush_actions(
2763         bContext *C, Sculpt *sd, VPaint *vd, struct VPaintData *vpd, Object *ob)
2764 {
2765         Brush *brush = BKE_paint_brush(&vd->paint);
2766         Mesh *me = ob->data;
2767         SculptSession *ss = ob->sculpt;
2768         StrokeCache *cache = ss->cache;
2769         const char symm = vd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
2770         int i = 0;
2771
2772         /* initial stroke */
2773         vpaint_do_paint(C, sd, vd, vpd, ob, me, brush, i, 'X', 0, 0);
2774         vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'X');
2775         vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'Y');
2776         vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'Z');
2777
2778         cache->symmetry = symm;
2779
2780         /* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
2781         for (i = 1; i <= symm; i++) {
2782                 if (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) {
2783                         cache->mirror_symmetry_pass = i;
2784                         cache->radial_symmetry_pass = 0;
2785                         sculpt_cache_calc_brushdata_symm(cache, i, 0, 0);
2786
2787                         if (i & (1 << 0)) {
2788                                 vpaint_do_paint(C, sd, vd, vpd, ob, me, brush, i, 'X', 0, 0);
2789                                 vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'X');
2790                         }
2791                         if (i & (1 << 1)) {
2792                                 vpaint_do_paint(C, sd, vd, vpd, ob, me, brush, i, 'Y', 0, 0);
2793                                 vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'Y');
2794                         }
2795                         if (i & (1 << 2)) {
2796                                 vpaint_do_paint(C, sd, vd, vpd, ob, me, brush, i, 'Z', 0, 0);
2797                                 vpaint_do_radial_symmetry(C, sd, vd, vpd, ob, me, brush, i, 'Z');
2798                         }
2799                 }
2800         }
2801
2802         copy_v3_v3(cache->true_last_location, cache->true_location);
2803         cache->is_last_valid = true;
2804 }
2805
2806 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2807 {
2808         Scene *scene = CTX_data_scene(C);
2809         ToolSettings *ts = CTX_data_tool_settings(C);
2810         struct VPaintData *vpd = paint_stroke_mode_data(stroke);
2811         VPaint *vp = ts->vpaint;
2812         ViewContext *vc = &vpd->vc;
2813         Object *ob = vc->obact;
2814         Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
2815
2816         vwpaint_update_cache_variants(C, vp, ob, itemptr);
2817
2818         float mat[4][4];