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