Vertex/Weight Paint now uses the regular global Undo.
[blender.git] / source / blender / src / vpaint.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <math.h>
34 #include <string.h>
35
36 #ifdef WIN32
37 #include <io.h>
38 #else
39 #include <unistd.h>
40 #endif   
41
42 #include "MEM_guardedalloc.h"
43
44 #include "IMB_imbuf.h"
45 #include "IMB_imbuf_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49 #include "MTC_matrixops.h"
50
51 #include "DNA_action_types.h"
52 #include "DNA_armature_types.h"
53 #include "DNA_brush_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_modifier_types.h"
57 #include "DNA_object_types.h"
58 #include "DNA_object_force.h"
59 #include "DNA_screen_types.h"
60 #include "DNA_space_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_userdef_types.h"
64
65 #include "BKE_armature.h"
66 #include "BKE_DerivedMesh.h"
67 #include "BKE_customdata.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_deform.h"
70 #include "BKE_displist.h"
71 #include "BKE_global.h"
72 #include "BKE_mesh.h"
73 #include "BKE_modifier.h"
74 #include "BKE_object.h"
75 #include "BKE_utildefines.h"
76
77 #include "BIF_editview.h"
78 #include "BIF_graphics.h"
79 #include "BIF_glutil.h"
80 #include "BIF_gl.h"
81 #include "BIF_interface.h"
82 #include "BIF_meshtools.h"
83 #include "BIF_mywindow.h"
84 #include "BIF_space.h"
85 #include "BIF_screen.h"
86 #include "BIF_toolbox.h"
87
88 #include "BDR_vpaint.h"
89
90 #include "BSE_drawview.h"
91 #include "BSE_trans_types.h"
92 #include "BSE_view.h"
93
94 #include "mydevice.h"
95 #include "blendef.h"
96
97 #include "BIF_editdeform.h"
98
99         /* Gvp.mode */
100 #define VP_MIX  0
101 #define VP_ADD  1
102 #define VP_SUB  2
103 #define VP_MUL  3
104 #define VP_FILT 4
105 #define VP_LIGHTEN      5
106 #define VP_DARKEN       6
107
108 #define MAXINDEX        512000
109
110 VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY, NULL};
111 VPaint Gwp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT, NULL};
112
113 static int *get_indexarray(void)
114 {
115         return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint");
116 }
117
118 void free_vertexpaint()
119 {
120         
121         if(Gvp.vpaint_prev) MEM_freeN(Gvp.vpaint_prev);
122         Gvp.vpaint_prev= NULL;
123         
124         mesh_octree_table(NULL, NULL, 'e');
125 }
126
127 /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! 
128    so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
129
130 unsigned int rgba_to_mcol(float r, float g, float b, float a)
131 {
132         int ir, ig, ib, ia;
133         unsigned int col;
134         char *cp;
135         
136         ir= floor(255.0*r);
137         if(ir<0) ir= 0; else if(ir>255) ir= 255;
138         ig= floor(255.0*g);
139         if(ig<0) ig= 0; else if(ig>255) ig= 255;
140         ib= floor(255.0*b);
141         if(ib<0) ib= 0; else if(ib>255) ib= 255;
142         ia= floor(255.0*a);
143         if(ia<0) ia= 0; else if(ia>255) ia= 255;
144         
145         cp= (char *)&col;
146         cp[0]= ia;
147         cp[1]= ib;
148         cp[2]= ig;
149         cp[3]= ir;
150         
151         return col;
152         
153 }
154
155 static unsigned int vpaint_get_current_col(VPaint *vp)
156 {
157         return rgba_to_mcol(vp->r, vp->g, vp->b, 1.0f);
158 }
159
160 void do_shared_vertexcol(Mesh *me)
161 {
162         /* if no mcol: do not do */
163         /* if tface: only the involved faces, otherwise all */
164         MFace *mface;
165         MTFace *tface;
166         int a;
167         short *scolmain, *scol;
168         char *mcol;
169         
170         if(me->mcol==0 || me->totvert==0 || me->totface==0) return;
171         
172         scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
173         
174         tface= me->mtface;
175         mface= me->mface;
176         mcol= (char *)me->mcol;
177         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
178                 if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
179                         scol= scolmain+4*mface->v1;
180                         scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
181                         scol= scolmain+4*mface->v2;
182                         scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
183                         scol= scolmain+4*mface->v3;
184                         scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
185                         if(mface->v4) {
186                                 scol= scolmain+4*mface->v4;
187                                 scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
188                         }
189                 }
190                 if(tface) tface++;
191         }
192         
193         a= me->totvert;
194         scol= scolmain;
195         while(a--) {
196                 if(scol[0]>1) {
197                         scol[1]/= scol[0];
198                         scol[2]/= scol[0];
199                         scol[3]/= scol[0];
200                 }
201                 scol+= 4;
202         }
203         
204         tface= me->mtface;
205         mface= me->mface;
206         mcol= (char *)me->mcol;
207         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
208                 if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
209                         scol= scolmain+4*mface->v1;
210                         mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
211                         scol= scolmain+4*mface->v2;
212                         mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
213                         scol= scolmain+4*mface->v3;
214                         mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
215                         if(mface->v4) {
216                                 scol= scolmain+4*mface->v4;
217                                 mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
218                         }
219                 }
220                 if(tface) tface++;
221         }
222
223         MEM_freeN(scolmain);
224 }
225
226 void make_vertexcol(int shade)  /* single ob */
227 {
228         Object *ob;
229         Mesh *me;
230
231         if(G.obedit) {
232                 error("Unable to perform function in Edit Mode");
233                 return;
234         }
235         
236         ob= OBACT;
237         if(!ob || ob->id.lib) return;
238         me= get_mesh(ob);
239         if(me==0) return;
240
241         /* copies from shadedisplist to mcol */
242         if(me->mcol == NULL)
243                 me->mcol = CustomData_add_layer(&me->fdata, CD_MCOL, 0, NULL, me->totface);
244
245         if(shade)
246                 shadeMeshMCol(ob, me);
247         else
248                 memset(me->mcol, 255, sizeof(MCol)*me->totface);
249
250         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
251         
252         allqueue(REDRAWBUTSEDIT, 0);
253         allqueue(REDRAWVIEW3D, 0);
254 }
255
256 static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
257 {
258         if(vp->vpaint_prev) {
259                 MEM_freeN(vp->vpaint_prev);
260                 vp->vpaint_prev= NULL;
261         }
262         vp->tot= tot;   
263         
264         if(mcol==NULL || tot==0) return;
265         
266         vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
267         memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
268         
269 }
270
271 void clear_vpaint()
272 {
273         Mesh *me;
274         Object *ob;
275         unsigned int *to, paintcol;
276         int a;
277         
278         if((G.f & G_VERTEXPAINT)==0) return;
279
280         ob= OBACT;
281         me= get_mesh(ob);
282         if(!ob || ob->id.lib) return;
283
284         if(me==0 || me->mcol==0 || me->totface==0) return;
285
286         paintcol= vpaint_get_current_col(&Gvp);
287
288         to= (unsigned int *)me->mcol;
289         a= 4*me->totface;
290         while(a--) {
291                 *to= paintcol;
292                 to++; 
293         }
294         BIF_undo_push("Clear vertex colors");
295         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
296         
297         allqueue(REDRAWVIEW3D, 0);
298 }
299
300 void clear_vpaint_selectedfaces()
301 {
302         Mesh *me;
303         MTFace *tf;
304         Object *ob;
305         unsigned int paintcol, *mcol;
306         int i;
307
308         ob= OBACT;
309         me= get_mesh(ob);
310         if(me==0 || me->mtface==0 || me->totface==0) return;
311
312         if(!me->mcol)
313                 make_vertexcol(0);
314
315         paintcol= vpaint_get_current_col(&Gvp);
316
317         tf = me->mtface;
318         mcol = (unsigned int*)me->mcol;
319         for (i = 0; i < me->totface; i++, tf++, mcol+=4) {
320                 if (tf->flag & TF_SELECT) {
321                         mcol[0] = paintcol;
322                         mcol[1] = paintcol;
323                         mcol[2] = paintcol;
324                         mcol[3] = paintcol;
325                 }
326         }
327         
328         BIF_undo_push("Clear vertex colors");
329         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
330         allqueue(REDRAWVIEW3D, 0);
331 }
332
333
334 /* fills in the selected faces with the current weight and vertex group */
335 void clear_wpaint_selectedfaces()
336 {
337         extern float editbutvweight;
338         float paintweight= editbutvweight;
339         Mesh *me;
340         MTFace *tface;
341         MFace *mface;
342         Object *ob;
343         MDeformWeight *dw, *uw;
344         int *indexar;
345         int index, vgroup;
346         unsigned int faceverts[5]={0,0,0,0,0};
347         unsigned char i;
348         int vgroup_mirror= -1;
349         
350         ob= OBACT;
351         me= ob->data;
352         if(me==0 || me->totface==0 || me->dvert==0 || !me->mtface) return;
353         
354         indexar= get_indexarray();
355         for(index=0, tface=me->mtface; index<me->totface; index++, tface++) {
356                 if((tface->flag & TF_SELECT)==0)
357                         indexar[index]= 0;
358                 else
359                         indexar[index]= index+1;
360         }
361         
362         vgroup= ob->actdef-1;
363         
364         /* directly copied from weight_paint, should probaby split into a seperate function */
365         /* if mirror painting, find the other group */          
366         if(Gwp.flag & VP_MIRROR_X) {
367                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
368                 if(defgroup) {
369                         bDeformGroup *curdef;
370                         int actdef= 0;
371                         char name[32];
372
373                         BLI_strncpy(name, defgroup->name, 32);
374                         bone_flip_name(name, 0);                /* 0 = don't strip off number extensions */
375                         
376                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
377                                 if (!strcmp(curdef->name, name))
378                                         break;
379                         if(curdef==NULL) {
380                                 int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
381                                 curdef= add_defgroup_name (ob, name);
382                                 ob->actdef= olddef;
383                         }
384                         
385                         if(curdef && curdef!=defgroup)
386                                 vgroup_mirror= actdef;
387                 }
388         }
389         /* end copy from weight_paint*/
390         
391         
392         for(index=0; index<me->totface; index++) {
393                 if(indexar[index] && indexar[index]<=me->totface) {
394                         mface= me->mface + (indexar[index]-1);
395                         /* just so we can loop through the verts */
396                         faceverts[0]= mface->v1;
397                         faceverts[1]= mface->v2;
398                         faceverts[2]= mface->v3;
399                         faceverts[3]= mface->v4;
400                         for (i=0; i<3 || faceverts[i]; i++) {
401                                 if(!((me->dvert+faceverts[i])->flag)) {
402                                         dw= verify_defweight(me->dvert+faceverts[i], vgroup);
403                                         if(dw) {
404                                                 uw= verify_defweight(Gwp.wpaint_prev+faceverts[i], vgroup);
405                                                 uw->weight= dw->weight; /* set the undio weight */
406                                                 dw->weight= paintweight;
407                                                 
408                                                 if(Gwp.flag & VP_MIRROR_X) {    /* x mirror painting */
409                                                         int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
410                                                         if(j>=0) {
411                                                                 /* copy, not paint again */
412                                                                 if(vgroup_mirror != -1) {
413                                                                         dw= verify_defweight(me->dvert+j, vgroup_mirror);
414                                                                         uw= verify_defweight(Gwp.wpaint_prev+j, vgroup_mirror);
415                                                                 } else {
416                                                                         dw= verify_defweight(me->dvert+j, vgroup);
417                                                                         uw= verify_defweight(Gwp.wpaint_prev+j, vgroup);
418                                                                 }
419                                                                 uw->weight= dw->weight; /* set the undo weight */
420                                                                 dw->weight= paintweight;
421                                                         }
422                                                 }
423                                         }
424                                         (me->dvert+faceverts[i])->flag= 1;
425                                 }
426                         }
427                 }
428         }
429         
430         index=0;
431         while (index<me->totvert) {
432                 (me->dvert+index)->flag= 0;
433                 index++;
434         }
435         
436         MEM_freeN(indexar);
437
438         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
439         BIF_undo_push("Set vertex weight");
440         allqueue(REDRAWVIEW3D, 0);
441 }
442
443
444 void vpaint_dogamma()
445 {
446         Mesh *me;
447         Object *ob;
448         float igam, fac;
449         int a, temp;
450         char *cp, gamtab[256];
451
452         if((G.f & G_VERTEXPAINT)==0) return;
453
454         ob= OBACT;
455         me= get_mesh(ob);
456         if(me==0 || me->mcol==0 || me->totface==0) return;
457
458         igam= 1.0/Gvp.gamma;
459         for(a=0; a<256; a++) {
460                 
461                 fac= ((float)a)/255.0;
462                 fac= Gvp.mul*pow( fac, igam);
463                 
464                 temp= 255.9*fac;
465                 
466                 if(temp<=0) gamtab[a]= 0;
467                 else if(temp>=255) gamtab[a]= 255;
468                 else gamtab[a]= temp;
469         }
470
471         a= 4*me->totface;
472         cp= (char *)me->mcol;
473         while(a--) {
474                 
475                 cp[1]= gamtab[ cp[1] ];
476                 cp[2]= gamtab[ cp[2] ];
477                 cp[3]= gamtab[ cp[3] ];
478                 
479                 cp+= 4;
480         }
481         allqueue(REDRAWVIEW3D, 0);
482 }
483
484 /* used for both 3d view and image window */
485 void sample_vpaint()    /* frontbuf */
486 {
487         unsigned int col;
488         int x, y;
489         short mval[2];
490         char *cp;
491         
492         getmouseco_areawin(mval);
493         x= mval[0]; y= mval[1];
494         
495         if(x<0 || y<0) return;
496         if(x>=curarea->winx || y>=curarea->winy) return;
497         
498         x+= curarea->winrct.xmin;
499         y+= curarea->winrct.ymin;
500         
501         glReadBuffer(GL_FRONT);
502         glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
503         glReadBuffer(GL_BACK);
504
505         cp = (char *)&col;
506         
507         if(G.f & (G_VERTEXPAINT|G_WEIGHTPAINT)) {
508                 Gvp.r= cp[0]/255.0f;
509                 Gvp.g= cp[1]/255.0f;
510                 Gvp.b= cp[2]/255.0f;
511         }
512         else {
513                 Brush *brush= G.scene->toolsettings->imapaint.brush;
514
515                 if(brush) {
516                         brush->rgb[0]= cp[0]/255.0f;
517                         brush->rgb[1]= cp[1]/255.0f;
518                         brush->rgb[2]= cp[2]/255.0f;
519
520                         allqueue(REDRAWVIEW3D, 0);
521                         allqueue(REDRAWIMAGE, 0);
522                 }
523         }
524
525         allqueue(REDRAWBUTSEDIT, 0);
526         addqueue(curarea->win, REDRAW, 1); /* needed for when panel is open... */
527 }
528
529 static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
530 {
531         char *cp1, *cp2, *cp;
532         int mfac;
533         unsigned int col=0;
534         
535         if(fac==0) return col1;
536         if(fac>=255) return col2;
537
538         mfac= 255-fac;
539         
540         cp1= (char *)&col1;
541         cp2= (char *)&col2;
542         cp=  (char *)&col;
543         
544         cp[0]= 255;
545         cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8;
546         cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8;
547         cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8;
548         
549         return col;
550 }
551
552 static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
553 {
554         char *cp1, *cp2, *cp;
555         int temp;
556         unsigned int col=0;
557         
558         if(fac==0) return col1;
559         
560         cp1= (char *)&col1;
561         cp2= (char *)&col2;
562         cp=  (char *)&col;
563         
564         cp[0]= 255;
565         temp= cp1[1] + ((fac*cp2[1])>>8);
566         if(temp>254) cp[1]= 255; else cp[1]= temp;
567         temp= cp1[2] + ((fac*cp2[2])>>8);
568         if(temp>254) cp[2]= 255; else cp[2]= temp;
569         temp= cp1[3] + ((fac*cp2[3])>>8);
570         if(temp>254) cp[3]= 255; else cp[3]= temp;
571         
572         return col;
573 }
574
575 static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
576 {
577         char *cp1, *cp2, *cp;
578         int temp;
579         unsigned int col=0;
580         
581         if(fac==0) return col1;
582         
583         cp1= (char *)&col1;
584         cp2= (char *)&col2;
585         cp=  (char *)&col;
586         
587         cp[0]= 255;
588         temp= cp1[1] - ((fac*cp2[1])>>8);
589         if(temp<0) cp[1]= 0; else cp[1]= temp;
590         temp= cp1[2] - ((fac*cp2[2])>>8);
591         if(temp<0) cp[2]= 0; else cp[2]= temp;
592         temp= cp1[3] - ((fac*cp2[3])>>8);
593         if(temp<0) cp[3]= 0; else cp[3]= temp;
594         
595         return col;
596 }
597
598 static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
599 {
600         char *cp1, *cp2, *cp;
601         int mfac;
602         unsigned int col=0;
603         
604         if(fac==0) return col1;
605
606         mfac= 255-fac;
607         
608         cp1= (char *)&col1;
609         cp2= (char *)&col2;
610         cp=  (char *)&col;
611         
612         /* first mul, then blend the fac */
613         cp[0]= 255;
614         cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])>>8)  )>>8;
615         cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])>>8)  )>>8;
616         cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])>>8)  )>>8;
617
618         
619         return col;
620 }
621
622 static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
623 {
624         char *cp1, *cp2, *cp;
625         int mfac;
626         unsigned int col=0;
627         
628         if(fac==0) return col1;
629         if(fac>=255) return col2;
630
631         mfac= 255-fac;
632         
633         cp1= (char *)&col1;
634         cp2= (char *)&col2;
635         cp=  (char *)&col;
636         
637         /* See if are lighter, if so mix, else dont do anything.
638         if the paint col is darker then the original, then ignore */
639         if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
640                 return col1;
641         
642         cp[0]= 255;
643         cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8;
644         cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8;
645         cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8;
646         
647         return col;
648 }
649
650 static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
651 {
652         char *cp1, *cp2, *cp;
653         int mfac;
654         unsigned int col=0;
655         
656         if(fac==0) return col1;
657         if(fac>=255) return col2;
658
659         mfac= 255-fac;
660         
661         cp1= (char *)&col1;
662         cp2= (char *)&col2;
663         cp=  (char *)&col;
664         
665         /* See if were darker, if so mix, else dont do anything.
666         if the paint col is brighter then the original, then ignore */
667         if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
668                 return col1;
669         
670         cp[0]= 255;
671         cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8;
672         cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8;
673         cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8;
674         return col;
675 }
676
677 static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
678 {
679
680         if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) *col= mcol_blend( *col, paintcol, alpha);
681         else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
682         else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
683         else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
684         else if(Gvp.mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
685         else if(Gvp.mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
686         
687         /* if no spray, clip color adding with colorig & orig alpha */
688         if((Gvp.flag & VP_SPRAY)==0) {
689                 unsigned int testcol=0, a;
690                 char *cp, *ct, *co;
691                 
692                 alpha= (int)(255.0*Gvp.a);
693                 
694                 if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) testcol= mcol_blend( *colorig, paintcol, alpha);
695                 else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
696                 else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
697                 else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
698                 else if(Gvp.mode==VP_LIGHTEN)  testcol= mcol_lighten( *colorig, paintcol, alpha);
699                 else if(Gvp.mode==VP_DARKEN)   testcol= mcol_darken( *colorig, paintcol, alpha);
700                 
701                 cp= (char *)col;
702                 ct= (char *)&testcol;
703                 co= (char *)colorig;
704                 
705                 for(a=0; a<4; a++) {
706                         if( ct[a]<co[a] ) {
707                                 if( cp[a]<ct[a] ) cp[a]= ct[a];
708                                 else if( cp[a]>co[a] ) cp[a]= co[a];
709                         }
710                         else {
711                                 if( cp[a]<co[a] ) cp[a]= co[a];
712                                 else if( cp[a]>ct[a] ) cp[a]= ct[a];
713                         }
714                 }
715         }
716 }
717
718
719 static int sample_backbuf_area(VPaint *vp, int *indexar, int x, int y, float size)
720 {
721         unsigned int *rt;
722         struct ImBuf *ibuf;
723         int x1, y1, x2, y2, a, tot=0, index;
724         
725         if(vp->tot>=MAXINDEX) return 0;
726         
727         if(size>64.0) size= 64.0;
728         
729         x1= x-size;
730         x2= x+size;
731         CLAMP(x1, 0, curarea->winx-1);
732         CLAMP(x2, 0, curarea->winx-1);
733         y1= y-size;
734         y2= y+size;
735         CLAMP(y1, 0, curarea->winy-1);
736         CLAMP(y2, 0, curarea->winy-1);
737 #ifdef __APPLE__
738         glReadBuffer(GL_AUX0);
739 #endif
740         
741         if(x1>=x2 || y1>=y2) return 0;
742         
743         ibuf = IMB_allocImBuf(2*size + 4, 2*size + 4, 32, IB_rect, 0);
744         glReadPixels(x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
745         glReadBuffer(GL_BACK);  
746
747         if(G.order==B_ENDIAN)  {
748                 IMB_convert_rgba_to_abgr(ibuf);
749         }
750
751         rt= ibuf->rect;
752         size= (y2-y1)*(x2-x1);
753         if(size<=0) return 0;
754
755         memset(indexar, 0, sizeof(int)*vp->tot+2);      /* plus 2! first element is total */
756         
757         while(size--) {
758                         
759                 if(*rt) {
760                         index= framebuffer_to_index(*rt);
761                         if(index>0 && index<=vp->tot)
762                                 indexar[index] = 1;
763                 }
764         
765                 rt++;
766         }
767         
768         for(a=1; a<=vp->tot; a++) {
769                 if(indexar[a]) indexar[tot++]= a;
770         }
771
772         IMB_freeImBuf(ibuf);
773         
774         return tot;
775 }
776
777 static int calc_vp_alpha_dl(VPaint *vp, float vpimat[][3], float *vert_nor, short *mval)
778 {
779         float fac, dx, dy;
780         int alpha;
781         short vertco[2];
782         
783         if(vp->flag & VP_SOFT) {
784                 project_short_noclip(vert_nor, vertco);
785                 dx= mval[0]-vertco[0];
786                 dy= mval[1]-vertco[1];
787                 
788                 fac= sqrt(dx*dx + dy*dy);
789                 if(fac > vp->size) return 0;
790                 if(vp->flag & VP_HARD)
791                         alpha= 255;
792                 else
793                         alpha= 255.0*vp->a*(1.0-fac/vp->size);
794         }
795         else {
796                 alpha= 255.0*vp->a;
797         }
798
799         if(vp->flag & VP_NORMALS) {
800                 float *no= vert_nor+3;
801                 
802                         /* transpose ! */
803                 fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
804                 if(fac>0.0) {
805                         dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
806                         dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
807                         
808                         alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
809                 }
810                 else return 0;
811         }
812         
813         return alpha;
814 }
815
816 void copy_wpaint_prev (VPaint *vp, MDeformVert *dverts, int dcount)
817 {
818         if (vp->wpaint_prev) {
819                 free_dverts(vp->wpaint_prev, vp->tot);
820                 vp->wpaint_prev= NULL;
821         }
822         
823         if(dverts && dcount) {
824                 
825                 vp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
826                 vp->tot = dcount;
827                 copy_dverts (vp->wpaint_prev, dverts, dcount);
828         }
829 }
830
831 static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval)
832 {
833         
834         if(dw==NULL || uw==NULL) return;
835         
836         if(Gwp.mode==VP_MIX || Gwp.mode==VP_FILT)
837                 dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
838         else if(Gwp.mode==VP_ADD)
839                 dw->weight += paintval*alpha;
840         else if(Gwp.mode==VP_SUB) 
841                 dw->weight -= paintval*alpha;
842         else if(Gwp.mode==VP_MUL) 
843                 /* first mul, then blend the fac */
844                 dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight;
845         else if(Gwp.mode==VP_LIGHTEN) {
846                 if (dw->weight < paintval)
847                         dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
848         } else if(Gwp.mode==VP_DARKEN) {
849                 if (dw->weight > paintval)
850                         dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
851         }
852         CLAMP(dw->weight, 0.0f, 1.0f);
853         
854         /* if no spray, clip result with orig weight & orig alpha */
855         if((Gwp.flag & VP_SPRAY)==0) {
856                 float testw=0.0f;
857                 
858                 alpha= Gwp.a;
859                 if(Gwp.mode==VP_MIX || Gwp.mode==VP_FILT)
860                         testw = paintval*alpha + uw->weight*(1.0-alpha);
861                 else if(Gwp.mode==VP_ADD)
862                         testw = uw->weight + paintval*alpha;
863                 else if(Gwp.mode==VP_SUB) 
864                         testw = uw->weight - paintval*alpha;
865                 else if(Gwp.mode==VP_MUL) 
866                         /* first mul, then blend the fac */
867                         testw = ((1.0-alpha) + alpha*paintval)*uw->weight;              
868                 else if(Gwp.mode==VP_LIGHTEN) {
869                         if (uw->weight < paintval)
870                                 testw = paintval*alpha + uw->weight*(1.0-alpha);
871                         else
872                                 testw = uw->weight;
873                 } else if(Gwp.mode==VP_DARKEN) {
874                         if (uw->weight > paintval)
875                                 testw = paintval*alpha + uw->weight*(1.0-alpha);
876                         else
877                                 testw = uw->weight;
878                 }
879                 CLAMP(testw, 0.0f, 1.0f);
880                 
881                 if( testw<uw->weight ) {
882                         if(dw->weight < testw) dw->weight= testw;
883                         else if(dw->weight > uw->weight) dw->weight= uw->weight;
884                 }
885                 else {
886                         if(dw->weight > testw) dw->weight= testw;
887                         else if(dw->weight < uw->weight) dw->weight= uw->weight;
888                 }
889         }
890         
891 }
892
893 /* ----------------------------------------------------- */
894
895 /* used for 3d view, on active object, assumes me->dvert exists */
896 /* if mode==1: */
897 /*     samples cursor location, and gives menu with vertex groups to activate */
898 /* else */
899 /*     sets editbutvweight to the closest weight value to vertex */
900 /*     note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
901 static void sample_wpaint(int mode)
902 {
903         Object *ob= OBACT;
904         Mesh *me= get_mesh(ob);
905         int index;
906         short mval[2], sco[2];
907
908         if (!me) return;
909         
910         getmouseco_areawin(mval);
911         index= sample_backbuf(mval[0], mval[1]);
912         
913         if(index && index<=me->totface) {
914                 MFace *mface;
915                 
916                 mface= ((MFace *)me->mface) + index-1;
917                 
918                 if(mode==1) {   /* sampe which groups are in here */
919                         MDeformVert *dv;
920                         int a, totgroup;
921                         
922                         totgroup= BLI_countlist(&ob->defbase);
923                         if(totgroup) {
924                                 int totmenu=0;
925                                 int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
926                                 
927                                 dv= me->dvert+mface->v1;
928                                 for(a=0; a<dv->totweight; a++) {
929                                         if (dv->dw[a].def_nr<totgroup)
930                                                 groups[dv->dw[a].def_nr]= 1;
931                                 }
932                                 dv= me->dvert+mface->v2;
933                                 for(a=0; a<dv->totweight; a++) {
934                                         if (dv->dw[a].def_nr<totgroup)
935                                                 groups[dv->dw[a].def_nr]= 1;
936                                 }
937                                 dv= me->dvert+mface->v3;
938                                 for(a=0; a<dv->totweight; a++) {
939                                         if (dv->dw[a].def_nr<totgroup)
940                                                 groups[dv->dw[a].def_nr]= 1;
941                                 }
942                                 if(mface->v4) {
943                                         dv= me->dvert+mface->v4;
944                                         for(a=0; a<dv->totweight; a++) {
945                                                 if (dv->dw[a].def_nr<totgroup)
946                                                         groups[dv->dw[a].def_nr]= 1;
947                                         }
948                                 }
949                                 for(a=0; a<totgroup; a++)
950                                         if(groups[a]) totmenu++;
951                                 
952                                 if(totmenu==0) {
953                                         notice("No Vertex Group Selected");
954                                 }
955                                 else {
956                                         bDeformGroup *dg;
957                                         short val;
958                                         char item[40], *str= MEM_mallocN(40*totmenu+40, "menu");
959                                         
960                                         strcpy(str, "Vertex Groups %t");
961                                         for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) {
962                                                 if(groups[a]) {
963                                                         sprintf(item, "|%s %%x%d", dg->name, a);
964                                                         strcat(str, item);
965                                                 }
966                                         }
967                                         
968                                         val= pupmenu(str);
969                                         if(val>=0) {
970                                                 ob->actdef= val+1;
971                                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
972                                                 allqueue(REDRAWVIEW3D, 0);
973                                                 allqueue(REDRAWOOPS, 0);
974                                                 allqueue(REDRAWBUTSEDIT, 0);
975                                         }
976                                         MEM_freeN(str);
977                                 }
978                                 MEM_freeN(groups);
979                         }
980                         else notice("No Vertex Groups in Object");
981                 }
982                 else {
983                         DerivedMesh *dm;
984                         MDeformWeight *dw;
985                         extern float editbutvweight;
986                         float w1, w2, w3, w4, co[3], fac;
987                         
988                         dm = mesh_get_derived_final(ob);
989                         if(dm->getVertCo==NULL) {
990                                 notice("Not supported yet");
991                         }
992                         else {
993                                 /* calc 3 or 4 corner weights */
994                                 dm->getVertCo(dm, mface->v1, co);
995                                 project_short_noclip(co, sco);
996                                 w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
997                                 
998                                 dm->getVertCo(dm, mface->v2, co);
999                                 project_short_noclip(co, sco);
1000                                 w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1001                                 
1002                                 dm->getVertCo(dm, mface->v3, co);
1003                                 project_short_noclip(co, sco);
1004                                 w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1005                                 
1006                                 if(mface->v4) {
1007                                         dm->getVertCo(dm, mface->v4, co);
1008                                         project_short_noclip(co, sco);
1009                                         w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1010                                 }
1011                                 else w4= 1.0e10;
1012                                 
1013                                 fac= MIN4(w1, w2, w3, w4);
1014                                 if(w1==fac) {
1015                                         dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
1016                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1017                                 }
1018                                 else if(w2==fac) {
1019                                         dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
1020                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1021                                 }
1022                                 else if(w3==fac) {
1023                                         dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
1024                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1025                                 }
1026                                 else if(w4==fac) {
1027                                         if(mface->v4) {
1028                                                 dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
1029                                                 if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1030                                         }
1031                                 }
1032                         }
1033                         dm->release(dm);
1034                 }               
1035                 
1036         }
1037         allqueue(REDRAWBUTSEDIT, 0);
1038         
1039 }
1040
1041 static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paintweight, int vgroup_mirror)
1042 {
1043         Mesh *me= ob->data;
1044         MDeformWeight   *dw, *uw;
1045         int vgroup= ob->actdef-1;
1046         
1047         if(Gwp.flag & VP_ONLYVGROUP) {
1048                 dw= get_defweight(me->dvert+index, vgroup);
1049                 uw= get_defweight(Gwp.wpaint_prev+index, vgroup);
1050         }
1051         else {
1052                 dw= verify_defweight(me->dvert+index, vgroup);
1053                 uw= verify_defweight(Gwp.wpaint_prev+index, vgroup);
1054         }
1055         if(dw==NULL || uw==NULL)
1056                 return;
1057         
1058         wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1059         
1060         if(Gwp.flag & VP_MIRROR_X) {    /* x mirror painting */
1061                 int j= mesh_get_x_mirror_vert(ob, index);
1062                 if(j>=0) {
1063                         /* copy, not paint again */
1064                         if(vgroup_mirror != -1)
1065                                 uw= verify_defweight(me->dvert+j, vgroup_mirror);
1066                         else
1067                                 uw= verify_defweight(me->dvert+j, vgroup);
1068                                 
1069                         uw->weight= dw->weight;
1070                 }
1071         }
1072 }
1073
1074 void weight_paint(void)
1075 {
1076         extern float editbutvweight;
1077         Object *ob; 
1078         Mesh *me;
1079         MFace *mface;
1080         MTFace *tface;
1081         float mat[4][4], imat[4][4], paintweight, *vertexcosnos;
1082         float vpimat[3][3];
1083         int *indexar, index, totindex, alpha, totw;
1084         int vgroup_mirror= -1;
1085         short mval[2], mvalo[2], firsttime=1, mousebut;
1086
1087         if((G.f & G_WEIGHTPAINT)==0) return;
1088         if(G.obedit) return;
1089         
1090         ob= OBACT;
1091         if(!ob || ob->id.lib) return;
1092
1093         me= get_mesh(ob);
1094         if(me==NULL || me->totface==0) return;
1095         
1096         /* if nothing was added yet, we make dverts and a vertex deform group */
1097         if (!me->dvert)
1098                 create_dverts(&me->id);
1099         
1100         if(G.qual & LR_CTRLKEY) {
1101                 sample_wpaint(0);
1102                 return;
1103         }
1104         if(G.qual & LR_SHIFTKEY) {
1105                 sample_wpaint(1);
1106                 return;
1107         }
1108         
1109         /* ALLOCATIONS! no return after this line */
1110                 /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1111         vertexcosnos= mesh_get_mapped_verts_nors(ob);
1112         indexar= get_indexarray();
1113         copy_wpaint_prev(&Gwp, me->dvert, me->totvert);
1114
1115         /* this happens on a Bone select, when no vgroup existed yet */
1116         if(ob->actdef<=0) {
1117                 Object *modob;
1118                 if((modob = modifiers_isDeformedByArmature(ob))) {
1119                         bPoseChannel *pchan;
1120                         for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next)
1121                                 if(pchan->bone->flag & SELECT)
1122                                         break;
1123                         if(pchan) {
1124                                 bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
1125                                 if(dg==NULL)
1126                                         dg= add_defgroup_name(ob, pchan->name); /* sets actdef */
1127                                 else
1128                                         ob->actdef= get_defgroup_num(ob, dg);
1129                                 allqueue(REDRAWBUTSEDIT, 0);
1130                         }
1131                 }
1132         }
1133         if(ob->defbase.first==NULL) {
1134                 add_defgroup(ob);
1135                 allqueue(REDRAWBUTSEDIT, 0);
1136         }       
1137         
1138         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
1139         
1140         persp(PERSP_VIEW);
1141         /* imat for normals */
1142         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
1143         Mat4Invert(imat, mat);
1144         Mat3CpyMat4(vpimat, imat);
1145         
1146         /* load projection matrix */
1147         mymultmatrix(ob->obmat);
1148         mygetsingmatrix(mat);
1149         myloadmatrix(G.vd->viewmat);
1150         
1151         getmouseco_areawin(mvalo);
1152         
1153         getmouseco_areawin(mval);
1154         mvalo[0]= mval[0];
1155         mvalo[1]= mval[1];
1156         
1157         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1158         else mousebut = L_MOUSE;
1159         
1160         /* if mirror painting, find the other group */
1161         if(Gwp.flag & VP_MIRROR_X) {
1162                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
1163                 if(defgroup) {
1164                         bDeformGroup *curdef;
1165                         int actdef= 0;
1166                         char name[32];
1167
1168                         BLI_strncpy(name, defgroup->name, 32);
1169                         bone_flip_name(name, 0);                /* 0 = don't strip off number extensions */
1170                         
1171                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
1172                                 if (!strcmp(curdef->name, name))
1173                                         break;
1174                         if(curdef==NULL) {
1175                                 int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
1176                                 curdef= add_defgroup_name (ob, name);
1177                                 ob->actdef= olddef;
1178                         }
1179                         
1180                         if(curdef && curdef!=defgroup)
1181                                 vgroup_mirror= actdef;
1182                 }
1183         }
1184         
1185         while (get_mbut() & mousebut) {
1186                 getmouseco_areawin(mval);
1187                 
1188                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1189                         firsttime= 0;
1190                         
1191                         /* which faces are involved */
1192                         if(Gwp.flag & VP_AREA) {
1193                                 totindex= sample_backbuf_area(&Gwp, indexar, mval[0], mval[1], Gwp.size);
1194                         }
1195                         else {
1196                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
1197                                 if(indexar[0]) totindex= 1;
1198                                 else totindex= 0;
1199                         }
1200                         
1201                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1202                         
1203                         if(Gwp.flag & VP_COLINDEX) {
1204                                 for(index=0; index<totindex; index++) {
1205                                         if(indexar[index] && indexar[index]<=me->totface) {
1206                                         
1207                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1208                                         
1209                                                 if(mface->mat_nr!=ob->actcol-1) {
1210                                                         indexar[index]= 0;
1211                                                 }
1212                                         }                                       
1213                                 }
1214                         }
1215
1216                         if((G.f & G_FACESELECT) && me->mtface) {
1217                                 for(index=0; index<totindex; index++) {
1218                                         if(indexar[index] && indexar[index]<=me->totface) {
1219                                         
1220                                                 tface= ((MTFace *)me->mtface) + (indexar[index]-1);
1221                                         
1222                                                 if((tface->flag & TF_SELECT)==0) {
1223                                                         indexar[index]= 0;
1224                                                 }
1225                                         }                                       
1226                                 }
1227                         }
1228                         
1229                         /* make sure each vertex gets treated only once */
1230                         /* and calculate filter weight */
1231                         totw= 0;
1232                         if(Gwp.mode==VP_FILT) 
1233                                 paintweight= 0.0f;
1234                         else
1235                                 paintweight= editbutvweight;
1236                         
1237                         for(index=0; index<totindex; index++) {
1238                                 if(indexar[index] && indexar[index]<=me->totface) {
1239                                         mface= me->mface + (indexar[index]-1);
1240                                         
1241                                         (me->dvert+mface->v1)->flag= 1;
1242                                         (me->dvert+mface->v2)->flag= 1;
1243                                         (me->dvert+mface->v3)->flag= 1;
1244                                         if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1245                                         
1246                                         if(Gwp.mode==VP_FILT) {
1247                                                 MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight;
1248                                                 
1249                                                 if(Gwp.flag & VP_ONLYVGROUP)
1250                                                         dw_func= get_defweight;
1251                                                 
1252                                                 dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
1253                                                 if(dw) {paintweight+= dw->weight; totw++;}
1254                                                 dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
1255                                                 if(dw) {paintweight+= dw->weight; totw++;}
1256                                                 dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
1257                                                 if(dw) {paintweight+= dw->weight; totw++;}
1258                                                 if(mface->v4) {
1259                                                         dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
1260                                                         if(dw) {paintweight+= dw->weight; totw++;}
1261                                                 }
1262                                         }
1263                                 }
1264                         }
1265                         
1266                         if(Gwp.mode==VP_FILT) 
1267                                 paintweight/= (float)totw;
1268                         
1269                         for(index=0; index<totindex; index++) {
1270                                 
1271                                 if(indexar[index] && indexar[index]<=me->totface) {
1272                                         mface= me->mface + (indexar[index]-1);
1273                                         
1274                                         if((me->dvert+mface->v1)->flag) {
1275                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v1, mval);
1276                                                 if(alpha) {
1277                                                         do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror);
1278                                                 }
1279                                                 (me->dvert+mface->v1)->flag= 0;
1280                                         }
1281                                         
1282                                         if((me->dvert+mface->v2)->flag) {
1283                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v2, mval);
1284                                                 if(alpha) {
1285                                                         do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror);
1286                                                 }
1287                                                 (me->dvert+mface->v2)->flag= 0;
1288                                         }
1289                                         
1290                                         if((me->dvert+mface->v3)->flag) {
1291                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v3, mval);
1292                                                 if(alpha) {
1293                                                         do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror);
1294                                                 }
1295                                                 (me->dvert+mface->v3)->flag= 0;
1296                                         }
1297                                         
1298                                         if((me->dvert+mface->v4)->flag) {
1299                                                 if(mface->v4) {
1300                                                         alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v4, mval);
1301                                                         if(alpha) {
1302                                                                 do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror);
1303                                                         }
1304                                                         (me->dvert+mface->v4)->flag= 0;
1305                                                 }
1306                                         }
1307                                 }
1308                         }
1309                         
1310                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1311                         
1312                 }
1313                 else BIF_wait_for_statechange();
1314                 
1315                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1316
1317                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1318                         scrarea_do_windraw(curarea);
1319                         
1320                         if(Gwp.flag & (VP_AREA|VP_SOFT)) {
1321                                 /* draw circle in backbuf! */
1322                                 persp(PERSP_WIN);
1323                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size);
1324                                 persp(PERSP_VIEW);
1325                         }
1326
1327                         screen_swapbuffers();
1328                         backdrawview3d(0);
1329         
1330                         mvalo[0]= mval[0];
1331                         mvalo[1]= mval[1];
1332                 }
1333         }
1334         
1335         if(vertexcosnos)
1336                 MEM_freeN(vertexcosnos);
1337         MEM_freeN(indexar);
1338         copy_wpaint_prev(&Gwp, NULL, 0);
1339
1340         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1341         /* this flag is event for softbody to refresh weightpaint values */
1342         if(ob->soft) ob->softflag |= OB_SB_REDO;
1343         
1344         BIF_undo_push("Weight Paint");
1345         allqueue(REDRAWVIEW3D, 0);
1346 }
1347
1348 void vertex_paint()
1349 {
1350         Object *ob;
1351         Mesh *me;
1352         MFace *mface;
1353         MTFace *tface;
1354         float mat[4][4], imat[4][4], *vertexcosnos;
1355         float vpimat[3][3];
1356         unsigned int paintcol=0, *mcol, *mcolorig, fcol1, fcol2;
1357         int *indexar, index, alpha, totindex;
1358         short mval[2], mvalo[2], firsttime=1, mousebut;
1359         
1360         if((G.f & G_VERTEXPAINT)==0) return;
1361         if(G.obedit) return;
1362         
1363         ob= OBACT;
1364         if(!ob || ob->id.lib) return;
1365
1366         me= get_mesh(ob);
1367         if(me==NULL || me->totface==0) return;
1368         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
1369         
1370         if(me->mtface==NULL && me->mcol==NULL) make_vertexcol(1);
1371
1372         if(me->mtface==NULL && me->mcol==NULL) return;
1373         
1374         /* ALLOCATIONS! No return after his line */
1375         
1376                                 /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1377         vertexcosnos= mesh_get_mapped_verts_nors(ob);
1378         indexar= get_indexarray();
1379         copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface);
1380         
1381         /* opengl/matrix stuff */
1382         persp(PERSP_VIEW);
1383         /* imat for normals */
1384         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
1385         Mat4Invert(imat, mat);
1386         Mat3CpyMat4(vpimat, imat);
1387         
1388         /* load projection matrix */
1389         mymultmatrix(ob->obmat);
1390         mygetsingmatrix(mat);
1391         myloadmatrix(G.vd->viewmat);
1392         
1393         paintcol= vpaint_get_current_col(&Gvp);
1394         
1395         getmouseco_areawin(mvalo);
1396         
1397         getmouseco_areawin(mval);
1398         mvalo[0]= mval[0];
1399         mvalo[1]= mval[1];
1400         
1401         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1402         else mousebut = L_MOUSE;
1403         
1404         while (get_mbut() & mousebut) {
1405                 getmouseco_areawin(mval);
1406                 
1407                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1408
1409                         firsttime= 0;
1410
1411                         /* which faces are involved */
1412                         if(Gvp.flag & VP_AREA) {
1413                                 totindex= sample_backbuf_area(&Gvp, indexar, mval[0], mval[1], Gvp.size);
1414                         }
1415                         else {
1416                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
1417                                 if(indexar[0]) totindex= 1;
1418                                 else totindex= 0;
1419                         }
1420                         
1421                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1422                         
1423                         if(Gvp.flag & VP_COLINDEX) {
1424                                 for(index=0; index<totindex; index++) {
1425                                         if(indexar[index] && indexar[index]<=me->totface) {
1426                                         
1427                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1428                                         
1429                                                 if(mface->mat_nr!=ob->actcol-1) {
1430                                                         indexar[index]= 0;
1431                                                 }
1432                                         }                                       
1433                                 }
1434                         }
1435                         if((G.f & G_FACESELECT) && me->mtface) {
1436                                 for(index=0; index<totindex; index++) {
1437                                         if(indexar[index] && indexar[index]<=me->totface) {
1438                                                 tface= ((MTFace *)me->mtface) + (indexar[index]-1);
1439                                         
1440                                                 if((tface->flag & TF_SELECT)==0)
1441                                                         indexar[index]= 0;
1442                                         }                                       
1443                                 }
1444                         }
1445
1446                         for(index=0; index<totindex; index++) {
1447
1448                                 if(indexar[index] && indexar[index]<=me->totface) {
1449                                 
1450                                         mface= ((MFace *)me->mface) + (indexar[index]-1);
1451                                         mcol=     ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
1452                                         mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1);
1453
1454                                         if(Gvp.mode==VP_FILT) {
1455                                                 fcol1= mcol_blend( mcol[0], mcol[1], 128);
1456                                                 if(mface->v4) {
1457                                                         fcol2= mcol_blend( mcol[2], mcol[3], 128);
1458                                                         paintcol= mcol_blend( fcol1, fcol2, 128);
1459                                                 }
1460                                                 else {
1461                                                         paintcol= mcol_blend( mcol[2], fcol1, 170);
1462                                                 }
1463                                                 
1464                                         }
1465                                         
1466                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v1, mval);
1467                                         if(alpha) vpaint_blend( mcol, mcolorig, paintcol, alpha);
1468                                         
1469                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v2, mval);
1470                                         if(alpha) vpaint_blend( mcol+1, mcolorig+1, paintcol, alpha);
1471         
1472                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v3, mval);
1473                                         if(alpha) vpaint_blend( mcol+2, mcolorig+2, paintcol, alpha);
1474
1475                                         if(mface->v4) {
1476                                                 alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v4, mval);
1477                                                 if(alpha) vpaint_blend( mcol+3, mcolorig+3, paintcol, alpha);
1478                                         }
1479                                 }
1480                         }
1481                                 
1482                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1483                         
1484                         do_shared_vertexcol(me);
1485         
1486                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1487                         scrarea_do_windraw(curarea);
1488
1489                         if(Gvp.flag & (VP_AREA|VP_SOFT)) {
1490                                 /* draw circle in backbuf! */
1491                                 persp(PERSP_WIN);
1492                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gvp.size);
1493                                 persp(PERSP_VIEW);
1494                         }
1495                         screen_swapbuffers();
1496                         backdrawview3d(0);
1497                         
1498                         mvalo[0]= mval[0];
1499                         mvalo[1]= mval[1];
1500                 }
1501                 else BIF_wait_for_statechange();
1502         }
1503         
1504         if(vertexcosnos)
1505                 MEM_freeN(vertexcosnos);
1506         MEM_freeN(indexar);
1507         
1508         /* frees prev buffer */
1509         copy_vpaint_prev(&Gvp, NULL, 0);
1510
1511         BIF_undo_push("Vertex Paint");
1512         
1513         allqueue(REDRAWVIEW3D, 0);
1514 }
1515
1516 void set_wpaint(void)           /* toggle */
1517 {               
1518         Object *ob;
1519         Mesh *me;
1520         
1521         scrarea_queue_headredraw(curarea);
1522         ob= OBACT;
1523         if(!ob || ob->id.lib) return;
1524         me= get_mesh(ob);
1525                 
1526         if(me && me->totface>=MAXINDEX) {
1527                 error("Maximum number of faces: %d", MAXINDEX-1);
1528                 G.f &= ~G_WEIGHTPAINT;
1529                 return;
1530         }
1531         
1532         if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
1533         else G.f |= G_WEIGHTPAINT;
1534         
1535         allqueue(REDRAWVIEW3D, 1);      /* including header */
1536         allqueue(REDRAWBUTSEDIT, 0);
1537         
1538                 /* Weightpaint works by overriding colors in mesh,
1539                  * so need to make sure we recalc on enter and
1540                  * exit (exit needs doing regardless because we
1541                  * should redeform).
1542                  */
1543         if (me) {
1544                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1545         }
1546
1547         if(G.f & G_WEIGHTPAINT) {
1548                 Object *par;
1549                 
1550                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1551                 
1552                 mesh_octree_table(ob, NULL, 's');
1553
1554                 /* verify if active weight group is also active bone */
1555                 par= modifiers_isDeformedByArmature(ob);
1556                 if(par && (par->flag & OB_POSEMODE)) {
1557                         bPoseChannel *pchan;
1558                         for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next)
1559                                 if(pchan->bone->flag & BONE_ACTIVE)
1560                                         break;
1561                         if(pchan)
1562                                 vertexgroup_select_by_name(ob, pchan->name);
1563                 }
1564         }
1565         else {
1566                 if(!(G.f & G_FACESELECT))
1567                         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1568                 
1569                 mesh_octree_table(ob, NULL, 'e');
1570         }
1571 }
1572
1573
1574 void set_vpaint(void)           /* toggle */
1575 {               
1576         Object *ob;
1577         Mesh *me;
1578         
1579         scrarea_queue_headredraw(curarea);
1580         ob= OBACT;
1581         if(!ob || ob->id.lib) {
1582                 G.f &= ~G_VERTEXPAINT;
1583                 return;
1584         }
1585         
1586         me= get_mesh(ob);
1587         
1588         if(me && me->totface>=MAXINDEX) {
1589                 error("Maximum number of faces: %d", MAXINDEX-1);
1590                 G.f &= ~G_VERTEXPAINT;
1591                 return;
1592         }
1593         
1594         if(me && me->mcol==NULL) make_vertexcol(1);
1595         
1596         if(G.f & G_VERTEXPAINT){
1597                 G.f &= ~G_VERTEXPAINT;
1598         }
1599         else {
1600                 G.f |= G_VERTEXPAINT;
1601                 /* Turn off weight painting */
1602                 if (G.f & G_WEIGHTPAINT)
1603                         set_wpaint();
1604         }
1605         
1606         allqueue(REDRAWVIEW3D, 1);      /* including header */
1607         allqueue(REDRAWBUTSEDIT, 0);
1608         
1609         if (me)
1610                 /* update modifier stack for mapping requirements */
1611                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1612
1613         if(G.f & G_VERTEXPAINT) {
1614                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1615         }
1616         else {
1617                 if((G.f & G_FACESELECT)==0) setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1618         }
1619 }
1620