Fix part of #34640: vertex color blur brush would average face corner colors
[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
33 #include <math.h>
34 #include <string.h>
35
36 #ifdef WIN32
37 #include <io.h>
38 #else
39 #include <unistd.h>
40 #endif   
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_math.h"
46 #include "BLI_math_color.h"
47 #include "BLI_memarena.h"
48 #include "BLI_utildefines.h"
49 #include "BLI_ghash.h"
50
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53
54 #include "DNA_armature_types.h"
55 #include "DNA_mesh_types.h"
56 #include "DNA_particle_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_brush_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_meshdata_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
65
66 #include "BKE_DerivedMesh.h"
67 #include "BKE_armature.h"
68 #include "BKE_action.h"
69 #include "BKE_brush.h"
70 #include "BKE_context.h"
71 #include "BKE_depsgraph.h"
72 #include "BKE_deform.h"
73 #include "BKE_mesh.h"
74 #include "BKE_modifier.h"
75 #include "BKE_object.h"
76 #include "BKE_object_deform.h"
77 #include "BKE_paint.h"
78 #include "BKE_report.h"
79
80 #include "WM_api.h"
81 #include "WM_types.h"
82
83 #include "GPU_buffers.h"
84
85 #include "ED_armature.h"
86 #include "ED_mesh.h"
87 #include "ED_screen.h"
88 #include "ED_view3d.h"
89
90 #include "paint_intern.h"
91
92 /* check if we can do partial updates and have them draw realtime
93  * (without rebuilding the 'derivedFinal') */
94 static int vertex_paint_use_fast_update_check(Object *ob)
95 {
96         DerivedMesh *dm = ob->derivedFinal;
97
98         if (dm) {
99                 Mesh *me = BKE_mesh_from_object(ob);
100                 if (me && me->mcol) {
101                         return (me->mcol == CustomData_get_layer(&dm->faceData, CD_MCOL));
102                 }
103         }
104
105         return FALSE;
106 }
107
108 /* if the polygons from the mesh and the 'derivedFinal' match
109  * we can assume that no modifiers are applied and that its worth adding tessellated faces
110  * so 'vertex_paint_use_fast_update_check()' returns TRUE */
111 static int vertex_paint_use_tessface_check(Object *ob, Mesh *me)
112 {
113         DerivedMesh *dm = ob->derivedFinal;
114
115         if (me && dm) {
116                 return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY));
117         }
118
119         return FALSE;
120 }
121
122 static void update_tessface_data(Object *ob, Mesh *me)
123 {
124         if (vertex_paint_use_tessface_check(ob, me)) {
125                 /* assume if these exist, that they are up to date & valid */
126                 if (!me->mcol || !me->mface) {
127                         /* should always be true */
128                         /* XXX Why this clearing? tessface_calc will reset it anyway! */
129 #if 0
130                         if (me->mcol) {
131                                 memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);
132                         }
133 #endif
134
135                         /* create tessfaces because they will be used for drawing & fast updates */
136                         BKE_mesh_tessface_calc(me); /* does own call to update pointers */
137                 }
138         }
139         else {
140                 if (me->totface) {
141                         /* this wont be used, theres no need to keep it */
142                         BKE_mesh_tessface_clear(me);
143                 }
144         }
145
146 }
147 /* polling - retrieve whether cursor should be set or operator should be done */
148
149 /* Returns true if vertex paint mode is active */
150 int vertex_paint_mode_poll(bContext *C)
151 {
152         Object *ob = CTX_data_active_object(C);
153
154         return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
155 }
156
157 int vertex_paint_poll(bContext *C)
158 {
159         if (vertex_paint_mode_poll(C) && 
160             BKE_paint_brush(&CTX_data_tool_settings(C)->vpaint->paint))
161         {
162                 ScrArea *sa = CTX_wm_area(C);
163                 if (sa && sa->spacetype == SPACE_VIEW3D) {
164                         ARegion *ar = CTX_wm_region(C);
165                         if (ar->regiontype == RGN_TYPE_WINDOW)
166                                 return 1;
167                 }
168         }
169         return 0;
170 }
171
172 int weight_paint_mode_poll(bContext *C)
173 {
174         Object *ob = CTX_data_active_object(C);
175
176         return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
177 }
178
179 int weight_paint_poll(bContext *C)
180 {
181         Object *ob = CTX_data_active_object(C);
182         ScrArea *sa;
183
184         if ((ob != NULL) &&
185             (ob->mode & OB_MODE_WEIGHT_PAINT) &&
186             (BKE_paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
187             (sa = CTX_wm_area(C)) &&
188             (sa->spacetype == SPACE_VIEW3D))
189         {
190                 ARegion *ar = CTX_wm_region(C);
191                 if (ar->regiontype == RGN_TYPE_WINDOW) {
192                         return 1;
193                 }
194         }
195         return 0;
196 }
197
198 static VPaint *new_vpaint(int wpaint)
199 {
200         VPaint *vp = MEM_callocN(sizeof(VPaint), "VPaint");
201         
202         vp->flag = VP_AREA + VP_SPRAY;
203         
204         if (wpaint)
205                 vp->flag = VP_AREA;
206
207         return vp;
208 }
209
210 static int *get_indexarray(Mesh *me)
211 {
212         return MEM_mallocN(sizeof(int) * (me->totpoly + 1), "vertexpaint");
213 }
214
215 unsigned int vpaint_get_current_col(VPaint *vp)
216 {
217         Brush *brush = BKE_paint_brush(&vp->paint);
218         unsigned char col[4];
219         rgb_float_to_uchar(col, brush->rgb);
220         col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
221         return *(unsigned int *)col;
222 }
223
224 static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag)
225 {
226         /* if no mcol: do not do */
227         /* if tface: only the involved faces, otherwise all */
228         const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
229         MFace *mface;
230         int a;
231         short *scolmain, *scol;
232         char *mcol;
233         bool *mftag;
234         
235         if (me->mcol == NULL || me->totvert == 0 || me->totface == 0) return;
236         
237         scolmain = MEM_callocN(4 * sizeof(short) * me->totvert, "colmain");
238         
239         mface = me->mface;
240         mcol = (char *)me->mcol;
241         for (a = me->totface; a > 0; a--, mface++, mcol += 16) {
242                 if ((use_face_sel == FALSE) || (mface->flag & ME_FACE_SEL)) {
243                         scol = scolmain + 4 * mface->v1;
244                         scol[0]++; scol[1] += mcol[1]; scol[2] += mcol[2]; scol[3] += mcol[3];
245                         scol = scolmain + 4 * mface->v2;
246                         scol[0]++; scol[1] += mcol[5]; scol[2] += mcol[6]; scol[3] += mcol[7];
247                         scol = scolmain + 4 * mface->v3;
248                         scol[0]++; scol[1] += mcol[9]; scol[2] += mcol[10]; scol[3] += mcol[11];
249                         if (mface->v4) {
250                                 scol = scolmain + 4 * mface->v4;
251                                 scol[0]++; scol[1] += mcol[13]; scol[2] += mcol[14]; scol[3] += mcol[15];
252                         }
253                 }
254         }
255         
256         a = me->totvert;
257         scol = scolmain;
258         while (a--) {
259                 if (scol[0] > 1) {
260                         scol[1] = divide_round_i(scol[1], scol[0]);
261                         scol[2] = divide_round_i(scol[2], scol[0]);
262                         scol[3] = divide_round_i(scol[3], scol[0]);
263                 }
264                 scol += 4;
265         }
266
267         mface = me->mface;
268         mcol = (char *)me->mcol;
269         mftag = mfacetag;
270         for (a = me->totface; a > 0; a--, mface++, mcol += 16, mftag += 4) {
271                 if ((use_face_sel == FALSE) || (mface->flag & ME_FACE_SEL)) {
272                         if (mftag[0]) {
273                                 scol = scolmain + 4 * mface->v1;
274                                 mcol[1] = scol[1]; mcol[2] = scol[2]; mcol[3] = scol[3];
275                         }
276
277                         if (mftag[1]) {
278                                 scol = scolmain + 4 * mface->v2;
279                                 mcol[5] = scol[1]; mcol[6] = scol[2]; mcol[7] = scol[3];
280                         }
281
282                         if (mftag[2]) {
283                                 scol = scolmain + 4 * mface->v3;
284                                 mcol[9] = scol[1]; mcol[10] = scol[2]; mcol[11] = scol[3];
285                         }
286
287                         if (mface->v4 && mftag[3]) {
288                                 scol = scolmain + 4 * mface->v4;
289                                 mcol[13] = scol[1]; mcol[14] = scol[2]; mcol[15] = scol[3];
290                         }
291                 }
292         }
293
294         MEM_freeN(scolmain);
295 }
296
297 static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, int do_tessface)
298 {
299         const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
300         MPoly *mp;
301         int (*scol)[4];
302         int i, j, has_shared = 0;
303
304         /* if no mloopcol: do not do */
305         /* if mtexpoly: only the involved faces, otherwise all */
306
307         if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) return;
308
309         scol = MEM_callocN(sizeof(int) * me->totvert * 5, "scol");
310
311         for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
312                 if ((use_face_sel == FALSE) || (mp->flag & ME_FACE_SEL)) {
313                         MLoop *ml = me->mloop + mp->loopstart;
314                         MLoopCol *lcol = me->mloopcol + mp->loopstart;
315                         for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
316                                 scol[ml->v][0] += lcol->r;
317                                 scol[ml->v][1] += lcol->g;
318                                 scol[ml->v][2] += lcol->b;
319                                 scol[ml->v][3] += 1;
320                                 has_shared = 1;
321                         }
322                 }
323         }
324
325         if (has_shared) {
326                 for (i = 0; i < me->totvert; i++) {
327                         if (scol[i][3] != 0) {
328                                 scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
329                                 scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
330                                 scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
331                         }
332                 }
333
334                 for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
335                         if ((use_face_sel == FALSE) || (mp->flag & ME_FACE_SEL)) {
336                                 MLoop *ml = me->mloop + mp->loopstart;
337                                 MLoopCol *lcol = me->mloopcol + mp->loopstart;
338                                 for (j = 0; j < mp->totloop; j++, ml++, lcol++) {
339                                         if (mlooptag[mp->loopstart + j]) {
340                                                 lcol->r = scol[ml->v][0];
341                                                 lcol->g = scol[ml->v][1];
342                                                 lcol->b = scol[ml->v][2];
343                                         }
344                                 }
345                         }
346                 }
347         }
348
349         MEM_freeN(scol);
350
351         if (has_shared && do_tessface) {
352                 do_shared_vertex_tesscol(me, mfacetag);
353         }
354 }
355
356 static void make_vertexcol(Object *ob)  /* single ob */
357 {
358         Mesh *me;
359         if (!ob || ob->id.lib) return;
360         me = BKE_mesh_from_object(ob);
361         if (me == NULL) return;
362         if (me->edit_btmesh) return;
363
364         /* copies from shadedisplist to mcol */
365         if (!me->mloopcol && me->totloop) {
366                 if (!me->mcol) {
367                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
368                 }
369                 if (!me->mloopcol) {
370                         CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
371                 }
372                 BKE_mesh_update_customdata_pointers(me, true);
373         }
374
375         update_tessface_data(ob, me);
376
377         //if (shade)
378         //      shadeMeshMCol(scene, ob, me);
379         //else
380         
381         DAG_id_tag_update(&me->id, 0);
382         
383 }
384
385 /* mirror_vgroup is set to -1 when invalid */
386 static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
387 {
388         bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
389
390         if (defgroup) {
391                 int mirrdef;
392                 char name[MAXBONENAME];
393
394                 flip_side_name(name, defgroup->name, FALSE);
395                 mirrdef = defgroup_name_index(ob, name);
396                 if (mirrdef == -1) {
397                         int olddef = ob->actdef;  /* tsk, ED_vgroup_add sets the active defgroup */
398                         if (ED_vgroup_add_name(ob, name)) {
399                                 mirrdef = BLI_countlist(&ob->defbase) - 1;
400                         }
401                         ob->actdef = olddef;
402                 }
403
404                 /* curdef should never be NULL unless this is
405                  * a  lamp and ED_vgroup_add_name fails */
406                 return mirrdef;
407         }
408
409         return -1;
410 }
411
412 static void free_vpaint_prev(VPaint *vp)
413 {
414         if (vp->vpaint_prev) {
415                 MEM_freeN(vp->vpaint_prev);
416                 vp->vpaint_prev = NULL;
417                 vp->tot = 0;
418         }
419 }
420
421 static void free_wpaint_prev(VPaint *vp)
422 {
423         if (vp->wpaint_prev) {
424                 BKE_defvert_array_free(vp->wpaint_prev, vp->tot);
425                 vp->wpaint_prev = NULL;
426                 vp->tot = 0;
427         }
428 }
429
430 static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
431 {
432         free_vpaint_prev(vp);
433
434         vp->tot = tot;
435         
436         if (lcol == NULL || tot == 0) return;
437         
438         vp->vpaint_prev = MEM_mallocN(sizeof(int) * tot, "vpaint_prev");
439         memcpy(vp->vpaint_prev, lcol, sizeof(int) * tot);
440         
441 }
442
443 static void copy_wpaint_prev(VPaint *wp, MDeformVert *dverts, int dcount)
444 {
445         free_wpaint_prev(wp);
446         
447         if (dverts && dcount) {
448                 
449                 wp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
450                 wp->tot = dcount;
451                 BKE_defvert_array_copy(wp->wpaint_prev, dverts, dcount);
452         }
453 }
454
455 void vpaint_fill(Object *ob, unsigned int paintcol)
456 {
457         Mesh *me;
458         MPoly *mp;
459         MLoopCol *lcol;
460         int i, j, selected;
461
462         me = BKE_mesh_from_object(ob);
463         if (me == NULL || me->totpoly == 0) return;
464
465         if (!me->mloopcol) make_vertexcol(ob);
466         if (!me->mloopcol) return;  /* possible we can't make mcol's */
467
468
469         selected = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
470
471         mp = me->mpoly;
472         for (i = 0; i < me->totpoly; i++, mp++) {
473                 if (!(!selected || mp->flag & ME_FACE_SEL))
474                         continue;
475
476                 lcol = me->mloopcol + mp->loopstart;
477                 for (j = 0; j < mp->totloop; j++, lcol++) {
478                         *(int *)lcol = paintcol;
479                 }
480         }
481         
482         /* remove stale me->mcol, will be added later */
483         BKE_mesh_tessface_clear(me);
484
485         DAG_id_tag_update(&me->id, 0);
486 }
487
488
489 /* fills in the selected faces with the current weight and vertex group */
490 void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
491 {
492         Mesh *me = ob->data;
493         MPoly *mp;
494         MDeformWeight *dw, *dw_prev;
495         int vgroup_active, vgroup_mirror = -1;
496         unsigned int index;
497
498         /* mutually exclusive, could be made into a */
499         const short paint_selmode = ME_EDIT_PAINT_SEL_MODE(me);
500
501         if (me->totpoly == 0 || me->dvert == NULL || !me->mpoly) return;
502         
503         vgroup_active = ob->actdef - 1;
504
505         /* if mirror painting, find the other group */
506         if (me->editflag & ME_EDIT_MIRROR_X) {
507                 vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, vgroup_active);
508         }
509         
510         copy_wpaint_prev(wp, me->dvert, me->totvert);
511         
512         for (index = 0, mp = me->mpoly; index < me->totpoly; index++, mp++) {
513                 unsigned int fidx = mp->totloop - 1;
514
515                 if ((paint_selmode == SCE_SELECT_FACE) && !(mp->flag & ME_FACE_SEL)) {
516                         continue;
517                 }
518
519                 do {
520                         unsigned int vidx = me->mloop[mp->loopstart + fidx].v;
521
522                         if (!me->dvert[vidx].flag) {
523                                 if ((paint_selmode == SCE_SELECT_VERTEX) && !(me->mvert[vidx].flag & SELECT)) {
524                                         continue;
525                                 }
526
527                                 dw = defvert_verify_index(&me->dvert[vidx], vgroup_active);
528                                 if (dw) {
529                                         dw_prev = defvert_verify_index(wp->wpaint_prev + vidx, vgroup_active);
530                                         dw_prev->weight = dw->weight; /* set the undo weight */
531                                         dw->weight = paintweight;
532
533                                         if (me->editflag & ME_EDIT_MIRROR_X) {  /* x mirror painting */
534                                                 int j = mesh_get_x_mirror_vert(ob, vidx);
535                                                 if (j >= 0) {
536                                                         /* copy, not paint again */
537                                                         if (vgroup_mirror != -1) {
538                                                                 dw = defvert_verify_index(me->dvert + j, vgroup_mirror);
539                                                                 dw_prev = defvert_verify_index(wp->wpaint_prev + j, vgroup_mirror);
540                                                         }
541                                                         else {
542                                                                 dw = defvert_verify_index(me->dvert + j, vgroup_active);
543                                                                 dw_prev = defvert_verify_index(wp->wpaint_prev + j, vgroup_active);
544                                                         }
545                                                         dw_prev->weight = dw->weight; /* set the undo weight */
546                                                         dw->weight = paintweight;
547                                                 }
548                                         }
549                                 }
550                                 me->dvert[vidx].flag = 1;
551                         }
552
553                 } while (fidx--);
554         }
555
556         {
557                 MDeformVert *dv = me->dvert;
558                 for (index = me->totvert; index != 0; index--, dv++) {
559                         dv->flag = 0;
560                 }
561         }
562
563         copy_wpaint_prev(wp, NULL, 0);
564
565         DAG_id_tag_update(&me->id, 0);
566 }
567
568 /* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator */
569 #if 0
570 void vpaint_dogamma(Scene *scene)
571 {
572         VPaint *vp = scene->toolsettings->vpaint;
573         Mesh *me;
574         Object *ob;
575         float igam, fac;
576         int a, temp;
577         unsigned char *cp, gamtab[256];
578
579         ob = OBACT;
580         me = BKE_mesh_from_object(ob);
581
582         if (!(ob->mode & OB_MODE_VERTEX_PAINT)) return;
583         if (me == 0 || me->mcol == 0 || me->totface == 0) return;
584
585         igam = 1.0 / vp->gamma;
586         for (a = 0; a < 256; a++) {
587
588                 fac = ((float)a) / 255.0;
589                 fac = vp->mul * pow(fac, igam);
590
591                 temp = 255.9 * fac;
592
593                 if (temp <= 0) gamtab[a] = 0;
594                 else if (temp >= 255) gamtab[a] = 255;
595                 else gamtab[a] = temp;
596         }
597
598         a = 4 * me->totface;
599         cp = (unsigned char *)me->mcol;
600         while (a--) {
601
602                 cp[1] = gamtab[cp[1]];
603                 cp[2] = gamtab[cp[2]];
604                 cp[3] = gamtab[cp[3]];
605
606                 cp += 4;
607         }
608 }
609 #endif
610
611 BLI_INLINE unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
612 {
613         unsigned char *cp1, *cp2, *cp;
614         int mfac;
615         unsigned int col = 0;
616
617         if (fac == 0) {
618                 return col1;
619         }
620
621         if (fac >= 255) {
622                 return col2;
623         }
624
625         mfac = 255 - fac;
626
627         cp1 = (unsigned char *)&col1;
628         cp2 = (unsigned char *)&col2;
629         cp  = (unsigned char *)&col;
630
631         cp[0] = divide_round_i((mfac * cp1[0] + fac * cp2[0]), 255);
632         cp[1] = divide_round_i((mfac * cp1[1] + fac * cp2[1]), 255);
633         cp[2] = divide_round_i((mfac * cp1[2] + fac * cp2[2]), 255);
634         cp[3] = 255;
635
636         return col;
637 }
638
639 BLI_INLINE unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
640 {
641         unsigned char *cp1, *cp2, *cp;
642         int temp;
643         unsigned int col = 0;
644
645         if (fac == 0) {
646                 return col1;
647         }
648
649         cp1 = (unsigned char *)&col1;
650         cp2 = (unsigned char *)&col2;
651         cp  = (unsigned char *)&col;
652
653         temp = cp1[0] + divide_round_i((fac * cp2[0]), 255);
654         cp[0] = (temp > 254) ? 255 : temp;
655         temp = cp1[1] + divide_round_i((fac * cp2[1]), 255);
656         cp[1] = (temp > 254) ? 255 : temp;
657         temp = cp1[2] + divide_round_i((fac * cp2[2]), 255);
658         cp[2] = (temp > 254) ? 255 : temp;
659         cp[3] = 255;
660         
661         return col;
662 }
663
664 BLI_INLINE unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
665 {
666         unsigned char *cp1, *cp2, *cp;
667         int temp;
668         unsigned int col = 0;
669
670         if (fac == 0) {
671                 return col1;
672         }
673
674         cp1 = (unsigned char *)&col1;
675         cp2 = (unsigned char *)&col2;
676         cp  = (unsigned char *)&col;
677
678         temp = cp1[0] - divide_round_i((fac * cp2[0]), 255);
679         cp[0] = (temp < 0) ? 0 : temp;
680         temp = cp1[1] - divide_round_i((fac * cp2[1]), 255);
681         cp[1] = (temp < 0) ? 0 : temp;
682         temp = cp1[2] - divide_round_i((fac * cp2[2]), 255);
683         cp[2] = (temp < 0) ? 0 : temp;
684         cp[3] = 255;
685
686         return col;
687 }
688
689 BLI_INLINE unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
690 {
691         unsigned char *cp1, *cp2, *cp;
692         int mfac;
693         unsigned int col = 0;
694
695         if (fac == 0) {
696                 return col1;
697         }
698
699         mfac = 255 - fac;
700
701         cp1 = (unsigned char *)&col1;
702         cp2 = (unsigned char *)&col2;
703         cp  = (unsigned char *)&col;
704
705         /* first mul, then blend the fac */
706         cp[0] = divide_round_i(mfac * cp1[0] * 255 + fac * cp2[0] * cp1[0], 255*255);
707         cp[1] = divide_round_i(mfac * cp1[1] * 255 + fac * cp2[1] * cp1[1], 255*255);
708         cp[2] = divide_round_i(mfac * cp1[2] * 255 + fac * cp2[2] * cp1[2], 255*255);
709         cp[3] = 255;
710
711         return col;
712 }
713
714 BLI_INLINE unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
715 {
716         unsigned char *cp1, *cp2, *cp;
717         int mfac;
718         unsigned int col = 0;
719
720         if (fac == 0) {
721                 return col1;
722         }
723         else if (fac >= 255) {
724                 return col2;
725         }
726
727         mfac = 255 - fac;
728
729         cp1 = (unsigned char *)&col1;
730         cp2 = (unsigned char *)&col2;
731         cp  = (unsigned char *)&col;
732
733         /* See if are lighter, if so mix, else don't do anything.
734          * if the paint col is darker then the original, then ignore */
735         if (rgb_to_grayscale_byte(cp1) > rgb_to_grayscale_byte(cp2)) {
736                 return col1;
737         }
738
739         cp[0] = divide_round_i(mfac * cp1[0] + fac * cp2[0], 255);
740         cp[1] = divide_round_i(mfac * cp1[1] + fac * cp2[1], 255);
741         cp[2] = divide_round_i(mfac * cp1[2] + fac * cp2[2], 255);
742         cp[3] = 255;
743
744         return col;
745 }
746
747 BLI_INLINE unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
748 {
749         unsigned char *cp1, *cp2, *cp;
750         int mfac;
751         unsigned int col = 0;
752
753         if (fac == 0) {
754                 return col1;
755         }
756         else if (fac >= 255) {
757                 return col2;
758         }
759
760         mfac = 255 - fac;
761
762         cp1 = (unsigned char *)&col1;
763         cp2 = (unsigned char *)&col2;
764         cp  = (unsigned char *)&col;
765
766         /* See if were darker, if so mix, else don't do anything.
767          * if the paint col is brighter then the original, then ignore */
768         if (rgb_to_grayscale_byte(cp1) < rgb_to_grayscale_byte(cp2)) {
769                 return col1;
770         }
771
772         cp[0] = divide_round_i((mfac * cp1[0] + fac * cp2[0]), 255);
773         cp[1] = divide_round_i((mfac * cp1[1] + fac * cp2[1]), 255);
774         cp[2] = divide_round_i((mfac * cp1[2] + fac * cp2[2]), 255);
775         cp[3] = 255;
776         return col;
777 }
778
779 /* wpaint has 'wpaint_blend_tool' */
780 static unsigned int vpaint_blend_tool(const int tool, const unsigned int col,
781                                       const unsigned int paintcol, const int alpha_i)
782 {
783         switch (tool) {
784                 case PAINT_BLEND_MIX:
785                 case PAINT_BLEND_BLUR:     return mcol_blend(col, paintcol, alpha_i);
786                 case PAINT_BLEND_ADD:      return mcol_add(col, paintcol, alpha_i);
787                 case PAINT_BLEND_SUB:      return mcol_sub(col, paintcol, alpha_i);
788                 case PAINT_BLEND_MUL:      return mcol_mul(col, paintcol, alpha_i);
789                 case PAINT_BLEND_LIGHTEN:  return mcol_lighten(col, paintcol, alpha_i);
790                 case PAINT_BLEND_DARKEN:   return mcol_darken(col, paintcol, alpha_i);
791                 default:
792                         BLI_assert(0);
793                         return 0;
794         }
795 }
796
797 /* wpaint has 'wpaint_blend' */
798 static unsigned int vpaint_blend(VPaint *vp, unsigned int col, unsigned int colorig, const
799                                  unsigned int paintcol, const int alpha_i,
800                                  /* pre scaled from [0-1] --> [0-255] */
801                                  const int brush_alpha_value_i)
802 {
803         Brush *brush = BKE_paint_brush(&vp->paint);
804         const int tool = brush->vertexpaint_tool;
805
806         col = vpaint_blend_tool(tool, col, paintcol, alpha_i);
807
808         /* if no spray, clip color adding with colorig & orig alpha */
809         if ((vp->flag & VP_SPRAY) == 0) {
810                 unsigned int testcol, a;
811                 char *cp, *ct, *co;
812                 
813                 testcol = vpaint_blend_tool(tool, colorig, paintcol, brush_alpha_value_i);
814                 
815                 cp = (char *)&col;
816                 ct = (char *)&testcol;
817                 co = (char *)&colorig;
818                 
819                 for (a = 0; a < 4; a++) {
820                         if (ct[a] < co[a]) {
821                                 if (cp[a] < ct[a]) cp[a] = ct[a];
822                                 else if (cp[a] > co[a]) cp[a] = co[a];
823                         }
824                         else {
825                                 if (cp[a] < co[a]) cp[a] = co[a];
826                                 else if (cp[a] > ct[a]) cp[a] = ct[a];
827                         }
828                 }
829         }
830
831         return col;
832 }
833
834
835 static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
836 {
837         struct ImBuf *ibuf;
838         int a, tot = 0, index;
839         
840         /* brecht: disabled this because it obviously fails for
841          * brushes with size > 64, why is this here? */
842         /*if (size > 64.0) size = 64.0;*/
843         
844         ibuf = view3d_read_backbuf(vc, x - size, y - size, x + size, y + size);
845         if (ibuf) {
846                 unsigned int *rt = ibuf->rect;
847
848                 memset(indexar, 0, sizeof(int) * (totface + 1));
849                 
850                 size = ibuf->x * ibuf->y;
851                 while (size--) {
852                                 
853                         if (*rt) {
854                                 index = WM_framebuffer_to_index(*rt);
855                                 if (index > 0 && index <= totface)
856                                         indexar[index] = 1;
857                         }
858                 
859                         rt++;
860                 }
861                 
862                 for (a = 1; a <= totface; a++) {
863                         if (indexar[a]) indexar[tot++] = a;
864                 }
865
866                 IMB_freeImBuf(ibuf);
867         }
868         
869         return tot;
870 }
871
872 /* whats _dl mean? */
873 static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co[3],
874                                  const float mval[2], const float brush_size_pressure, float rgba[4])
875 {
876         float co_ss[2];  /* screenspace */
877
878         if (ED_view3d_project_float_object(vc->ar,
879                                            co, co_ss,
880                                            V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
881         {
882                 float delta[2];
883                 float dist_squared;
884                 float factor = 1.0;
885
886                 sub_v2_v2v2(delta, mval, co_ss);
887                 dist_squared = dot_v2v2(delta, delta); /* len squared */
888                 if (dist_squared <= brush_size_pressure * brush_size_pressure) {
889                         Brush *brush = BKE_paint_brush(&vp->paint);
890                         const float dist = sqrtf(dist_squared);
891                         if (brush->mtex.tex && rgba) {
892                                 if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
893                                         BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL);
894                                 }
895                                 else {
896                                         const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f};  /* we need a 3rd empty value */
897                                         BKE_brush_sample_tex_3D(vc->scene, brush, co_ss_3d, rgba, 0, NULL);
898                                 }
899                                 factor = rgba[3];
900                         }
901                         return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
902                 }
903         }
904         if (rgba)
905                 zero_v4(rgba);
906         return 0.0f;
907 }
908
909 static float calc_vp_alpha_col_dl(VPaint *vp, ViewContext *vc,
910                               float vpimat[3][3], const DMCoNo *v_co_no,
911                               const float mval[2],
912                               const float brush_size_pressure, const float brush_alpha_pressure, float rgba[4])
913 {
914         float strength = calc_vp_strength_col_dl(vp, vc, v_co_no->co, mval, brush_size_pressure, rgba);
915
916         if (strength > 0.0f) {
917                 float alpha = brush_alpha_pressure * strength;
918
919                 if (vp->flag & VP_NORMALS) {
920                         float dvec[3];
921
922                         /* transpose ! */
923                         dvec[2] = dot_v3v3(vpimat[2], v_co_no->no);
924                         if (dvec[2] > 0.0f) {
925                                 dvec[0] = dot_v3v3(vpimat[0], v_co_no->no);
926                                 dvec[1] = dot_v3v3(vpimat[1], v_co_no->no);
927
928                                 alpha *= dvec[2] / len_v3(dvec);
929                         }
930                         else {
931                                 return 0.0f;
932                         }
933                 }
934
935                 return alpha;
936         }
937
938         return 0.0f;
939 }
940
941
942 BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
943 {
944         const float talpha = min_ff(alpha, 1.0f);  /* blending with values over 1 doesn't make sense */
945         return (paintval * talpha) + (weight * (1.0f - talpha));
946 }
947 BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
948 {
949         return weight + (paintval * alpha);
950 }
951 BLI_INLINE float wval_sub(const float weight, const float paintval, const float alpha)
952 {
953         return weight - (paintval * alpha);
954 }
955 BLI_INLINE float wval_mul(const float weight, const float paintval, const float alpha)
956 {   /* first mul, then blend the fac */
957         return ((1.0f - alpha) + (alpha * paintval)) * weight;
958 }
959 BLI_INLINE float wval_lighten(const float weight, const float paintval, const float alpha)
960 {
961         return (weight < paintval) ? wval_blend(weight, paintval, alpha) : weight;
962 }
963 BLI_INLINE float wval_darken(const float weight, const float paintval, const float alpha)
964 {
965         return (weight > paintval) ? wval_blend(weight, paintval, alpha) : weight;
966 }
967
968
969 /* vpaint has 'vpaint_blend_tool' */
970 /* result is not clamped from [0-1] */
971 static float wpaint_blend_tool(const int tool,
972                                /* dw->weight */
973                                const float weight,
974                                const float paintval, const float alpha)
975 {
976         switch (tool) {
977                 case PAINT_BLEND_MIX:
978                 case PAINT_BLEND_BLUR:     return wval_blend(weight, paintval, alpha);
979                 case PAINT_BLEND_ADD:      return wval_add(weight, paintval, alpha);
980                 case PAINT_BLEND_SUB:      return wval_sub(weight, paintval, alpha);
981                 case PAINT_BLEND_MUL:      return wval_mul(weight, paintval, alpha);
982                 case PAINT_BLEND_LIGHTEN:  return wval_lighten(weight, paintval, alpha);
983                 case PAINT_BLEND_DARKEN:   return wval_darken(weight, paintval, alpha);
984                 default:
985                         BLI_assert(0);
986                         return 0.0f;
987         }
988 }
989
990 /* vpaint has 'vpaint_blend' */
991 static float wpaint_blend(VPaint *wp, float weight, float weight_prev,
992                           const float alpha, float paintval,
993                           const float brush_alpha_value,
994                           const short do_flip, const short do_multipaint_totsel)
995 {
996         Brush *brush = BKE_paint_brush(&wp->paint);
997         int tool = brush->vertexpaint_tool;
998
999         if (do_flip) {
1000                 switch (tool) {
1001                         case PAINT_BLEND_MIX:
1002                                 paintval = 1.f - paintval; break;
1003                         case PAINT_BLEND_ADD:
1004                                 tool = PAINT_BLEND_SUB; break;
1005                         case PAINT_BLEND_SUB:
1006                                 tool = PAINT_BLEND_ADD; break;
1007                         case PAINT_BLEND_LIGHTEN:
1008                                 tool = PAINT_BLEND_DARKEN; break;
1009                         case PAINT_BLEND_DARKEN:
1010                                 tool = PAINT_BLEND_LIGHTEN; break;
1011                 }
1012         }
1013         
1014         weight = wpaint_blend_tool(tool, weight, paintval, alpha);
1015
1016         /* delay clamping until the end so multi-paint can function when the active group is at the limits */
1017         if (do_multipaint_totsel == FALSE) {
1018                 CLAMP(weight, 0.0f, 1.0f);
1019         }
1020         
1021         /* if no spray, clip result with orig weight & orig alpha */
1022         if ((wp->flag & VP_SPRAY) == 0) {
1023                 if (do_multipaint_totsel == FALSE) {
1024                         float testw = wpaint_blend_tool(tool, weight_prev, paintval, brush_alpha_value);
1025
1026                         CLAMP(testw, 0.0f, 1.0f);
1027                         if (testw < weight_prev) {
1028                                 if (weight < testw) weight = testw;
1029                                 else if (weight > weight_prev) weight = weight_prev;
1030                         }
1031                         else {
1032                                 if (weight > testw) weight = testw;
1033                                 else if (weight < weight_prev) weight = weight_prev;
1034                         }
1035                 }
1036         }
1037
1038         return weight;
1039 }
1040
1041 /* ----------------------------------------------------- */
1042
1043
1044 /* sets wp->weight to the closest weight value to vertex */
1045 /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
1046 static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1047 {
1048         ViewContext vc;
1049         Mesh *me;
1050         short change = FALSE;
1051
1052         view3d_set_viewcontext(C, &vc);
1053         me = BKE_mesh_from_object(vc.obact);
1054
1055         if (me && me->dvert && vc.v3d && vc.rv3d) {
1056                 const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1057                 int v_idx_best = -1;
1058                 unsigned int index;
1059
1060                 view3d_operator_needs_opengl(C);
1061                 ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
1062
1063                 if (use_vert_sel) {
1064                         if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
1065                                 v_idx_best = index;
1066                         }
1067                 }
1068                 else {
1069                         if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
1070                                 v_idx_best = index;
1071                         }
1072                         else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
1073                                 /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
1074                                 BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
1075                         }
1076                 }
1077
1078                 if (v_idx_best != -1) { /* should always be valid */
1079                         ToolSettings *ts = vc.scene->toolsettings;
1080                         Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
1081                         const int vgroup_active = vc.obact->actdef - 1;
1082                         float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
1083                         BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
1084                         change = TRUE;
1085                 }
1086         }
1087
1088         if (change) {
1089                 /* not really correct since the brush didnt change, but redraws the toolbar */
1090                 WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL); /* ts->wpaint->paint.brush */
1091
1092                 return OPERATOR_FINISHED;
1093         }
1094         else {
1095                 return OPERATOR_CANCELLED;
1096         }
1097 }
1098
1099 void PAINT_OT_weight_sample(wmOperatorType *ot)
1100 {
1101         /* identifiers */
1102         ot->name = "Weight Paint Sample Weight";
1103         ot->idname = "PAINT_OT_weight_sample";
1104         ot->description = "Use the mouse to sample a weight in the 3D view";
1105
1106         /* api callbacks */
1107         ot->invoke = weight_sample_invoke;
1108         ot->poll = weight_paint_mode_poll;
1109
1110         /* flags */
1111         ot->flag = OPTYPE_UNDO;
1112 }
1113
1114 /* samples cursor location, and gives menu with vertex groups to activate */
1115 static int weight_paint_sample_enum_itemf__helper(const MDeformVert *dvert, const int defbase_tot, int *groups)
1116 {
1117         /* this func fills in used vgroup's */
1118         int found = FALSE;
1119         int i = dvert->totweight;
1120         MDeformWeight *dw;
1121         for (dw = dvert->dw; i > 0; dw++, i--) {
1122                 if (dw->def_nr < defbase_tot) {
1123                         groups[dw->def_nr] = TRUE;
1124                         found = TRUE;
1125                 }
1126         }
1127         return found;
1128 }
1129 static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
1130 {
1131         if (C) {
1132                 wmWindow *win = CTX_wm_window(C);
1133                 if (win && win->eventstate) {
1134                         ViewContext vc;
1135                         Mesh *me;
1136
1137                         view3d_set_viewcontext(C, &vc);
1138                         me = BKE_mesh_from_object(vc.obact);
1139
1140                         if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
1141                                 const int defbase_tot = BLI_countlist(&vc.obact->defbase);
1142                                 const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
1143                                 int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
1144                                 int found = FALSE;
1145                                 unsigned int index;
1146
1147                                 int mval[2] = {win->eventstate->x - vc.ar->winrct.xmin,
1148                                                win->eventstate->y - vc.ar->winrct.ymin};
1149
1150                                 view3d_operator_needs_opengl(C);
1151                                 ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
1152
1153                                 if (use_vert_sel) {
1154                                         if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
1155                                                 MDeformVert *dvert = &me->dvert[index];
1156                                                 found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
1157                                         }
1158                                 }
1159                                 else {
1160                                         if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
1161                                                 MPoly *mp = &me->mpoly[index];
1162                                                 unsigned int fidx = mp->totloop - 1;
1163
1164                                                 do {
1165                                                         MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v];
1166                                                         found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
1167                                                 } while (fidx--);
1168                                         }
1169                                 }
1170
1171                                 if (found == FALSE) {
1172                                         MEM_freeN(groups);
1173                                 }
1174                                 else {
1175                                         EnumPropertyItem *item = NULL, item_tmp = {0};
1176                                         int totitem = 0;
1177                                         int i = 0;
1178                                         bDeformGroup *dg;
1179                                         for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
1180                                                 if (groups[i]) {
1181                                                         item_tmp.identifier = item_tmp.name = dg->name;
1182                                                         item_tmp.value = i;
1183                                                         RNA_enum_item_add(&item, &totitem, &item_tmp);
1184                                                 }
1185                                         }
1186
1187                                         RNA_enum_item_end(&item, &totitem);
1188                                         *free = 1;
1189
1190                                         MEM_freeN(groups);
1191                                         return item;
1192                                 }
1193                         }
1194                 }
1195         }
1196
1197         return DummyRNA_NULL_items;
1198 }
1199
1200 static int weight_sample_group_exec(bContext *C, wmOperator *op)
1201 {
1202         int type = RNA_enum_get(op->ptr, "group");
1203         ViewContext vc;
1204         view3d_set_viewcontext(C, &vc);
1205
1206         BLI_assert(type + 1 >= 0);
1207         vc.obact->actdef = type + 1;
1208
1209         DAG_id_tag_update(&vc.obact->id, OB_RECALC_DATA);
1210         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, vc.obact);
1211         return OPERATOR_FINISHED;
1212 }
1213
1214 /* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active rather than its own operator */
1215 void PAINT_OT_weight_sample_group(wmOperatorType *ot)
1216 {
1217         PropertyRNA *prop = NULL;
1218
1219         /* identifiers */
1220         ot->name = "Weight Paint Sample Group";
1221         ot->idname = "PAINT_OT_weight_sample_group";
1222         ot->description = "Select one of the vertex groups available under current mouse position";
1223
1224         /* api callbacks */
1225         ot->exec = weight_sample_group_exec;
1226         ot->invoke = WM_menu_invoke;
1227         ot->poll = weight_paint_mode_poll;
1228
1229         /* flags */
1230         ot->flag = OPTYPE_UNDO;
1231
1232         /* keyingset to use (dynamic enum) */
1233         prop = RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1234         RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
1235         ot->prop = prop;
1236 }
1237
1238 static void do_weight_paint_normalize_all(MDeformVert *dvert, const int defbase_tot, const char *vgroup_validmap)
1239 {
1240         float sum = 0.0f, fac;
1241         unsigned int i, tot = 0;
1242         MDeformWeight *dw;
1243
1244         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1245                 if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1246                         tot++;
1247                         sum += dw->weight;
1248                 }
1249         }
1250
1251         if ((tot == 0) || (sum == 1.0f)) {
1252                 return;
1253         }
1254
1255         if (sum != 0.0f) {
1256                 fac = 1.0f / sum;
1257
1258                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1259                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1260                                 dw->weight *= fac;
1261                         }
1262                 }
1263         }
1264         else {
1265                 /* hrmf, not a factor in this case */
1266                 fac = 1.0f / tot;
1267
1268                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1269                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1270                                 dw->weight = fac;
1271                         }
1272                 }
1273         }
1274 }
1275
1276 /* same as function above except it normalizes against the active vgroup which remains unchanged
1277  *
1278  * note that the active is just the group which is unchanged, it can be any,
1279  * can also be -1 to normalize all but in that case call 'do_weight_paint_normalize_all' */
1280 static void do_weight_paint_normalize_all_active(MDeformVert *dvert, const int defbase_tot, const char *vgroup_validmap,
1281                                                  const int vgroup_active)
1282 {
1283         float sum = 0.0f, fac;
1284         unsigned int i, tot = 0;
1285         MDeformWeight *dw;
1286         float act_weight = 0.0f;
1287
1288         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1289                 if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1290                         if (dw->def_nr != vgroup_active) {
1291                                 sum += dw->weight;
1292                                 tot++;
1293                         }
1294                         else {
1295                                 act_weight = dw->weight;
1296                         }
1297                 }
1298         }
1299
1300         if ((tot == 0) || (sum + act_weight == 1.0f)) {
1301                 return;
1302         }
1303
1304         if (sum != 0.0f) {
1305                 fac = (1.0f / sum) * (1.0f - act_weight);
1306
1307                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1308                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1309                                 if (dw->def_nr != vgroup_active) {
1310                                         dw->weight *= fac;
1311
1312                                         /* paranoid but possibly with float error */
1313                                         CLAMP(dw->weight, 0.0f, 1.0f);
1314                                 }
1315                         }
1316                 }
1317         }
1318         else {
1319                 /* corner case where we need to scale all weights evenly because they're all zero */
1320
1321                 /* hrmf, not a factor in this case */
1322                 fac = (1.0f - act_weight) / tot;
1323
1324                 /* paranoid but possibly with float error */
1325                 CLAMP(fac, 0.0f, 1.0f);
1326
1327                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1328                         if (dw->def_nr < defbase_tot && vgroup_validmap[dw->def_nr]) {
1329                                 if (dw->def_nr != vgroup_active) {
1330                                         dw->weight = fac;
1331                                 }
1332                         }
1333                 }
1334         }
1335 }
1336
1337 /*
1338  * See if the current deform vertex has a locked group
1339  */
1340 static char has_locked_group(MDeformVert *dvert, const int defbase_tot,
1341                              const char *bone_groups, const char *lock_flags)
1342 {
1343         int i;
1344         MDeformWeight *dw;
1345
1346         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
1347                 if (dw->def_nr < defbase_tot) {
1348                         if (bone_groups[dw->def_nr] && lock_flags[dw->def_nr] && dw->weight > 0.0f) {
1349                                 return TRUE;
1350                         }
1351                 }
1352         }
1353         return FALSE;
1354 }
1355
1356 static int has_locked_group_selected(int defbase_tot, const char *defbase_sel, const char *lock_flags)
1357 {
1358         int i;
1359         for (i = 0; i < defbase_tot; i++) {
1360                 if (defbase_sel[i] && lock_flags[i]) {
1361                         return TRUE;
1362                 }
1363         }
1364         return FALSE;
1365 }
1366
1367
1368 #if 0 /* UNUSED */
1369 static int has_unselected_unlocked_bone_group(int defbase_tot, char *defbase_sel, int selected, char *lock_flags, char *vgroup_validmap)
1370 {
1371         int i;
1372         if (defbase_tot == selected) {
1373                 return FALSE;
1374         }
1375         for (i = 0; i < defbase_tot; i++) {
1376                 if (vgroup_validmap[i] && !defbase_sel[i] && !lock_flags[i]) {
1377                         return TRUE;
1378                 }
1379         }
1380         return FALSE;
1381 }
1382 #endif
1383
1384
1385 static void multipaint_selection(MDeformVert *dvert, const int defbase_tot, float change, const char *defbase_sel)
1386 {
1387         int i;
1388         MDeformWeight *dw;
1389         float val;
1390         /* make sure they are all at most 1 after the change */
1391         for (i = 0; i < defbase_tot; i++) {
1392                 if (defbase_sel[i]) {
1393                         dw = defvert_find_index(dvert, i);
1394                         if (dw && dw->weight) {
1395                                 val = dw->weight * change;
1396                                 if (val > 1) {
1397                                         /* TODO: when the change is reduced, you need to recheck
1398                                          * the earlier values to make sure they are not 0
1399                                          * (precision error) */
1400                                         change = 1.0f / dw->weight;
1401                                 }
1402                                 /* the value should never reach zero while multi-painting if it
1403                                  * was nonzero beforehand */
1404                                 if (val <= 0) {
1405                                         return;
1406                                 }
1407                         }
1408                 }
1409         }
1410         /* apply the valid change */
1411         for (i = 0; i < defbase_tot; i++) {
1412                 if (defbase_sel[i]) {
1413                         dw = defvert_find_index(dvert, i);
1414                         if (dw && dw->weight) {
1415                                 dw->weight = dw->weight * change;
1416                         }
1417                 }
1418         }
1419 }
1420
1421 /* move all change onto valid, unchanged groups.  If there is change left over,
1422  * then return it.
1423  * assumes there are valid groups to shift weight onto */
1424 static float redistribute_change(MDeformVert *ndv, const int defbase_tot,
1425                                  char *change_status, const char change_me, int changeto,
1426                                  float totchange, float total_valid,
1427                                  char do_auto_normalize)
1428 {
1429         float was_change;
1430         float change;
1431         float oldval;
1432         MDeformWeight *ndw;
1433         int i;
1434         do {
1435                 /* assume there is no change until you see one */
1436                 was_change = FALSE;
1437                 /* change each group by the same amount each time */
1438                 change = totchange / total_valid;
1439                 for (i = 0; i < ndv->totweight && total_valid && totchange; i++) {
1440                         ndw = (ndv->dw + i);
1441
1442                         /* ignore anything outside the value range */
1443                         if (ndw->def_nr < defbase_tot) {
1444
1445                                 /* change only the groups with a valid status */
1446                                 if (change_status[ndw->def_nr] == change_me) {
1447                                         oldval = ndw->weight;
1448                                         /* if auto normalize is active, don't worry about upper bounds */
1449                                         if (do_auto_normalize == FALSE && ndw->weight + change > 1) {
1450                                                 totchange -= 1.0f - ndw->weight;
1451                                                 ndw->weight = 1.0f;
1452                                                 /* stop the changes to this group */
1453                                                 change_status[ndw->def_nr] = changeto;
1454                                                 total_valid--;
1455                                         }
1456                                         else if (ndw->weight + change < 0) { /* check the lower bound */
1457                                                 totchange -= ndw->weight;
1458                                                 ndw->weight = 0;
1459                                                 change_status[ndw->def_nr] = changeto;
1460                                                 total_valid--;
1461                                         }
1462                                         else { /* a perfectly valid change occurred to ndw->weight */
1463                                                 totchange -= change;
1464                                                 ndw->weight += change;
1465                                         }
1466                                         /* see if there was a change */
1467                                         if (oldval != ndw->weight) {
1468                                                 was_change = TRUE;
1469                                         }
1470                                 }
1471                         }
1472                 }
1473                 /* don't go again if there was no change, if there is no valid group,
1474                  * or there is no change left */
1475         } while (was_change && total_valid && totchange);
1476         /* left overs */
1477         return totchange;
1478 }
1479 static float get_mp_change(MDeformVert *odv, const int defbase_tot, const char *defbase_sel, float brush_change);
1480 /* observe the changes made to the weights of groups.
1481  * make sure all locked groups on the vertex have the same deformation
1482  * by moving the changes made to groups onto other unlocked groups */
1483 static void enforce_locks(MDeformVert *odv, MDeformVert *ndv,
1484                           const int defbase_tot, const char *defbase_sel,
1485                           const char *lock_flags, const char *vgroup_validmap,
1486                           char do_auto_normalize, char do_multipaint)
1487 {
1488         float totchange = 0.0f;
1489         float totchange_allowed = 0.0f;
1490         float left_over;
1491
1492         int total_valid = 0;
1493         int total_changed = 0;
1494         unsigned int i;
1495         MDeformWeight *ndw;
1496         MDeformWeight *odw;
1497
1498         // float changed_sum = 0.0f;  // UNUSED
1499
1500         char *change_status;
1501
1502         if (!lock_flags || !has_locked_group(ndv, defbase_tot, vgroup_validmap, lock_flags)) {
1503                 return;
1504         }
1505         /* record if a group was changed, unlocked and not changed, or locked */
1506         change_status = MEM_callocN(sizeof(char) * defbase_tot, "unlocked_unchanged");
1507
1508         for (i = 0; i < defbase_tot; i++) {
1509                 ndw = defvert_find_index(ndv, i);
1510                 odw = defvert_find_index(odv, i);
1511                 /* the weights are zero, so we can assume a lot */
1512                 if (!ndw || !odw) {
1513                         if (!lock_flags[i] && vgroup_validmap[i]) {
1514                                 defvert_verify_index(odv, i);
1515                                 defvert_verify_index(ndv, i);
1516                                 total_valid++;
1517                                 change_status[i] = 1; /* can be altered while redistributing */
1518                         }
1519                         continue;
1520                 }
1521                 /* locked groups should not be changed */
1522                 if (lock_flags[i]) {
1523                         ndw->weight = odw->weight;
1524                 }
1525                 else if (ndw->weight != odw->weight) { /* changed groups are handled here */
1526                         totchange += ndw->weight - odw->weight;
1527                         // changed_sum += ndw->weight;  // UNUSED
1528                         change_status[i] = 2; /* was altered already */
1529                         total_changed++;
1530                 } /* unchanged, unlocked bone groups are handled here */
1531                 else if (vgroup_validmap[i]) {
1532                         totchange_allowed += ndw->weight;
1533                         total_valid++;
1534                         change_status[i] = 1; /* can be altered while redistributing */
1535                 }
1536         }
1537         /* if there was any change, redistribute it */
1538         if (total_changed) {
1539                 /* auto normalize will allow weights to temporarily go above 1 in redistribution */
1540                 if (vgroup_validmap && total_changed < 0 && total_valid) {
1541                         totchange_allowed = total_valid;
1542                 }
1543                 /* the way you modify the unlocked + unchanged groups is different depending
1544                  * on whether or not you are painting the weight(s) up or down */
1545                 if (totchange < 0) {
1546                         totchange_allowed = total_valid - totchange_allowed;
1547                 }
1548                 else {
1549                         totchange_allowed *= -1;
1550                 }
1551                 /* there needs to be change allowed, or you should not bother */
1552                 if (totchange_allowed) {
1553                         left_over = 0;
1554                         if (fabsf(totchange_allowed) < fabsf(totchange)) {
1555                                 /* this amount goes back onto the changed, unlocked weights */
1556                                 left_over = fabsf(fabsf(totchange) - fabsf(totchange_allowed));
1557                                 if (totchange > 0) {
1558                                         left_over *= -1;
1559                                 }
1560                         }
1561                         else {
1562                                 /* all of the change will be permitted */
1563                                 totchange_allowed = -totchange;
1564                         }
1565                         /* move the weight evenly between the allowed groups, move excess back onto the used groups based on the change */
1566                         totchange_allowed = redistribute_change(ndv, defbase_tot, change_status, 1, -1, totchange_allowed, total_valid, do_auto_normalize);
1567                         left_over += totchange_allowed;
1568                         if (left_over) {
1569                                 /* more than one nonzero weights were changed with the same ratio with multipaint, so keep them changed that way! */
1570                                 if (total_changed > 1 && do_multipaint) {
1571                                         float undo_change = get_mp_change(ndv, defbase_tot, defbase_sel, left_over);
1572                                         multipaint_selection(ndv, defbase_tot, undo_change, defbase_sel);
1573                                 }
1574                                 /* or designatedw is still -1 put weight back as evenly as possible */
1575                                 else {
1576                                         redistribute_change(ndv, defbase_tot, change_status, 2, -2, left_over, total_changed, do_auto_normalize);
1577                                 }
1578                         }
1579                 }
1580                 else {
1581                         /* reset the weights */
1582                         MDeformWeight *dw_old = odv->dw;
1583                         MDeformWeight *dw_new = ndv->dw;
1584
1585                         for (i = odv->totweight; i != 0; i--, dw_old++, dw_new++) {
1586                                 dw_new->weight = dw_old->weight;
1587                         }
1588                 }
1589         }
1590
1591         MEM_freeN(change_status);
1592 }
1593
1594 /* multi-paint's initial, potential change is computed here based on the user's stroke */
1595 static float get_mp_change(MDeformVert *odv, const int defbase_tot, const char *defbase_sel, float brush_change)
1596 {
1597         float selwsum = 0.0f;
1598         unsigned int i;
1599         MDeformWeight *dw = odv->dw;
1600
1601         for (i = odv->totweight; i != 0; i--, dw++) {
1602                 if (dw->def_nr < defbase_tot) {
1603                         if (defbase_sel[dw->def_nr]) {
1604                                 selwsum += dw->weight;
1605                         }
1606                 }
1607         }
1608         if (selwsum && selwsum + brush_change > 0) {
1609                 return (selwsum + brush_change) / selwsum;
1610         }
1611         return 0.0f;
1612 }
1613
1614 /* change the weights back to the wv's weights
1615  * it assumes you already have the correct pointer index */
1616 static void defvert_reset_to_prev(MDeformVert *dv_prev, MDeformVert *dv)
1617 {
1618         MDeformWeight *dw = dv->dw;
1619         MDeformWeight *dw_prev;
1620         unsigned int i;
1621         for (i = dv->totweight; i != 0; i--, dw++) {
1622                 dw_prev = defvert_find_index(dv_prev, dw->def_nr);
1623                 /* if there was no w when there is a d, then the old weight was 0 */
1624                 dw->weight = dw_prev ? dw_prev->weight : 0.0f;
1625         }
1626 }
1627
1628 static void clamp_weights(MDeformVert *dvert)
1629 {
1630         MDeformWeight *dw = dvert->dw;
1631         unsigned int i;
1632         for (i = dvert->totweight; i != 0; i--, dw++) {
1633                 CLAMP(dw->weight, 0.0f, 1.0f);
1634         }
1635 }
1636
1637 /* struct to avoid passing many args each call to do_weight_paint_vertex()
1638  * this _could_ be made a part of the operators 'WPaintData' struct, or at
1639  * least a member, but for now keep its own struct, initialized on every
1640  * paint stroke update - campbell */
1641 typedef struct WeightPaintInfo {
1642
1643         int defbase_tot;
1644
1645         /* both must add up to 'defbase_tot' */
1646         int defbase_tot_sel;
1647         int defbase_tot_unsel;
1648
1649         int vgroup_active; /* (ob->actdef - 1) */
1650         int vgroup_mirror; /* mirror group or -1 */
1651
1652         const char *lock_flags;  /* boolean array for locked bones,
1653                                   * length of defbase_tot */
1654         const char *defbase_sel; /* boolean array for selected bones,
1655                                   * length of defbase_tot, cant be const because of how its passed */
1656
1657         const char *vgroup_validmap; /* same as WeightPaintData.vgroup_validmap,
1658                                       * only added here for convenience */
1659
1660         char do_flip;
1661         char do_multipaint;
1662         char do_auto_normalize;
1663
1664         float brush_alpha_value;  /* result of BKE_brush_alpha_get() */
1665 } WeightPaintInfo;
1666
1667 /* fresh start to make multi-paint and locking modular */
1668 /* returns TRUE if it thinks you need to reset the weights due to
1669  * normalizing while multi-painting
1670  *
1671  * note: this assumes dw->def_nr range has been checked by the caller
1672  */
1673 static int apply_mp_locks_normalize(Mesh *me, const WeightPaintInfo *wpi,
1674                                     const unsigned int index,
1675                                     MDeformWeight *dw, MDeformWeight *tdw,
1676                                     float change, float oldChange,
1677                                     float oldw, float neww)
1678 {
1679         MDeformVert *dv = &me->dvert[index];
1680         MDeformVert dv_test = {NULL};
1681
1682         dv_test.dw = MEM_dupallocN(dv->dw);
1683         dv_test.flag = dv->flag;
1684         dv_test.totweight = dv->totweight;
1685         /* do not multi-paint if a locked group is selected or the active group is locked
1686          * !lock_flags[dw->def_nr] helps if nothing is selected, but active group is locked */
1687         if ((wpi->lock_flags == NULL) ||
1688             ((wpi->lock_flags[dw->def_nr] == FALSE) && /* def_nr range has to be checked for by caller */
1689              has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE))
1690         {
1691                 if (wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
1692                         if (change && change != 1) {
1693                                 multipaint_selection(dv, wpi->defbase_tot, change, wpi->defbase_sel);
1694                         }
1695                 }
1696                 else { /* this lets users paint normally, but don't let them paint locked groups */
1697                         dw->weight = neww;
1698                 }
1699         }
1700         clamp_weights(dv);
1701
1702         enforce_locks(&dv_test, dv, wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags, wpi->vgroup_validmap, wpi->do_auto_normalize, wpi->do_multipaint);
1703
1704         if (wpi->do_auto_normalize) {
1705                 /* XXX - should we pass the active group? - currently '-1' */
1706                 do_weight_paint_normalize_all(dv, wpi->defbase_tot, wpi->vgroup_validmap);
1707         }
1708
1709         if (oldChange && wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
1710                 if (tdw->weight != oldw) {
1711                         if (neww > oldw) {
1712                                 if (tdw->weight <= oldw) {
1713                                         MEM_freeN(dv_test.dw);
1714                                         return TRUE;
1715                                 }
1716                         }
1717                         else {
1718                                 if (tdw->weight >= oldw) {
1719                                         MEM_freeN(dv_test.dw);
1720                                         return TRUE;
1721                                 }
1722                         }
1723                 }
1724         }
1725         MEM_freeN(dv_test.dw);
1726         return FALSE;
1727 }
1728
1729 /* within the current dvert index, get the dw that is selected and has a weight
1730  * above 0, this helps multi-paint */
1731 static int get_first_selected_nonzero_weight(MDeformVert *dvert, const int defbase_tot, const char *defbase_sel)
1732 {
1733         int i;
1734         MDeformWeight *dw = dvert->dw;
1735         for (i = 0; i < dvert->totweight; i++, dw++) {
1736                 if (dw->def_nr < defbase_tot) {
1737                         if (defbase_sel[dw->def_nr] && dw->weight > 0.0f) {
1738                                 return i;
1739                         }
1740                 }
1741         }
1742         return -1;
1743 }
1744
1745 static void do_weight_paint_vertex(
1746         /* vars which remain the same for every vert */
1747         VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
1748         /* vars which change on each stroke */
1749         const unsigned int index, float alpha, float paintweight
1750         )
1751 {
1752         Mesh *me = ob->data;
1753         MDeformVert *dv = &me->dvert[index];
1754         
1755         MDeformWeight *dw, *dw_prev;
1756
1757         /* mirror vars */
1758         int index_mirr;
1759         int vgroup_mirr;
1760
1761         MDeformVert *dv_mirr;
1762         MDeformWeight *dw_mirr;
1763
1764         const short do_multipaint_totsel = (wpi->do_multipaint && wpi->defbase_tot_sel > 1);
1765
1766         if (wp->flag & VP_ONLYVGROUP) {
1767                 dw = defvert_find_index(dv, wpi->vgroup_active);
1768                 dw_prev = defvert_find_index(wp->wpaint_prev + index, wpi->vgroup_active);
1769         }
1770         else {
1771                 dw = defvert_verify_index(dv, wpi->vgroup_active);
1772                 dw_prev = defvert_verify_index(wp->wpaint_prev + index, wpi->vgroup_active);
1773         }
1774
1775         if (dw == NULL || dw_prev == NULL) {
1776                 return;
1777         }
1778
1779
1780         /* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
1781         if (me->editflag & ME_EDIT_MIRROR_X) {
1782                 index_mirr = mesh_get_x_mirror_vert(ob, index);
1783                 vgroup_mirr = (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : wpi->vgroup_active;
1784
1785                 /* another possible error - mirror group _and_ active group are the same (which is fine),
1786                  * but we also are painting onto a center vertex - this would paint the same weight twice */
1787                 if (index_mirr == index && vgroup_mirr == wpi->vgroup_active) {
1788                         index_mirr = vgroup_mirr = -1;
1789                 }
1790         }
1791         else {
1792                 index_mirr = vgroup_mirr = -1;
1793         }
1794
1795
1796         /* get the mirror def vars */
1797         if (index_mirr != -1) {
1798                 dv_mirr = &me->dvert[index_mirr];
1799                 if (wp->flag & VP_ONLYVGROUP) {
1800                         dw_mirr = defvert_find_index(dv_mirr, vgroup_mirr);
1801
1802                         if (dw_mirr == NULL) {
1803                                 index_mirr = vgroup_mirr = -1;
1804                                 dv_mirr = NULL;
1805                         }
1806                 }
1807                 else {
1808                         if (index != index_mirr) {
1809                                 dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
1810                         }
1811                         else {
1812                                 /* dv and dv_mirr are the same */
1813                                 int totweight_prev = dv_mirr->totweight;
1814                                 int dw_offset = (int)(dw - dv_mirr->dw);
1815                                 dw_mirr = defvert_verify_index(dv_mirr, vgroup_mirr);
1816
1817                                 /* if we added another, get our old one back */
1818                                 if (totweight_prev != dv_mirr->totweight) {
1819                                         dw = &dv_mirr->dw[dw_offset];
1820                                 }
1821                         }
1822                 }
1823         }
1824         else {
1825                 dv_mirr = NULL;
1826                 dw_mirr = NULL;
1827         }
1828
1829
1830         /* TODO: De-duplicate the simple weight paint - jason */
1831         /* ... or not, since its <10 SLOC - campbell */
1832
1833         /* If there are no locks or multipaint,
1834          * then there is no need to run the more complicated checks */
1835         if ((do_multipaint_totsel == FALSE) &&
1836             (wpi->lock_flags == NULL || has_locked_group(dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags) == FALSE))
1837         {
1838                 dw->weight = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight,
1839                                           wpi->brush_alpha_value, wpi->do_flip, FALSE);
1840
1841                 /* WATCH IT: take care of the ordering of applying mirror -> normalize,
1842                  * can give wrong results [#26193], least confusing if normalize is done last */
1843
1844                 /* apply mirror */
1845                 if (index_mirr != -1) {
1846                         /* copy, not paint again */
1847                         dw_mirr->weight = dw->weight;
1848                 }
1849
1850                 /* apply normalize */
1851                 if (wpi->do_auto_normalize) {
1852                         /* note on normalize - this used to be applied after painting and normalize all weights,
1853                          * in some ways this is good because there is feedback where the more weights involved would
1854                          * 'resist' so you couldn't instantly zero out other weights by painting 1.0 on the active.
1855                          *
1856                          * However this gave a problem since applying mirror, then normalize both verts
1857                          * the resulting weight wont match on both sides.
1858                          *
1859                          * If this 'resisting', slower normalize is nicer, we could call
1860                          * do_weight_paint_normalize_all() and only use...
1861                          * do_weight_paint_normalize_all_active() when normalizing the mirror vertex.
1862                          * - campbell
1863                          */
1864                         do_weight_paint_normalize_all_active(dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->vgroup_active);
1865
1866                         if (index_mirr != -1) {
1867                                 /* only normalize if this is not a center vertex, else we get a conflict, normalizing twice */
1868                                 if (index != index_mirr) {
1869                                         do_weight_paint_normalize_all_active(dv_mirr, wpi->defbase_tot, wpi->vgroup_validmap, vgroup_mirr);
1870                                 }
1871                                 else {
1872                                         /* this case accounts for...
1873                                          * - painting onto a center vertex of a mesh
1874                                          * - x mirror is enabled
1875                                          * - auto normalize is enabled
1876                                          * - the group you are painting onto has a L / R version
1877                                          *
1878                                          * We want L/R vgroups to have the same weight but this cant be if both are over 0.5,
1879                                          * We _could_ have special check for that, but this would need its own normalize function which
1880                                          * holds 2 groups from changing at once.
1881                                          *
1882                                          * So! just balance out the 2 weights, it keeps them equal and everything normalized.
1883                                          *
1884                                          * While it wont hit the desired weight immediately as the user waggles their mouse,
1885                                          * constant painting and re-normalizing will get there. this is also just simpler logic.
1886                                          * - campbell */
1887                                         dw_mirr->weight = dw->weight = (dw_mirr->weight + dw->weight) * 0.5f;
1888                                 }
1889                         }
1890                 }
1891         }
1892         else {
1893                 /* use locks and/or multipaint */
1894                 float oldw;
1895                 float neww;
1896                 /* float testw = 0; */ /* UNUSED */
1897                 float observedChange = 0;
1898                 float change = 0;
1899                 float oldChange = 0;
1900                 int i;
1901                 MDeformWeight *tdw = NULL, *tdw_prev;
1902                 MDeformVert dv_copy = {NULL};
1903
1904                 oldw = dw->weight;
1905                 neww = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight,
1906                                     wpi->brush_alpha_value, wpi->do_flip, do_multipaint_totsel);
1907                 
1908                 /* setup multi-paint */
1909                 observedChange = neww - oldw;
1910                 if (do_multipaint_totsel && observedChange) {
1911                         dv_copy.dw = MEM_dupallocN(dv->dw);
1912                         dv_copy.flag = dv->flag;
1913                         dv_copy.totweight = dv->totweight;
1914                         tdw = dw;
1915                         tdw_prev = dw_prev;
1916                         change = get_mp_change(&wp->wpaint_prev[index], wpi->defbase_tot, wpi->defbase_sel, observedChange);
1917                         if (change) {
1918                                 if (!tdw->weight) {
1919                                         i = get_first_selected_nonzero_weight(dv, wpi->defbase_tot, wpi->defbase_sel);
1920                                         if (i >= 0) {
1921                                                 tdw = &(dv->dw[i]);
1922                                                 tdw_prev = defvert_verify_index(&wp->wpaint_prev[index], tdw->def_nr);
1923                                         }
1924                                         else {
1925                                                 change = 0;
1926                                         }
1927                                 }
1928                                 if (change && tdw_prev->weight && tdw_prev->weight * change) {
1929                                         if (tdw->weight != tdw_prev->weight) {
1930                                                 oldChange = tdw->weight / tdw_prev->weight;
1931                                                 /* testw = tdw_prev->weight * change; */ /* UNUSED */
1932                                                 if (observedChange > 0) {
1933                                                         if (change > oldChange) {
1934                                                                 /* reset the weights and use the new change */
1935                                                                 defvert_reset_to_prev(wp->wpaint_prev + index, dv);
1936                                                         }
1937                                                         else {
1938                                                                 /* the old change was more significant, so set
1939                                                                  * the change to 0 so that it will not do another multi-paint */
1940                                                                 change = 0;
1941                                                         }
1942                                                 }
1943                                                 else {
1944                                                         if (change < oldChange) {
1945                                                                 defvert_reset_to_prev(wp->wpaint_prev + index, dv);
1946                                                         }
1947                                                         else {
1948                                                                 change = 0;
1949                                                         }
1950                                                 }
1951                                         }
1952                                 }
1953                                 else {
1954                                         change = 0;
1955                                 }
1956                         }
1957                 }
1958                 
1959                 if (apply_mp_locks_normalize(me, wpi, index, dw, tdw, change, oldChange, oldw, neww)) {
1960                         defvert_reset_to_prev(&dv_copy, dv);
1961                         change = 0;
1962                         oldChange = 0;
1963                 }
1964                 if (dv_copy.dw) {
1965                         MEM_freeN(dv_copy.dw);
1966                 }
1967 #if 0
1968                 /* dv may have been altered greatly */
1969                 dw = defvert_find_index(dv, vgroup);
1970 #else
1971                 dw = NULL; /* UNUSED after assignment, set to NULL to ensure we don't
1972                             * use again, we thats needed un-ifdef the line above */
1973                 (void)dw;  /* quiet warnigns */
1974 #endif
1975
1976                 /* x mirror painting */
1977                 if (index_mirr != -1) {
1978                         /* copy, not paint again */
1979
1980                         /* dw_mirr->weight = dw->weight; */  /* TODO, explain the logic in not assigning weight! - campbell */
1981                         apply_mp_locks_normalize(me, wpi, index_mirr, dw_mirr, tdw, change, oldChange, oldw, neww);
1982                 }
1983         }
1984 }
1985
1986
1987 /* *************** set wpaint operator ****************** */
1988
1989 static int set_wpaint(bContext *C, wmOperator *UNUSED(op))  /* toggle */
1990 {               
1991         Object *ob = CTX_data_active_object(C);
1992         Scene *scene = CTX_data_scene(C);
1993         VPaint *wp = scene->toolsettings->wpaint;
1994         Mesh *me;
1995         
1996         me = BKE_mesh_from_object(ob);
1997         if (ob->id.lib || me == NULL) return OPERATOR_PASS_THROUGH;
1998         
1999         if (ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
2000         else ob->mode |= OB_MODE_WEIGHT_PAINT;
2001         
2002         
2003         /* Weightpaint works by overriding colors in mesh,
2004          * so need to make sure we recalc on enter and
2005          * exit (exit needs doing regardless because we
2006          * should redeform).
2007          */
2008         DAG_id_tag_update(&me->id, 0);
2009         
2010         if (ob->mode & OB_MODE_WEIGHT_PAINT) {
2011                 Object *par;
2012                 
2013                 if (wp == NULL)
2014                         wp = scene->toolsettings->wpaint = new_vpaint(1);
2015
2016                 BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
2017                 paint_cursor_start(C, weight_paint_poll);
2018                 
2019                 mesh_octree_table(ob, NULL, NULL, 's');
2020                 
2021                 /* verify if active weight group is also active bone */
2022                 par = modifiers_isDeformedByArmature(ob);
2023                 if (par && (par->mode & OB_MODE_POSE)) {
2024                         bArmature *arm = par->data;
2025
2026                         if (arm->act_bone)
2027                                 ED_vgroup_select_by_name(ob, arm->act_bone->name);
2028                 }
2029         }
2030         else {
2031                 mesh_octree_table(NULL, NULL, NULL, 'e');
2032                 mesh_mirrtopo_table(NULL, 'e');
2033
2034                 if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
2035                         BKE_mesh_flush_select_from_verts(me);
2036                 }
2037                 else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
2038                         BKE_mesh_flush_select_from_polys(me);
2039                 }
2040         }
2041         
2042         WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
2043         
2044         return OPERATOR_FINISHED;
2045 }
2046
2047 /* for switching to/from mode */
2048 static int paint_poll_test(bContext *C)
2049 {
2050         Object *ob = CTX_data_active_object(C);
2051         if (CTX_data_edit_object(C))
2052                 return 0;
2053         if (CTX_data_active_object(C) == NULL)
2054                 return 0;
2055         if (!ob->data || ((ID *)ob->data)->lib)
2056                 return 0;
2057         return 1;
2058 }
2059
2060 void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
2061 {
2062         
2063         /* identifiers */
2064         ot->name = "Weight Paint Mode";
2065         ot->idname = "PAINT_OT_weight_paint_toggle";
2066         ot->description = "Toggle weight paint mode in 3D view";
2067         
2068         /* api callbacks */
2069         ot->exec = set_wpaint;
2070         ot->poll = paint_poll_test;
2071         
2072         /* flags */
2073         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2074         
2075 }
2076
2077 /* ************ weight paint operator ********** */
2078
2079 struct WPaintData {
2080         ViewContext vc;
2081         int *indexar;
2082         int vgroup_active;
2083         int vgroup_mirror;
2084         DMCoNo *vertexcosnos;
2085         float wpimat[3][3];
2086
2087         /* variables for auto normalize */
2088         const char *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
2089         const char *lock_flags;
2090         int defbase_tot;
2091 };
2092
2093 /* ensure we have data on wpaint start, add if needed */
2094 static int wpaint_ensure_data(bContext *C, wmOperator *op)
2095 {
2096         Scene *scene = CTX_data_scene(C);
2097         Object *ob = CTX_data_active_object(C);
2098         Mesh *me = BKE_mesh_from_object(ob);
2099
2100         if (scene->obedit) {
2101                 return FALSE;
2102         }
2103
2104         if (me == NULL || me->totpoly == 0) {
2105                 return FALSE;
2106         }
2107
2108         /* if nothing was added yet, we make dverts and a vertex deform group */
2109         if (!me->dvert) {
2110                 ED_vgroup_data_create(&me->id);
2111                 WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
2112         }
2113
2114         /* this happens on a Bone select, when no vgroup existed yet */
2115         if (ob->actdef <= 0) {
2116                 Object *modob;
2117                 if ((modob = modifiers_isDeformedByArmature(ob))) {
2118                         Bone *actbone = ((bArmature *)modob->data)->act_bone;
2119                         if (actbone) {
2120                                 bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name);
2121
2122                                 if (pchan) {
2123                                         bDeformGroup *dg = defgroup_find_name(ob, pchan->name);
2124                                         if (dg == NULL) {
2125                                                 dg = ED_vgroup_add_name(ob, pchan->name);  /* sets actdef */
2126                                         }
2127                                         else {
2128                                                 int actdef = 1 + BLI_findindex(&ob->defbase, dg);
2129                                                 BLI_assert(actdef >= 0);
2130                                                 ob->actdef = actdef;
2131                                         }
2132                                 }
2133                         }
2134                 }
2135         }
2136         if (ob->defbase.first == NULL) {
2137                 ED_vgroup_add(ob);
2138         }
2139
2140         /* ensure we don't try paint onto an invalid group */
2141         if (ob->actdef <= 0) {
2142                 BKE_report(op->reports, RPT_WARNING, "No active vertex group for painting, aborting");
2143                 return FALSE;
2144         }
2145
2146         return TRUE;
2147 }
2148
2149 static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
2150 {
2151         Scene *scene = CTX_data_scene(C);
2152         struct PaintStroke *stroke = op->customdata;
2153         ToolSettings *ts = scene->toolsettings;
2154         VPaint *wp = ts->wpaint;
2155         Object *ob = CTX_data_active_object(C);
2156         Mesh *me = BKE_mesh_from_object(ob);
2157         struct WPaintData *wpd;
2158
2159         float mat[4][4], imat[4][4];
2160
2161         if (wpaint_ensure_data(C, op) == FALSE) {
2162                 return FALSE;
2163         }
2164
2165         {
2166                 /* check if we are attempting to paint onto a locked vertex group,
2167                  * and other options disallow it from doing anything useful */
2168                 bDeformGroup *dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
2169                 if (dg->flag & DG_LOCK_WEIGHT) {
2170                         BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting");
2171                         return FALSE;
2172                 }
2173         }
2174
2175         /* ALLOCATIONS! no return after this line */
2176         /* make mode data storage */
2177         wpd = MEM_callocN(sizeof(struct WPaintData), "WPaintData");
2178         paint_stroke_set_mode_data(stroke, wpd);
2179         view3d_set_viewcontext(C, &wpd->vc);
2180
2181         wpd->vgroup_active = ob->actdef - 1;
2182         wpd->vgroup_mirror = -1;
2183
2184         /* set up auto-normalize, and generate map for detecting which
2185          * vgroups affect deform bones */
2186         wpd->defbase_tot = BLI_countlist(&ob->defbase);
2187         wpd->lock_flags = BKE_objdef_lock_flags_get(ob, wpd->defbase_tot);
2188         if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) {
2189                 wpd->vgroup_validmap = BKE_objdef_validmap_get(ob, wpd->defbase_tot);
2190         }
2191
2192         /* painting on subsurfs should give correct points too, this returns me->totvert amount */
2193         wpd->vertexcosnos = mesh_get_mapped_verts_nors(scene, ob);
2194         wpd->indexar = get_indexarray(me);
2195         copy_wpaint_prev(wp, me->dvert, me->totvert);
2196
2197         /* imat for normals */
2198         mult_m4_m4m4(mat, wpd->vc.rv3d->viewmat, ob->obmat);
2199         invert_m4_m4(imat, mat);
2200         copy_m3_m4(wpd->wpimat, imat);
2201
2202         /* if mirror painting, find the other group */
2203         if (me->editflag & ME_EDIT_MIRROR_X) {
2204                 wpd->vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, wpd->vgroup_active);
2205         }
2206
2207         {
2208                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
2209                 ups->draw_pressure = true;
2210         }
2211         
2212         return TRUE;
2213 }
2214
2215 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2216 {
2217         Scene *scene = CTX_data_scene(C);
2218         ToolSettings *ts = CTX_data_tool_settings(C);
2219         VPaint *wp = ts->wpaint;
2220         Brush *brush = BKE_paint_brush(&wp->paint);
2221         struct WPaintData *wpd = paint_stroke_mode_data(stroke);
2222         ViewContext *vc;
2223         Object *ob;
2224         Mesh *me;
2225         float mat[4][4];
2226         float paintweight;
2227         int *indexar;
2228         float totw;
2229         unsigned int index, totindex;
2230         float alpha;
2231         float mval[2];
2232         bool use_vert_sel;
2233         bool use_face_sel;
2234         bool use_depth;
2235
2236         MDeformWeight *(*dw_func)(MDeformVert *, const int) =
2237                 (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
2238                 ((wp->flag & VP_ONLYVGROUP) ?
2239                      (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index :
2240                       defvert_verify_index) : NULL;
2241
2242         const float pressure = RNA_float_get(itemptr, "pressure");
2243         const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
2244         const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
2245         const float brush_alpha_pressure = brush_alpha_value * (BKE_brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
2246
2247         /* intentionally don't initialize as NULL, make sure we initialize all members below */
2248         WeightPaintInfo wpi;
2249
2250         /* cannot paint if there is no stroke data */
2251         if (wpd == NULL) {
2252                 /* XXX: force a redraw here, since even though we can't paint,
2253                  * at least view won't freeze until stroke ends */
2254                 ED_region_tag_redraw(CTX_wm_region(C));
2255                 return;
2256         }
2257
2258         vc = &wpd->vc;
2259         ob = vc->obact;
2260         me = ob->data;
2261         indexar = wpd->indexar;
2262         
2263         view3d_operator_needs_opengl(C);
2264         ED_view3d_init_mats_rv3d(ob, vc->rv3d);
2265
2266         /* load projection matrix */
2267         mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
2268
2269         RNA_float_get_array(itemptr, "mouse", mval);
2270
2271         /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
2272         wpi.defbase_tot =        wpd->defbase_tot;
2273         wpi.defbase_sel = BKE_objdef_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel);
2274         if (wpi.defbase_tot_sel == 0 && ob->actdef > 0) {
2275                 wpi.defbase_tot_sel = 1;
2276         }
2277
2278         wpi.defbase_tot_unsel =  wpi.defbase_tot - wpi.defbase_tot_sel;
2279         wpi.vgroup_active =      wpd->vgroup_active;
2280         wpi.vgroup_mirror =      wpd->vgroup_mirror;
2281         wpi.lock_flags =         wpd->lock_flags;
2282         wpi.vgroup_validmap =    wpd->vgroup_validmap;
2283         wpi.do_flip =            RNA_boolean_get(itemptr, "pen_flip");
2284         wpi.do_multipaint =      (ts->multipaint != 0);
2285         wpi.do_auto_normalize =  ((ts->auto_normalize != 0) && (wpi.vgroup_validmap != NULL));
2286         wpi.brush_alpha_value =  brush_alpha_value;
2287         /* *** done setting up WeightPaintInfo *** */
2288
2289
2290
2291         swap_m4m4(wpd->vc.rv3d->persmat, mat);
2292
2293         use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
2294         use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
2295         use_depth = (vc->v3d->flag & V3D_ZBUF_SELECT);
2296
2297         /* which faces are involved */
2298         if (use_depth) {
2299                 if (wp->flag & VP_AREA) {
2300                         /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
2301                         me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
2302                         totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
2303                         me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
2304                 }
2305                 else {
2306                         indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
2307                         if (indexar[0]) totindex = 1;
2308                         else totindex = 0;
2309                 }
2310
2311                 if (use_face_sel && me->mpoly) {
2312                         for (index = 0; index < totindex; index++) {
2313                                 if (indexar[index] && indexar[index] <= me->totpoly) {
2314                                         MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
2315
2316                                         if ((mpoly->flag & ME_FACE_SEL) == 0) {
2317                                                 indexar[index] = 0;
2318                                         }
2319                                 }
2320                         }
2321                 }
2322         }
2323         else {
2324                 indexar = NULL;
2325         }
2326
2327         /* make sure each vertex gets treated only once */
2328         /* and calculate filter weight */
2329         totw = 0.0f;
2330         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR)
2331                 paintweight = 0.0f;
2332         else
2333                 paintweight = BKE_brush_weight_get(scene, brush);
2334
2335 #define WP_BLUR_ACCUM(v_idx_var)  \
2336         { \
2337                 const unsigned int vidx = v_idx_var; \
2338                 const float fac = calc_vp_strength_col_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure, NULL); \
2339                 if (fac > 0.0f) { \
2340                         MDeformWeight *dw = dw_func(&me->dvert[vidx], wpi.vgroup_active); \
2341                         paintweight += dw ? (dw->weight * fac) : 0.0f; \
2342                         totw += fac; \
2343                 } \
2344         } (void)0
2345
2346
2347         if (use_depth) {
2348                 for (index = 0; index < totindex; index++) {
2349                         if (indexar[index] && indexar[index] <= me->totpoly) {
2350                                 MPoly *mpoly = me->mpoly + (indexar[index] - 1);
2351                                 MLoop *ml = me->mloop + mpoly->loopstart;
2352                                 int i;
2353
2354                                 if (use_vert_sel) {
2355                                         for (i = 0; i < mpoly->totloop; i++, ml++) {
2356                                                 me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
2357                                         }
2358                                 }
2359                                 else {
2360                                         for (i = 0; i < mpoly->totloop; i++, ml++) {
2361                                                 me->dvert[ml->v].flag = 1;
2362                                         }
2363                                 }
2364
2365                                 if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2366                                         ml = me->mloop + mpoly->loopstart;
2367                                         for (i = 0; i < mpoly->totloop; i++, ml++) {
2368                                                 WP_BLUR_ACCUM(ml->v);
2369                                         }
2370                                 }
2371                         }
2372                 }
2373         }
2374         else {
2375                 const unsigned int totvert = me->totvert;
2376                 unsigned int       i;
2377
2378                 /* in the case of face selection we need to flush */
2379                 if (use_vert_sel || use_face_sel) {
2380                         for (i = 0; i < totvert; i++) {
2381                                 me->dvert[i].flag = me->mvert[i].flag & SELECT;
2382                         }
2383                 }
2384                 else {
2385                         for (i = 0; i < totvert; i++) {
2386                                 me->dvert[i].flag = SELECT;
2387                         }
2388                 }
2389
2390                 if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2391                         for (i = 0; i < totvert; i++) {
2392                                 WP_BLUR_ACCUM(i);
2393                         }
2394                 }
2395         }
2396
2397 #undef WP_BLUR_ACCUM
2398
2399
2400         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2401                 paintweight /= totw;
2402         }
2403
2404 #define WP_PAINT(v_idx_var)  \
2405         { \
2406                 unsigned int vidx = v_idx_var; \
2407                 if (me->dvert[vidx].flag) { \
2408                         alpha = calc_vp_alpha_col_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \
2409                                                  mval, brush_size_pressure, brush_alpha_pressure, NULL); \
2410                         if (alpha) { \
2411                                 do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
2412                         } \
2413                         me->dvert[vidx].flag = 0; \
2414                 } \
2415         } (void)0
2416
2417         if (use_depth) {
2418                 for (index = 0; index < totindex; index++) {
2419
2420                         if (indexar[index] && indexar[index] <= me->totpoly) {
2421                                 MPoly *mpoly = me->mpoly + (indexar[index] - 1);
2422                                 MLoop *ml = me->mloop + mpoly->loopstart;
2423                                 int i;
2424
2425                                 for (i = 0; i < mpoly->totloop; i++, ml++) {
2426                                         WP_PAINT(ml->v);
2427                                 }
2428                         }
2429                 }
2430         }
2431         else {
2432                 const unsigned int totvert = me->totvert;
2433                 unsigned int       i;
2434
2435                 for (i = 0; i < totvert; i++) {
2436                         WP_PAINT(i);
2437                 }
2438         }
2439 #undef WP_PAINT
2440
2441
2442         /* *** free wpi members */
2443         MEM_freeN((void *)wpi.defbase_sel);
2444         /* *** done freeing wpi members */
2445
2446
2447         swap_m4m4(vc->rv3d->persmat, mat);
2448
2449         {
2450                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
2451                 ups->pressure_value = pressure;
2452         }
2453
2454         DAG_id_tag_update(ob->data, 0);
2455         ED_region_tag_redraw(vc->ar);
2456 }
2457
2458 static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
2459 {
2460         ToolSettings *ts = CTX_data_tool_settings(C);
2461         Object *ob = CTX_data_active_object(C);
2462         struct WPaintData *wpd = paint_stroke_mode_data(stroke);
2463         
2464         if (wpd) {
2465                 if (wpd->vertexcosnos)
2466                         MEM_freeN(wpd->vertexcosnos);
2467                 MEM_freeN(wpd->indexar);
2468                 
2469                 if (wpd->vgroup_validmap)
2470                         MEM_freeN((void *)wpd->vgroup_validmap);
2471                 if (wpd->lock_flags)
2472                         MEM_freeN((void *)wpd->lock_flags);
2473
2474                 MEM_freeN(wpd);
2475         }
2476         
2477         /* frees prev buffer */
2478         copy_wpaint_prev(ts->wpaint, NULL, 0);
2479         
2480         /* and particles too */
2481         if (ob->particlesystem.first) {
2482                 ParticleSystem *psys;
2483                 int i;
2484                 
2485                 for (psys = ob->particlesystem.first; psys; psys = psys->next) {
2486                         for (i = 0; i < PSYS_TOT_VG; i++) {
2487                                 if (psys->vgroup[i] == ob->actdef) {
2488                                         psys->recalc |= PSYS_RECALC_RESET;
2489                                         break;
2490                                 }
2491                         }
2492                 }
2493         }
2494
2495         {
2496                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
2497                 ups->draw_pressure = false;
2498         }
2499
2500         DAG_id_tag_update(ob->data, 0);
2501
2502         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
2503 }
2504
2505
2506 static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
2507 {
2508         int retval;
2509
2510         op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
2511                                           wpaint_stroke_update_step,
2512                                           wpaint_stroke_done, event->type);
2513         
2514         /* add modal handler */
2515         WM_event_add_modal_handler(C, op);
2516
2517         retval = op->type->modal(C, op, event);
2518         OPERATOR_RETVAL_CHECK(retval);
2519         BLI_assert(retval == OPERATOR_RUNNING_MODAL);
2520         
2521         return OPERATOR_RUNNING_MODAL;
2522 }
2523
2524 static int wpaint_cancel(bContext *C, wmOperator *op)
2525 {
2526         paint_stroke_cancel(C, op);
2527
2528         return OPERATOR_CANCELLED;
2529 }
2530
2531 void PAINT_OT_weight_paint(wmOperatorType *ot)
2532 {
2533         
2534         /* identifiers */
2535         ot->name = "Weight Paint";
2536         ot->idname = "PAINT_OT_weight_paint";
2537         ot->description = "Paint a stroke in the current vertex group's weights";
2538         
2539         /* api callbacks */
2540         ot->invoke = wpaint_invoke;
2541         ot->modal = paint_stroke_modal;
2542         /* ot->exec = vpaint_exec; <-- needs stroke property */
2543         ot->poll = weight_paint_poll;
2544         ot->cancel = wpaint_cancel;
2545         
2546         /* flags */
2547         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
2548
2549         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
2550 }
2551
2552 static int weight_paint_set_exec(bContext *C, wmOperator *op)
2553 {
2554         struct Scene *scene = CTX_data_scene(C);
2555         Object *obact = CTX_data_active_object(C);
2556         ToolSettings *ts = CTX_data_tool_settings(C);
2557         Brush *brush = BKE_paint_brush(&ts->wpaint->paint);
2558         float vgroup_weight = BKE_brush_weight_get(scene, brush);
2559
2560         if (wpaint_ensure_data(C, op) == FALSE) {
2561                 return OPERATOR_CANCELLED;
2562         }
2563
2564         wpaint_fill(scene->toolsettings->wpaint, obact, vgroup_weight);
2565         ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
2566         return OPERATOR_FINISHED;
2567 }
2568
2569 void PAINT_OT_weight_set(wmOperatorType *ot)
2570 {
2571         /* identifiers */
2572         ot->name = "Set Weight";
2573         ot->idname = "PAINT_OT_weight_set";
2574         ot->description = "Fill the active vertex group with the current paint weight";
2575
2576         /* api callbacks */
2577         ot->exec = weight_paint_set_exec;
2578         ot->poll = mask_paint_poll; /* it was facemask_paint_poll */
2579
2580         /* flags */
2581         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2582 }
2583
2584 /* ************ set / clear vertex paint mode ********** */
2585
2586
2587 static int set_vpaint(bContext *C, wmOperator *op)  /* toggle */
2588 {       
2589         Object *ob = CTX_data_active_object(C);
2590         Scene *scene = CTX_data_scene(C);
2591         VPaint *vp = scene->toolsettings->vpaint;
2592         Mesh *me;
2593         
2594         me = BKE_mesh_from_object(ob);
2595         
2596         if (me == NULL || BKE_object_obdata_is_libdata(ob)) {
2597                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2598                 return OPERATOR_PASS_THROUGH;
2599         }
2600         
2601         if (me && me->mloopcol == NULL) {
2602                 make_vertexcol(ob);
2603         }
2604         
2605         /* toggle: end vpaint */
2606         if (ob->mode & OB_MODE_VERTEX_PAINT) {
2607                 
2608                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2609
2610                 if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
2611                         BKE_mesh_flush_select_from_polys(me);
2612                 }
2613         }
2614         else {
2615                 ob->mode |= OB_MODE_VERTEX_PAINT;
2616                 /* Turn off weight painting */
2617                 if (ob->mode & OB_MODE_WEIGHT_PAINT)
2618                         set_wpaint(C, op);
2619                 
2620                 if (vp == NULL)
2621                         vp = scene->toolsettings->vpaint = new_vpaint(0);
2622                 
2623                 paint_cursor_start(C, vertex_paint_poll);
2624
2625                 BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
2626         }
2627         
2628         /* update modifier stack for mapping requirements */
2629         DAG_id_tag_update(&me->id, 0);
2630         
2631         WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
2632         
2633         return OPERATOR_FINISHED;
2634 }
2635
2636 void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
2637 {
2638         
2639         /* identifiers */
2640         ot->name = "Vertex Paint Mode";
2641         ot->idname = "PAINT_OT_vertex_paint_toggle";
2642         ot->description = "Toggle the vertex paint mode in 3D view";
2643         
2644         /* api callbacks */
2645         ot->exec = set_vpaint;
2646         ot->poll = paint_poll_test;
2647         
2648         /* flags */
2649         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2650 }
2651
2652
2653
2654 /* ********************** vertex paint operator ******************* */
2655
2656 /* Implementation notes:
2657  *
2658  * Operator->invoke()
2659  * - validate context (add mcol)
2660  * - create customdata storage
2661  * - call paint once (mouse click)
2662  * - add modal handler 
2663  *
2664  * Operator->modal()
2665  * - for every mousemove, apply vertex paint
2666  * - exit on mouse release, free customdata
2667  *   (return OPERATOR_FINISHED also removes handler and operator)
2668  *
2669  * For future:
2670  * - implement a stroke event (or mousemove with past positons)
2671  * - revise whether op->customdata should be added in object, in set_vpaint
2672  */
2673
2674 typedef struct PolyFaceMap {
2675         struct PolyFaceMap *next, *prev;
2676         int facenr;
2677 } PolyFaceMap;
2678
2679 typedef struct VPaintData {
2680         ViewContext vc;
2681         unsigned int paintcol;
2682         int *indexar;
2683         DMCoNo *vertexcosnos;
2684         float vpimat[3][3];
2685
2686         /* modify 'me->mcol' directly, since the derived mesh is drawing from this
2687          * array, otherwise we need to refresh the modifier stack */
2688         int use_fast_update;
2689
2690         /* mpoly -> mface mapping */
2691         MemArena *polyfacemap_arena;
2692         ListBase *polyfacemap;
2693
2694         /* loops tagged as having been painted, to apply shared vertex color
2695          * blending only to modified loops */
2696         bool *mlooptag;
2697         bool *mfacetag;
2698
2699         bool is_texbrush;
2700 } VPaintData;
2701
2702 static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
2703 {
2704         MFace *mf;
2705         PolyFaceMap *e;
2706         int *origIndex;
2707         int i;
2708
2709         vd->polyfacemap_arena = BLI_memarena_new(1 << 13, "vpaint tmp");
2710         BLI_memarena_use_calloc(vd->polyfacemap_arena);
2711
2712         vd->polyfacemap = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(ListBase) * me->totpoly);
2713
2714         origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
2715         mf = me->mface;
2716
2717         if (!origIndex)
2718                 return;
2719
2720         for (i = 0; i < me->totface; i++, mf++, origIndex++) {
2721                 if (*origIndex == ORIGINDEX_NONE)
2722                         continue;
2723
2724                 e = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(PolyFaceMap));
2725                 e->facenr = i;
2726                 
2727                 BLI_addtail(&vd->polyfacemap[*origIndex], e);
2728         }
2729 }
2730
2731 static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
2732 {
2733         ToolSettings *ts = CTX_data_tool_settings(C);
2734         struct PaintStroke *stroke = op->customdata;
2735         VPaint *vp = ts->vpaint;
2736         Brush *brush = BKE_paint_brush(&vp->paint);
2737         struct VPaintData *vpd;
2738         Object *ob = CTX_data_active_object(C);
2739         Mesh *me;
2740         float mat[4][4], imat[4][4];
2741
2742         /* context checks could be a poll() */
2743         me = BKE_mesh_from_object(ob);
2744         if (me == NULL || me->totpoly == 0)
2745                 return OPERATOR_PASS_THROUGH;
2746         
2747         if (me->mloopcol == NULL)
2748                 make_vertexcol(ob);
2749         if (me->mloopcol == NULL)
2750                 return OPERATOR_CANCELLED;
2751
2752         /* Update tessface data if needed
2753          * Added here too because e.g. switching to/from edit mode would remove tessface data,
2754          * yet "fast_update" could still be used! */
2755         update_tessface_data(ob, me);
2756
2757         /* make mode data storage */
2758         vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData");
2759         paint_stroke_set_mode_data(stroke, vpd);
2760         view3d_set_viewcontext(C, &vpd->vc);
2761         
2762         vpd->vertexcosnos = mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
2763         vpd->indexar = get_indexarray(me);
2764         vpd->paintcol = vpaint_get_current_col(vp);
2765
2766         vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
2767                            brush->mtex.tex;
2768
2769         /* are we painting onto a modified mesh?,
2770          * if not we can skip face map trickyness */
2771         if (vertex_paint_use_fast_update_check(ob)) {
2772                 vpaint_build_poly_facemap(vpd, me);
2773                 vpd->use_fast_update = TRUE;
2774 /*              printf("Fast update!\n");*/
2775         }
2776         else {
2777                 vpd->use_fast_update = FALSE;
2778 /*              printf("No fast update!\n");*/
2779         }
2780
2781         /* to keep tracked of modified loops for shared vertex color blending */
2782         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2783                 vpd->mlooptag = MEM_mallocN(sizeof(bool)*me->totloop, "VPaintData mlooptag");
2784                 if (vpd->use_fast_update)
2785                         vpd->mfacetag = MEM_mallocN(sizeof(bool)*me->totface*4, "VPaintData mfacetag");
2786         }
2787
2788         /* for filtering */
2789         copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop);
2790         
2791         /* some old cruft to sort out later */
2792         mult_m4_m4m4(mat, vpd->vc.rv3d->viewmat, ob->obmat);
2793         invert_m4_m4(imat, mat);
2794         copy_m3_m4(vpd->vpimat, imat);
2795
2796         {
2797                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
2798                 ups->draw_pressure = true;
2799         }
2800
2801         return 1;
2802 }
2803
2804 static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
2805                               const unsigned int index, const float mval[2],
2806                               const float brush_size_pressure, const float brush_alpha_pressure)
2807 {
2808         ViewContext *vc = &vpd->vc;
2809         Brush *brush = BKE_paint_brush(&vp->paint);
2810         MPoly *mpoly = &me->mpoly[index];
2811         MFace *mf;
2812         MCol *mc;
2813         MLoop *ml;
2814         MLoopCol *mlc;
2815         PolyFaceMap *e;
2816         unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart;
2817         unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart;
2818         bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL;
2819         bool *mftag;
2820         float alpha;
2821         int i, j;
2822         int totloop = mpoly->totloop;
2823
2824         int brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f);
2825
2826         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2827                 unsigned int blend[4] = {0};
2828                 unsigned int tcol;
2829                 char *col;
2830
2831                 for (j = 0; j < totloop; j++) {
2832                         col = (char *)(lcol + j);
2833                         blend[0] += col[0];
2834                         blend[1] += col[1];
2835                         blend[2] += col[2];
2836                         blend[3] += col[3];
2837                 }
2838
2839                 blend[0] = divide_round_i(blend[0], totloop);
2840                 blend[1] = divide_round_i(blend[1], totloop);
2841                 blend[2] = divide_round_i(blend[2], totloop);
2842                 blend[3] = divide_round_i(blend[3], totloop);
2843                 col = (char *)&tcol;
2844                 col[0] = blend[0];
2845                 col[1] = blend[1];
2846                 col[2] = blend[2];
2847                 col[3] = blend[3];
2848
2849                 vpd->paintcol = *((unsigned int *)col);
2850         }
2851
2852         ml = me->mloop + mpoly->loopstart;
2853         for (i = 0; i < totloop; i++, ml++) {
2854                 float rgba[4];
2855                 unsigned int paintcol;
2856                 alpha = calc_vp_alpha_col_dl(vp, vc, vpd->vpimat,
2857                                          &vpd->vertexcosnos[ml->v], mval,
2858                                          brush_size_pressure, brush_alpha_pressure, rgba);
2859
2860                 if (vpd->is_texbrush) {
2861                         float rgba_br[3];
2862                         rgb_uchar_to_float(rgba_br, (const unsigned char *)&vpd->paintcol);
2863                         mul_v3_v3(rgba_br, rgba);
2864                         rgb_float_to_uchar((unsigned char *)&paintcol, rgba_br);
2865                 }
2866                 else
2867                         paintcol = vpd->paintcol;
2868
2869                 if (alpha > 0.0f) {
2870                         const int alpha_i = (int)(alpha * 255.0f);
2871                         lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], paintcol, alpha_i, brush_alpha_pressure_i);
2872
2873                         if (mlooptag) mlooptag[i] = 1;
2874                 }
2875         }
2876
2877         if (vpd->use_fast_update) {
2878                 /* update vertex colors for tessellations incrementally,
2879                  * rather then regenerating the tessellation altogether */
2880                 for (e = vpd->polyfacemap[index].first; e; e = e->next) {
2881                         mf = &me->mface[e->facenr];
2882                         mc = &me->mcol[e->facenr * 4];
2883                         mftag = &vpd->mfacetag[e->facenr * 4];
2884
2885                         ml = me->mloop + mpoly->loopstart;
2886                         mlc = me->mloopcol + mpoly->loopstart;
2887                         for (j = 0; j < totloop; j++, ml++, mlc++) {
2888                                 if (ml->v == mf->v1) {
2889                                         MESH_MLOOPCOL_TO_MCOL(mlc, mc + 0);
2890                                         if (mlooptag) mftag[0] = mlooptag[j];
2891                                 }
2892                                 else if (ml->v == mf->v2) {
2893                                         MESH_MLOOPCOL_TO_MCOL(mlc, mc + 1);
2894                                         if (mlooptag) mftag[1] = mlooptag[j];
2895                                 }
2896                                 else if (ml->v == mf->v3) {
2897                                         MESH_MLOOPCOL_TO_MCOL(mlc, mc + 2);
2898                                         if (mlooptag) mftag[2] = mlooptag[j];
2899                                 }
2900                                 else if (mf->v4 && ml->v == mf->v4) {
2901                                         MESH_MLOOPCOL_TO_MCOL(mlc, mc + 3);
2902                                         if (mlooptag) mftag[3] = mlooptag[j];
2903                                 }
2904                         }
2905                 }
2906         }
2907
2908 }
2909
2910 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2911 {
2912         Scene *scene = CTX_data_scene(C);
2913         ToolSettings *ts = CTX_data_tool_settings(C);
2914         struct VPaintData *vpd = paint_stroke_mode_data(stroke);
2915         VPaint *vp = ts->vpaint;
2916         Brush *brush = BKE_paint_brush(&vp->paint);
2917         ViewContext *vc = &vpd->vc;
2918         Object *ob = vc->obact;
2919         Mesh *me = ob->data;
2920         float mat[4][4];
2921         int *indexar = vpd->indexar;
2922         int totindex, index;
2923         float mval[2];
2924
2925         const float pressure = RNA_float_get(itemptr, "pressure");
2926         const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
2927         const float brush_alpha_pressure = BKE_brush_alpha_get(scene, brush) * (BKE_brush_use_alpha_pressure(scene, brush) ? pressure : 1.0f);
2928
2929         RNA_float_get_array(itemptr, "mouse", mval);
2930
2931         view3d_operator_needs_opengl(C);
2932         ED_view3d_init_mats_rv3d(ob, vc->rv3d);
2933
2934         /* load projection matrix */
2935         mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
2936
2937         /* which faces are involved */
2938         if (vp->flag & VP_AREA) {
2939                 totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
2940         }
2941         else {
2942                 indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
2943                 if (indexar[0]) totindex = 1;
2944                 else totindex = 0;
2945         }
2946
2947         if ((me->editflag & ME_EDIT_PAINT_FACE_SEL) && me->mpoly) {
2948                 for (index = 0; index < totindex; index++) {
2949                         if (indexar[index] && indexar[index] <= me->totpoly) {
2950                                 MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
2951                                                 
2952                                 if ((mpoly->flag & ME_FACE_SEL) == 0)
2953                                         indexar[index] = 0;
2954                         }
2955                 }
2956         }
2957         
2958         swap_m4m4(vc->rv3d->persmat, mat);
2959
2960         /* clear modified tag for blur tool */
2961         if(vpd->mlooptag)
2962                 memset(vpd->mlooptag, 0, sizeof(bool)*me->totloop);
2963         if (vpd->mfacetag)
2964                 memset(vpd->mfacetag, 0, sizeof(bool)*me->totface*4);
2965
2966         for (index = 0; index < totindex; index++) {
2967                 if (indexar[index] && indexar[index] <= me->totpoly) {
2968                         vpaint_paint_poly(vp, vpd, me, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure);
2969                 }
2970         }
2971                 
2972         swap_m4m4(vc->rv3d->persmat, mat);
2973
2974         /* was disabled because it is slow, but necessary for blur */
2975         if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
2976                 int do_tessface = vpd->use_fast_update;
2977                 do_shared_vertexcol(me, vpd->mlooptag, vpd->mfacetag, do_tessface);
2978         }
2979
2980         {
2981                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
2982                 ups->pressure_value = pressure;
2983         }
2984
2985         ED_region_tag_redraw(vc->ar);
2986
2987         if (vpd->use_fast_update == FALSE) {
2988                 /* recalculate modifier stack to get new colors, slow,
2989                  * avoid this if we can! */
2990                 DAG_id_tag_update(ob->data, 0);
2991         }
2992         else if (!GPU_buffer_legacy(ob->derivedFinal)) {
2993                 /* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */
2994                 ob->derivedFinal->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW;
2995         }
2996 }
2997
2998 static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
2999 {
3000         ToolSettings *ts = CTX_data_tool_settings(C);
3001         struct VPaintData *vpd = paint_stroke_mode_data(stroke);
3002         ViewContext *vc = &vpd->vc;
3003         Object *ob = vc->obact;
3004         
3005         if (vpd->vertexcosnos)
3006                 MEM_freeN(vpd->vertexcosnos);
3007         MEM_freeN(vpd->indexar);
3008         
3009         /* frees prev buffer */
3010         copy_vpaint_prev(ts->vpaint, NULL, 0);
3011
3012         if (vpd->polyfacemap_arena) {
3013                 BLI_memarena_free(vpd->polyfacemap_arena);
3014         }
3015
3016         if (vpd->mlooptag)
3017                 MEM_freeN(vpd->mlooptag);
3018
3019         if (vpd->mfacetag)
3020                 MEM_freeN(vpd->mfacetag);
3021
3022         {
3023                 UnifiedPaintSettings *ups = &ts->unified_paint_settings;
3024                 ups->draw_pressure = false;
3025         }
3026
3027         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
3028
3029         MEM_freeN(vpd);
3030 }
3031
3032 static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
3033 {
3034         int retval;
3035
3036         op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
3037                                           vpaint_stroke_update_step,
3038                                           vpaint_stroke_done, event->type);
3039         
3040         /* add modal handler */