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