- more fixes for wpaint mode, need to patch mesh modifier as well
[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 HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #ifdef WIN32
41 #include <io.h>
42 #else
43 #include <unistd.h>
44 #endif   
45
46 #include "MEM_guardedalloc.h"
47
48 #include "IMB_imbuf.h"
49
50 #include "BLI_blenlib.h"
51 #include "BLI_arithb.h"
52 #include "MTC_matrixops.h"
53
54 #include "DNA_action_types.h"
55 #include "DNA_armature_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_object_force.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_userdef_types.h"
64
65 #include "BKE_DerivedMesh.h"
66 #include "BKE_depsgraph.h"
67 #include "BKE_deform.h"
68 #include "BKE_displist.h"
69 #include "BKE_global.h"
70 #include "BKE_mesh.h"
71 #include "BKE_object.h"
72 #include "BKE_utildefines.h"
73
74 #include "BIF_graphics.h"
75 #include "BIF_interface.h"
76 #include "BIF_mywindow.h"
77 #include "BIF_editview.h"
78 #include "BIF_space.h"
79 #include "BIF_screen.h"
80 #include "BIF_toolbox.h"
81 #include "BIF_glutil.h"
82 #include "BIF_gl.h"
83
84 #include "BDR_vpaint.h"
85
86 #include "BSE_drawview.h"
87 #include "BSE_trans_types.h"
88 #include "BSE_view.h"
89
90 #include "mydevice.h"
91 #include "blendef.h"
92
93 #include "BIF_editdeform.h"
94
95         /* Gvp.mode */
96 #define VP_MIX  0
97 #define VP_ADD  1
98 #define VP_SUB  2
99 #define VP_MUL  3
100 #define VP_FILT 4
101
102 #define MAXINDEX        512000
103
104 VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY};
105 VPaint Gwp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT};
106 float vpimat[3][3];
107 unsigned int *vpaintundobuf= NULL;
108 int totvpaintundo;
109 int *indexar= NULL;
110
111 int totwpaintundo;
112 MDeformVert *wpaintundobuf=NULL;
113
114 /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! 
115    so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
116
117 unsigned int rgba_to_mcol(float r, float g, float b, float a)
118 {
119         int ir, ig, ib, ia;
120         unsigned int col;
121         char *cp;
122         
123         ir= floor(255.0*r);
124         if(ir<0) ir= 0; else if(ir>255) ir= 255;
125         ig= floor(255.0*g);
126         if(ig<0) ig= 0; else if(ig>255) ig= 255;
127         ib= floor(255.0*b);
128         if(ib<0) ib= 0; else if(ib>255) ib= 255;
129         ia= floor(255.0*a);
130         if(ia<0) ia= 0; else if(ia>255) ia= 255;
131         
132         cp= (char *)&col;
133         cp[0]= ia;
134         cp[1]= ib;
135         cp[2]= ig;
136         cp[3]= ir;
137         
138         return col;
139         
140 }
141
142 unsigned int vpaint_get_current_col(void)
143 {
144         return rgba_to_mcol(Gvp.r, Gvp.g, Gvp.b, 1.0);
145 }
146
147 void do_shared_vertexcol(Mesh *me)
148 {
149         /* if no mcol: do not do */
150         /* if tface: only the involved faces, otherwise all */
151         MFace *mface;
152         TFace *tface;
153         int a;
154         short *scolmain, *scol;
155         char *mcol;
156         
157         if(me->mcol==0 || me->totvert==0 || me->totface==0) return;
158         
159         scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
160         
161         tface= me->tface;
162         mface= me->mface;
163         mcol= (char *)me->mcol;
164         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
165                 if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
166                         scol= scolmain+4*mface->v1;
167                         scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
168                         scol= scolmain+4*mface->v2;
169                         scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
170                         scol= scolmain+4*mface->v3;
171                         scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
172                         if(mface->v4) {
173                                 scol= scolmain+4*mface->v4;
174                                 scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
175                         }
176                 }
177                 if(tface) tface++;
178         }
179         
180         a= me->totvert;
181         scol= scolmain;
182         while(a--) {
183                 if(scol[0]>1) {
184                         scol[1]/= scol[0];
185                         scol[2]/= scol[0];
186                         scol[3]/= scol[0];
187                 }
188                 scol+= 4;
189         }
190         
191         tface= me->tface;
192         mface= me->mface;
193         mcol= (char *)me->mcol;
194         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
195                 if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
196                         scol= scolmain+4*mface->v1;
197                         mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
198                         scol= scolmain+4*mface->v2;
199                         mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
200                         scol= scolmain+4*mface->v3;
201                         mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
202                         if(mface->v4) {
203                                 scol= scolmain+4*mface->v4;
204                                 mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
205                         }
206                 }
207                 if(tface) tface++;
208         }
209
210         MEM_freeN(scolmain);
211 }
212
213 void make_vertexcol()   /* single ob */
214 {
215         Object *ob;
216         Mesh *me;
217         int i;
218
219         /*
220          * Always copies from shadedisplist to mcol.
221          * When there are tfaces, it copies the colors and frees mcol
222          */
223         
224         if(G.obedit) {
225                 error("Unable to perform function in Edit Mode");
226                 return;
227         }
228         
229         ob= OBACT;
230         me= get_mesh(ob);
231         if(me==0) return;
232
233         if(me->mcol) MEM_freeN(me->mcol);
234         mesh_create_shadedColors(ob, 1, (unsigned int**) &me->mcol, NULL);
235
236         for (i=0; i<me->totface*4; i++) {
237                 me->mcol[i].a = 255;
238         }
239                 
240         if(me->tface) mcol_to_tface(me, 1);
241         
242         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
243         
244         allqueue(REDRAWBUTSEDIT, 0);
245         allqueue(REDRAWVIEW3D, 0);
246 }
247
248
249
250 void copy_vpaint_undo(unsigned int *mcol, int tot)
251 {
252         if(vpaintundobuf) MEM_freeN(vpaintundobuf);
253         vpaintundobuf= 0;
254         totvpaintundo= tot;     // because of return, it is used by weightpaint
255         
256         if(mcol==0 || tot==0) return;
257         
258         vpaintundobuf= MEM_mallocN(4*sizeof(int)*tot, "vpaintundobuf");
259         memcpy(vpaintundobuf, mcol, 4*sizeof(int)*tot);
260         
261 }
262
263 void vpaint_undo()
264 {
265         Mesh *me;
266         Object *ob;
267         unsigned int temp, *from, *to;
268         int a;
269         
270         if((G.f & G_VERTEXPAINT)==0) return;
271         if(vpaintundobuf==0) return;
272
273         ob= OBACT;
274         me= get_mesh(ob);
275         if(me==0 || me->totface==0) return;
276
277         if(me->tface) tface_to_mcol(me);
278         else if(me->mcol==0) return;
279         
280         a= MIN2(me->totface, totvpaintundo);
281         from= vpaintundobuf;
282         to= (unsigned int *)me->mcol;
283         a*= 4;
284         while(a--) {
285                 temp= *to;
286                 *to= *from;
287                 *from= temp;
288                 to++; from++;
289         }
290         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
291         
292         allqueue(REDRAWVIEW3D, 0);
293         if(me->tface) mcol_to_tface(me, 1);
294 }
295
296 void clear_vpaint()
297 {
298         Mesh *me;
299         Object *ob;
300         unsigned int *to, paintcol;
301         int a;
302         
303         if((G.f & G_VERTEXPAINT)==0) return;
304
305         ob= OBACT;
306         me= get_mesh(ob);
307         if(ob->id.lib) return;
308
309         if(me==0 || me->totface==0) return;
310
311         if(me->tface) tface_to_mcol(me);
312         if(me->mcol==0) return;
313
314         paintcol= vpaint_get_current_col();
315
316         to= (unsigned int *)me->mcol;
317         copy_vpaint_undo(to, me->totface);
318         a= 4*me->totface;
319         while(a--) {
320                 *to= paintcol;
321                 to++; 
322         }
323         BIF_undo_push("Clear vertex colors");
324         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
325         
326         allqueue(REDRAWVIEW3D, 0);
327         if(me->tface) mcol_to_tface(me, 1);
328 }
329
330 void clear_vpaint_selectedfaces()
331 {
332         Mesh *me;
333         TFace *tf;
334         Object *ob;
335         unsigned int paintcol;
336         int i;
337
338         ob= OBACT;
339
340         me= get_mesh(ob);
341         tf = me->tface;
342         if (!tf) return; /* should not happen, but you never know */
343
344         if(me==0 || me->totface==0) return;
345
346         paintcol= vpaint_get_current_col();
347
348         for (i = 0; i < me->totface; i++) {
349                 if (tf[i].flag & TF_SELECT) {
350                         tf[i].col[0] = paintcol;
351                         tf[i].col[1] = paintcol;
352                         tf[i].col[2] = paintcol;
353                         tf[i].col[3] = paintcol;
354                 }
355         }
356         BIF_undo_push("Clear vertex colors");
357         allqueue(REDRAWVIEW3D, 0);
358 }
359
360 void vpaint_dogamma()
361 {
362         Mesh *me;
363         Object *ob;
364         float igam, fac;
365         int a, temp;
366         char *cp, gamtab[256];
367
368         if((G.f & G_VERTEXPAINT)==0) return;
369
370         ob= OBACT;
371         me= get_mesh(ob);
372         if(me==0 || me->totface==0) return;
373
374         if(me->tface) tface_to_mcol(me);
375         else if(me->mcol==0) return;
376
377         copy_vpaint_undo((unsigned int *)me->mcol, me->totface);
378
379         igam= 1.0/Gvp.gamma;
380         for(a=0; a<256; a++) {
381                 
382                 fac= ((float)a)/255.0;
383                 fac= Gvp.mul*pow( fac, igam);
384                 
385                 temp= 255.9*fac;
386                 
387                 if(temp<=0) gamtab[a]= 0;
388                 else if(temp>=255) gamtab[a]= 255;
389                 else gamtab[a]= temp;
390         }
391
392         a= 4*me->totface;
393         cp= (char *)me->mcol;
394         while(a--) {
395                 
396                 cp[1]= gamtab[ cp[1] ];
397                 cp[2]= gamtab[ cp[2] ];
398                 cp[3]= gamtab[ cp[3] ];
399                 
400                 cp+= 4;
401         }
402         allqueue(REDRAWVIEW3D, 0);
403         
404         if(me->tface) mcol_to_tface(me, 1);
405 }
406
407 /* used for both 3d view and image window */
408 void sample_vpaint()    /* frontbuf */
409 {
410         unsigned int col;
411         int x, y;
412         short mval[2];
413         char *cp;
414         
415         getmouseco_areawin(mval);
416         x= mval[0]; y= mval[1];
417         
418         if(x<0 || y<0) return;
419         if(x>=curarea->winx || y>=curarea->winy) return;
420         
421         x+= curarea->winrct.xmin;
422         y+= curarea->winrct.ymin;
423         
424         glReadBuffer(GL_FRONT);
425         glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
426         glReadBuffer(GL_BACK);
427
428         cp = (char *)&col;
429         
430         Gvp.r= cp[0];
431         Gvp.r /= 255.0;
432
433         Gvp.g= cp[1];
434         Gvp.g /= 255.0;
435
436         Gvp.b= cp[2];
437         Gvp.b /= 255.0;
438
439         allqueue(REDRAWBUTSEDIT, 0);
440         addqueue(curarea->win, REDRAW, 1); // needed for when panel is open...
441 }
442
443 void init_vertexpaint()
444 {
445         
446         indexar= MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint");
447 }
448
449
450 void free_vertexpaint()
451 {
452         
453         if(indexar) MEM_freeN(indexar);
454         indexar= NULL;
455         if(vpaintundobuf) MEM_freeN(vpaintundobuf);
456         vpaintundobuf= NULL;
457         if(wpaintundobuf) 
458                 free_dverts(wpaintundobuf, totwpaintundo);
459         wpaintundobuf= NULL;
460 }
461
462
463 static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
464 {
465         char *cp1, *cp2, *cp;
466         int mfac;
467         unsigned int col=0;
468         
469         if(fac==0) return col1;
470         if(fac>=255) return col2;
471
472         mfac= 255-fac;
473         
474         cp1= (char *)&col1;
475         cp2= (char *)&col2;
476         cp=  (char *)&col;
477         
478         cp[0]= 255;
479         cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8;
480         cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8;
481         cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8;
482         
483         return col;
484 }
485
486 static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
487 {
488         char *cp1, *cp2, *cp;
489         int temp;
490         unsigned int col=0;
491         
492         if(fac==0) return col1;
493         
494         cp1= (char *)&col1;
495         cp2= (char *)&col2;
496         cp=  (char *)&col;
497         
498         cp[0]= 255;
499         temp= cp1[1] + ((fac*cp2[1])>>8);
500         if(temp>254) cp[1]= 255; else cp[1]= temp;
501         temp= cp1[2] + ((fac*cp2[2])>>8);
502         if(temp>254) cp[2]= 255; else cp[2]= temp;
503         temp= cp1[3] + ((fac*cp2[3])>>8);
504         if(temp>254) cp[3]= 255; else cp[3]= temp;
505         
506         return col;
507 }
508
509 static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
510 {
511         char *cp1, *cp2, *cp;
512         int temp;
513         unsigned int col=0;
514         
515         if(fac==0) return col1;
516         
517         cp1= (char *)&col1;
518         cp2= (char *)&col2;
519         cp=  (char *)&col;
520         
521         cp[0]= 255;
522         temp= cp1[1] - ((fac*cp2[1])>>8);
523         if(temp<0) cp[1]= 0; else cp[1]= temp;
524         temp= cp1[2] - ((fac*cp2[2])>>8);
525         if(temp<0) cp[2]= 0; else cp[2]= temp;
526         temp= cp1[3] - ((fac*cp2[3])>>8);
527         if(temp<0) cp[3]= 0; else cp[3]= temp;
528         
529         return col;
530 }
531
532 static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
533 {
534         char *cp1, *cp2, *cp;
535         int mfac;
536         unsigned int col=0;
537         
538         if(fac==0) return col1;
539
540         mfac= 255-fac;
541         
542         cp1= (char *)&col1;
543         cp2= (char *)&col2;
544         cp=  (char *)&col;
545         
546         /* first mul, then blend the fac */
547         cp[0]= 255;
548         cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])>>8)  )>>8;
549         cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])>>8)  )>>8;
550         cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])>>8)  )>>8;
551
552         
553         return col;
554 }
555
556 static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
557 {
558
559         if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) *col= mcol_blend( *col, paintcol, alpha);
560         else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
561         else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
562         else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
563         
564         /* if no spray, clip color adding with colorig & orig alpha */
565         if((Gvp.flag & VP_SPRAY)==0) {
566                 unsigned int testcol=0, a;
567                 char *cp, *ct, *co;
568                 
569                 alpha= (int)(255.0*Gvp.a);
570                 
571                 if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) testcol= mcol_blend( *colorig, paintcol, alpha);
572                 else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
573                 else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
574                 else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
575                 
576                 cp= (char *)col;
577                 ct= (char *)&testcol;
578                 co= (char *)colorig;
579                 
580                 for(a=0; a<4; a++) {
581                         if( ct[a]<co[a] ) {
582                                 if( cp[a]<ct[a] ) cp[a]= ct[a];
583                                 else if( cp[a]>co[a] ) cp[a]= co[a];
584                         }
585                         else {
586                                 if( cp[a]<co[a] ) cp[a]= co[a];
587                                 else if( cp[a]>ct[a] ) cp[a]= ct[a];
588                         }
589                 }
590         }
591 }
592
593
594 static int sample_backbuf_area(int x, int y, float size)
595 {
596         unsigned int rect[129*129], *rt;
597         int x1, y1, x2, y2, a, tot=0, index;
598         
599         if(totvpaintundo>=MAXINDEX) return 0;
600         
601         if(size>64.0) size= 64.0;
602         
603         x1= x-size;
604         x2= x+size;
605         CLAMP(x1, 0, curarea->winx);
606         CLAMP(x2, 0, curarea->winx);
607         y1= y-size;
608         y2= y+size;
609         CLAMP(y1, 0, curarea->winy);
610         CLAMP(y2, 0, curarea->winy);
611 #ifdef __APPLE__
612         glReadBuffer(GL_AUX0);
613 #endif
614         glReadPixels(x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE,  rect);
615         glReadBuffer(GL_BACK);  
616
617         if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr( (int)(4*size*size), rect);
618
619         rt= rect;
620         size= (y2-y1)*(x2-x1);
621         if(size<=0) return 0;
622
623         memset(indexar, 0, sizeof(int)*totvpaintundo+2);        /* plus 2! first element is total */
624         
625         while(size--) {
626                         
627                 if(*rt) {
628                         index= framebuffer_to_index(*rt);
629                         if(index>0 && index<=totvpaintundo)
630                                 indexar[index] = 1;
631                 }
632         
633                 rt++;
634         }
635         
636         for(a=1; a<=totvpaintundo; a++) {
637                 if(indexar[a]) indexar[tot++]= a;
638         }
639         
640         return tot;
641 }
642
643 static unsigned int sample_backbuf(int x, int y)
644 {
645         unsigned int col;
646         
647         if(x>=curarea->winx || y>=curarea->winy) return 0;
648         
649         x+= curarea->winrct.xmin;
650         y+= curarea->winrct.ymin;
651
652 #ifdef __APPLE__
653         glReadBuffer(GL_AUX0);
654 #endif
655         glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
656         glReadBuffer(GL_BACK);  
657
658         if(G.order==B_ENDIAN) SWITCH_INT(col);
659                 
660         return framebuffer_to_index(col);
661 }
662
663 static int calc_vp_alpha_dl(VPaint *vp, DerivedMesh *dm, int vert, short *mval)
664 {
665         float co[3], no[3];
666         float fac, dx, dy;
667         int alpha;
668         short vertco[2];
669         
670         if(vp->flag & VP_SOFT) {
671                 dm->getVertCo(dm, vert, co);
672
673                 project_short_noclip(co, vertco);
674                 dx= mval[0]-vertco[0];
675                 dy= mval[1]-vertco[1];
676                 
677                 fac= sqrt(dx*dx + dy*dy);
678                 if(fac > vp->size) return 0;
679
680                 alpha= 255.0*vp->a*(1.0-fac/vp->size);
681         }
682         else {
683                 alpha= 255.0*vp->a;
684         }
685
686         if(vp->flag & VP_NORMALS) {
687                 dm->getVertNo(dm, vert, no);
688
689                         /* transpose ! */
690                 fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
691                 if(fac>0.0) {
692                         dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
693                         dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
694                         
695                         alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
696                 }
697                 else return 0;
698         }
699         
700         return alpha;
701 }
702
703
704 void wpaint_undo (void)
705 {
706         Object *ob= OBACT;
707         Mesh    *me;
708         MDeformVert *swapbuf;
709
710         me = get_mesh(ob);
711         if (!me)
712                 return;
713
714         if (!wpaintundobuf)
715                 return;
716
717         if (!me->dvert)
718                 return;
719
720         if (totwpaintundo != me->totvert)
721                 return;
722
723         swapbuf= me->dvert;
724
725         /* copy undobuf to mesh */
726         me->dvert= MEM_mallocN(sizeof(MDeformVert)*me->totvert, "deformVert");
727         copy_dverts(me->dvert, wpaintundobuf, totwpaintundo);
728         
729         /* copy previous mesh to undo */
730         free_dverts(wpaintundobuf, me->totvert);
731         wpaintundobuf= MEM_mallocN(sizeof(MDeformVert)*me->totvert, "wpaintundo");
732         copy_dverts(wpaintundobuf, swapbuf, totwpaintundo);
733         
734         /* now free previous mesh dverts */
735         free_dverts(swapbuf, me->totvert);
736
737         DAG_object_flush_update(G.scene, ob->parent, OB_RECALC_DATA);
738         scrarea_do_windraw(curarea);
739         
740 }
741
742 void copy_wpaint_undo (MDeformVert *dverts, int dcount)
743 {
744         if (wpaintundobuf)
745                 free_dverts(wpaintundobuf, totwpaintundo);
746
747         wpaintundobuf = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaintundo");
748         totwpaintundo = dcount;
749         copy_dverts (wpaintundobuf, dverts, dcount);
750 }
751
752 static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval)
753 {
754         
755         if(dw==NULL || uw==NULL) return;
756         
757         if(Gwp.mode==VP_MIX || Gwp.mode==VP_FILT)
758                 dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
759         else if(Gwp.mode==VP_ADD)
760                 dw->weight += paintval*alpha;
761         else if(Gwp.mode==VP_SUB) 
762                 dw->weight -= paintval*alpha;
763         else if(Gwp.mode==VP_MUL) 
764                 /* first mul, then blend the fac */
765                 dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight;
766         
767         CLAMP(dw->weight, 0.0f, 1.0f);
768         
769         /* if no spray, clip result with orig weight & orig alpha */
770         if((Gwp.flag & VP_SPRAY)==0) {
771                 float testw=0.0f;
772                 
773                 alpha= Gwp.a;
774                 
775                 if(Gwp.mode==VP_MIX || Gwp.mode==VP_FILT)
776                         testw = paintval*alpha + uw->weight*(1.0-alpha);
777                 else if(Gwp.mode==VP_ADD)
778                         testw = uw->weight + paintval*alpha;
779                 else if(Gwp.mode==VP_SUB) 
780                         testw = uw->weight - paintval*alpha;
781                 else if(Gwp.mode==VP_MUL) 
782                         /* first mul, then blend the fac */
783                         testw = ((1.0-alpha) + alpha*paintval)*uw->weight;
784                 
785                 CLAMP(testw, 0.0f, 1.0f);
786                 
787                 if( testw<uw->weight ) {
788                         if(dw->weight < testw) dw->weight= testw;
789                         else if(dw->weight > uw->weight) dw->weight= uw->weight;
790                 }
791                 else {
792                         if(dw->weight > testw) dw->weight= testw;
793                         else if(dw->weight < uw->weight) dw->weight= uw->weight;
794                 }
795         }
796         
797 }
798
799 static MDeformWeight *get_defweight(MDeformVert *dv, int defgroup)
800 {
801         int i;
802         for (i=0; i<dv->totweight; i++){
803                 if (dv->dw[i].def_nr == defgroup)
804                         return dv->dw+i;
805         }
806         return NULL;
807 }
808
809 /* used for 3d view */
810 /* cant sample frontbuf, weight colors are interpolated too unpredictable */
811 /* so we return the closest value to vertex, wich is actually correct anyway */
812 void sample_wpaint()
813 {
814         extern float editbutvweight;
815         Object *ob= OBACT;
816         Mesh *me= get_mesh(ob);
817         int index;
818         short mval[2], sco[2];
819         
820         getmouseco_areawin(mval);
821         index= sample_backbuf(mval[0], mval[1]);
822         
823         if(index && index<=me->totface) {
824                 MFace *mface;
825                 DerivedMesh *dm;
826                 MDeformWeight *dw;
827                 float w1, w2, w3, w4, co[3], fac;
828                 int needsFree;
829                 
830                 dm = mesh_get_derived_deform(ob, &needsFree);
831                 
832                 mface= ((MFace *)me->mface) + index-1;
833                 
834                 /* calc 3 or 4 corner weights */
835                 dm->getVertCo(dm, mface->v1, co);
836                 project_short_noclip(co, sco);
837                 w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
838                 
839                 dm->getVertCo(dm, mface->v2, co);
840                 project_short_noclip(co, sco);
841                 w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
842                 
843                 dm->getVertCo(dm, mface->v3, co);
844                 project_short_noclip(co, sco);
845                 w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
846                 
847                 if(mface->v4) {
848                         dm->getVertCo(dm, mface->v4, co);
849                         project_short_noclip(co, sco);
850                         w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
851                 }
852                 else w4= 1.0e10;
853                 
854                 fac= MIN4(w1, w2, w3, w4);
855                 if(w1==fac) {
856                         dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
857                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
858                 }
859                 else if(w2==fac) {
860                         dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
861                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
862                 }
863                 else if(w3==fac) {
864                         dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
865                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
866                 }
867                 else if(w4==fac) {
868                         if(mface->v4) {
869                                 dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
870                                 if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
871                         }
872                 }
873                 
874                 if (needsFree)
875                         dm->release(dm);
876                 
877         }
878         allqueue(REDRAWBUTSEDIT, 0);
879         
880 }
881
882
883 void weight_paint(void)
884 {
885         extern float editbutvweight;
886         MDeformWeight   *dw, *uw;
887         Object *ob; 
888         Mesh *me;
889         MFace *mface;
890         TFace *tface;
891         float mat[4][4], imat[4][4], paintweight;
892         int index, totindex, alpha, totw;
893         short mval[2], mvalo[2], firsttime=1, mousebut;
894
895         if((G.f & G_WEIGHTPAINT)==0) return;
896         if(G.obedit) return;
897         
898         if(G.qual & LR_CTRLKEY) {
899                 sample_wpaint();
900                 return;
901         }
902         
903         if(indexar==NULL) init_vertexpaint();
904         
905         ob= OBACT;
906         if(ob->id.lib) return;
907
908         me= get_mesh(ob);
909         if(me==NULL || me->totface==0) return;
910         
911         /* if nothing was added yet, we make dverts and a vertex deform group */
912         if (!me->dvert)
913                 create_dverts(me);
914         /* this happens on a Bone select, when no vgroup existed yet */
915         if(ob->actdef==0) {
916                 if(ob->parent && (ob->parent->flag & OB_POSEMODE)) {
917                         bPoseChannel *pchan;
918                         for(pchan= ob->parent->pose->chanbase.first; pchan; pchan= pchan->next)
919                                 if(pchan->bone->flag & SELECT)
920                                         break;
921                         if(pchan) {
922                                 bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
923                                 if(dg==NULL)
924                                         dg= add_defgroup_name(ob, pchan->name); // sets actdef
925                                 else
926                                         ob->actdef= get_defgroup_num(ob, dg);
927                                 allqueue(REDRAWBUTSEDIT, 0);
928                         }
929                 }
930         }
931         if(ob->defbase.first==NULL) {
932                 add_defgroup(ob);
933                 allqueue(REDRAWBUTSEDIT, 0);
934         }       
935         
936         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
937         
938         persp(PERSP_VIEW);
939         /* imat for normals */
940         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
941         Mat4Invert(imat, mat);
942         Mat3CpyMat4(vpimat, imat);
943         
944         /* load projection matrix */
945         mymultmatrix(ob->obmat);
946         mygetsingmatrix(mat);
947         myloadmatrix(G.vd->viewmat);
948         
949         getmouseco_areawin(mvalo);
950         
951         if(me->tface) tface_to_mcol(me);
952         copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
953         copy_wpaint_undo(me->dvert, me->totvert);
954         
955         getmouseco_areawin(mval);
956         mvalo[0]= mval[0];
957         mvalo[1]= mval[1];
958         
959         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
960         else mousebut = L_MOUSE;
961         
962         while (get_mbut() & mousebut) {
963                 getmouseco_areawin(mval);
964                 
965                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
966                         DerivedMesh *dm;
967                         int needsFree;
968
969                         firsttime= 0;
970                         
971                         /* which faces are involved */
972                         if(Gwp.flag & VP_AREA) {
973                                 totindex= sample_backbuf_area(mval[0], mval[1], Gwp.size);
974                         }
975                         else {
976                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
977                                 if(indexar[0]) totindex= 1;
978                                 else totindex= 0;
979                         }
980                         
981                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
982                         
983                         if(Gwp.flag & VP_COLINDEX) {
984                                 for(index=0; index<totindex; index++) {
985                                         if(indexar[index] && indexar[index]<=me->totface) {
986                                         
987                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
988                                         
989                                                 if(mface->mat_nr!=ob->actcol-1) {
990                                                         indexar[index]= 0;
991                                                 }
992                                         }                                       
993                                 }
994                         }
995
996                         if((G.f & G_FACESELECT) && me->tface) {
997                                 for(index=0; index<totindex; index++) {
998                                         if(indexar[index] && indexar[index]<=me->totface) {
999                                         
1000                                                 tface= ((TFace *)me->tface) + (indexar[index]-1);
1001                                         
1002                                                 if((tface->flag & TF_SELECT)==0) {
1003                                                         indexar[index]= 0;
1004                                                 }
1005                                         }                                       
1006                                 }
1007                         }
1008                         
1009                         /* make sure each vertex gets treated only once */
1010                         /* and calculate filter weight */
1011                         totw= 0;
1012                         if(Gwp.mode==VP_FILT) 
1013                                 paintweight= 0.0f;
1014                         else
1015                                 paintweight= editbutvweight;
1016                         
1017                         for(index=0; index<totindex; index++) {
1018                                 if(indexar[index] && indexar[index]<=me->totface) {
1019                                         mface= me->mface + (indexar[index]-1);
1020                                         
1021                                         (me->dvert+mface->v1)->flag= 1;
1022                                         (me->dvert+mface->v2)->flag= 1;
1023                                         (me->dvert+mface->v3)->flag= 1;
1024                                         if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1025                                         
1026                                         if(Gwp.mode==VP_FILT) {
1027                                                 dw= verify_defweight(me->dvert+mface->v1, ob->actdef-1);
1028                                                 if(dw) {paintweight+= dw->weight; totw++;}
1029                                                 dw= verify_defweight(me->dvert+mface->v2, ob->actdef-1);
1030                                                 if(dw) {paintweight+= dw->weight; totw++;}
1031                                                 dw= verify_defweight(me->dvert+mface->v3, ob->actdef-1);
1032                                                 if(dw) {paintweight+= dw->weight; totw++;}
1033                                                 if(mface->v4) {
1034                                                         dw= verify_defweight(me->dvert+mface->v4, ob->actdef-1);
1035                                                         if(dw) {paintweight+= dw->weight; totw++;}
1036                                                 }
1037                                         }
1038                                 }
1039                         }
1040                         
1041                         if(Gwp.mode==VP_FILT) 
1042                                 paintweight/= (float)totw;
1043                         
1044                         dm = mesh_get_derived_deform(ob, &needsFree);
1045
1046                         for(index=0; index<totindex; index++) {
1047                                 
1048                                 if(indexar[index] && indexar[index]<=me->totface) {
1049                                         mface= me->mface + (indexar[index]-1);
1050                                         
1051                                         if((me->dvert+mface->v1)->flag) {
1052                                                 alpha= calc_vp_alpha_dl(&Gwp, dm, mface->v1, mval);
1053                                                 if(alpha) {
1054                                                         dw= verify_defweight(me->dvert+mface->v1, ob->actdef-1);
1055                                                         uw= verify_defweight(wpaintundobuf+mface->v1, ob->actdef-1);
1056                                                         wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1057                                                 }
1058                                                 (me->dvert+mface->v1)->flag= 0;
1059                                         }
1060                                         
1061                                         if((me->dvert+mface->v2)->flag) {
1062                                                 alpha= calc_vp_alpha_dl(&Gwp, dm, mface->v2, mval);
1063                                                 if(alpha) {
1064                                                         dw= verify_defweight(me->dvert+mface->v2, ob->actdef-1);
1065                                                         uw= verify_defweight(wpaintundobuf+mface->v2, ob->actdef-1);
1066                                                         wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1067                                                 }
1068                                                 (me->dvert+mface->v2)->flag= 0;
1069                                         }
1070                                         
1071                                         if((me->dvert+mface->v3)->flag) {
1072                                                 alpha= calc_vp_alpha_dl(&Gwp, dm, mface->v3, mval);
1073                                                 if(alpha) {
1074                                                         dw= verify_defweight(me->dvert+mface->v3, ob->actdef-1);
1075                                                         uw= verify_defweight(wpaintundobuf+mface->v3, ob->actdef-1);
1076                                                         wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1077                                                 }
1078                                                 (me->dvert+mface->v3)->flag= 0;
1079                                         }
1080                                         
1081                                         if((me->dvert+mface->v4)->flag) {
1082                                                 if(mface->v4) {
1083                                                         alpha= calc_vp_alpha_dl(&Gwp, dm, mface->v4, mval);
1084                                                         if(alpha) {
1085                                                                 dw= verify_defweight(me->dvert+mface->v4, ob->actdef-1);
1086                                                                 uw= verify_defweight(wpaintundobuf+mface->v4, ob->actdef-1);
1087                                                                 wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1088                                                         }
1089                                                         (me->dvert+mface->v4)->flag= 0;
1090                                                 }
1091                                         }
1092                                 }
1093                         }
1094                         if (needsFree)
1095                                 dm->release(dm);
1096                         
1097                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1098                         
1099                 }
1100                 else BIF_wait_for_statechange();
1101                 
1102                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1103
1104                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1105                         scrarea_do_windraw(curarea);
1106                         
1107                         if(Gwp.flag & (VP_AREA|VP_SOFT)) {
1108                                 /* draw circle in backbuf! */
1109                                 persp(PERSP_WIN);
1110                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size);
1111                                 persp(PERSP_VIEW);
1112                         }
1113
1114                         screen_swapbuffers();
1115                         backdrawview3d(0);
1116         
1117                         mvalo[0]= mval[0];
1118                         mvalo[1]= mval[1];
1119                 }
1120         }
1121         
1122         if(me->tface) {
1123                 MEM_freeN(me->mcol);
1124                 me->mcol= 0;
1125         }
1126         
1127         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1128         // this flag is event for softbody to refresh weightpaint values
1129         if(ob->soft) ob->softflag |= OB_SB_REDO;
1130         
1131         allqueue(REDRAWVIEW3D, 0);
1132
1133 }
1134
1135 void vertex_paint()
1136 {
1137         Object *ob;
1138         Mesh *me;
1139         MFace *mface;
1140         TFace *tface;
1141         float mat[4][4], imat[4][4];
1142         unsigned int paintcol=0, *mcol, *mcolorig, fcol1, fcol2;
1143         int index, alpha, totindex;
1144         short mval[2], mvalo[2], firsttime=1, mousebut;
1145         
1146         if((G.f & G_VERTEXPAINT)==0) return;
1147         if(G.obedit) return;
1148         
1149         if(indexar==NULL) init_vertexpaint();
1150         
1151         ob= OBACT;
1152         if(ob->id.lib) return;
1153
1154         me= get_mesh(ob);
1155         if(me==NULL || me->totface==0) return;
1156         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
1157         
1158         if(me->tface==NULL && me->mcol==NULL) make_vertexcol();
1159
1160         if(me->tface==NULL && me->mcol==NULL) return;
1161         
1162         persp(PERSP_VIEW);
1163         /* imat for normals */
1164         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
1165         Mat4Invert(imat, mat);
1166         Mat3CpyMat4(vpimat, imat);
1167         
1168         /* load projection matrix */
1169         mymultmatrix(ob->obmat);
1170         mygetsingmatrix(mat);
1171         myloadmatrix(G.vd->viewmat);
1172         
1173         paintcol= vpaint_get_current_col();
1174         
1175         getmouseco_areawin(mvalo);
1176         
1177         if(me->tface) tface_to_mcol(me);
1178         copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
1179         
1180         getmouseco_areawin(mval);
1181         mvalo[0]= mval[0];
1182         mvalo[1]= mval[1];
1183         
1184         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1185         else mousebut = L_MOUSE;
1186         
1187         while (get_mbut() & mousebut) {
1188                 getmouseco_areawin(mval);
1189                 
1190                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1191                         DerivedMesh *dm;
1192                         int needsFree;
1193
1194                         firsttime= 0;
1195
1196                         /* which faces are involved */
1197                         if(Gvp.flag & VP_AREA) {
1198                                 totindex= sample_backbuf_area(mval[0], mval[1], Gvp.size);
1199                         }
1200                         else {
1201                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
1202                                 if(indexar[0]) totindex= 1;
1203                                 else totindex= 0;
1204                         }
1205                         
1206                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1207                         
1208                         if(Gvp.flag & VP_COLINDEX) {
1209                                 for(index=0; index<totindex; index++) {
1210                                         if(indexar[index] && indexar[index]<=me->totface) {
1211                                         
1212                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1213                                         
1214                                                 if(mface->mat_nr!=ob->actcol-1) {
1215                                                         indexar[index]= 0;
1216                                                 }
1217                                         }                                       
1218                                 }
1219                         }
1220                         if((G.f & G_FACESELECT) && me->tface) {
1221                                 for(index=0; index<totindex; index++) {
1222                                         if(indexar[index] && indexar[index]<=me->totface) {
1223                                         
1224                                                 tface= ((TFace *)me->tface) + (indexar[index]-1);
1225                                         
1226                                                 if((tface->flag & TF_SELECT)==0) {
1227                                                         indexar[index]= 0;
1228                                                 }
1229                                         }                                       
1230                                 }
1231                         }
1232
1233                         dm= mesh_get_derived_deform(ob, &needsFree);
1234                         for(index=0; index<totindex; index++) {
1235
1236                                 if(indexar[index] && indexar[index]<=me->totface) {
1237                                 
1238                                         mface= ((MFace *)me->mface) + (indexar[index]-1);
1239                                         mcol=     ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
1240                                         mcolorig= ( (unsigned int *)vpaintundobuf) + 4*(indexar[index]-1);
1241
1242                                         if(Gvp.mode==VP_FILT) {
1243                                                 fcol1= mcol_blend( mcol[0], mcol[1], 128);
1244                                                 if(mface->v4) {
1245                                                         fcol2= mcol_blend( mcol[2], mcol[3], 128);
1246                                                         paintcol= mcol_blend( fcol1, fcol2, 128);
1247                                                 }
1248                                                 else {
1249                                                         paintcol= mcol_blend( mcol[2], fcol1, 170);
1250                                                 }
1251                                                 
1252                                         }
1253                                         
1254                                         alpha= calc_vp_alpha_dl(&Gvp, dm, mface->v1, mval);
1255                                         if(alpha) vpaint_blend( mcol, mcolorig, paintcol, alpha);
1256                                         
1257                                         alpha= calc_vp_alpha_dl(&Gvp, dm, mface->v2, mval);
1258                                         if(alpha) vpaint_blend( mcol+1, mcolorig+1, paintcol, alpha);
1259         
1260                                         alpha= calc_vp_alpha_dl(&Gvp, dm, mface->v3, mval);
1261                                         if(alpha) vpaint_blend( mcol+2, mcolorig+2, paintcol, alpha);
1262
1263                                         if(mface->v4) {
1264                                                 alpha= calc_vp_alpha_dl(&Gvp, dm, mface->v4, mval);
1265                                                 if(alpha) vpaint_blend( mcol+3, mcolorig+3, paintcol, alpha);
1266                                         }
1267                                 }
1268                         }
1269                         if (needsFree)
1270                                 dm->release(dm);
1271                                 
1272                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1273                         
1274                         do_shared_vertexcol(me);
1275                         if(me->tface) {
1276                                 mcol_to_tface(me, 0);
1277                         }
1278         
1279                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1280                         scrarea_do_windraw(curarea);
1281
1282                         if(Gvp.flag & (VP_AREA|VP_SOFT)) {
1283                                 /* draw circle in backbuf! */
1284                                 persp(PERSP_WIN);
1285                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gvp.size);
1286                                 persp(PERSP_VIEW);
1287                         }
1288                         screen_swapbuffers();
1289                         backdrawview3d(0);
1290                         
1291                         mvalo[0]= mval[0];
1292                         mvalo[1]= mval[1];
1293                 }
1294                 else BIF_wait_for_statechange();
1295         }
1296         
1297         if(me->tface) {
1298                 MEM_freeN(me->mcol);
1299                 me->mcol= 0;
1300         }
1301         
1302         allqueue(REDRAWVIEW3D, 0);
1303 }
1304
1305 void set_wpaint(void)           /* toggle */
1306 {               
1307         Object *ob;
1308         Mesh *me;
1309         
1310         scrarea_queue_headredraw(curarea);
1311         ob= OBACT;
1312         if(ob->id.lib) return;
1313         me= get_mesh(ob);
1314                 
1315         if(me && me->totface>=MAXINDEX) {
1316                 error("Maximum number of faces: %d", MAXINDEX-1);
1317                 G.f &= ~G_WEIGHTPAINT;
1318                 return;
1319         }
1320         
1321         if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
1322         else G.f |= G_WEIGHTPAINT;
1323         
1324         allqueue(REDRAWVIEW3D, 0);
1325         allqueue(REDRAWBUTSEDIT, 0);
1326         
1327                 /* Weightpaint works by overriding colors in mesh,
1328                  * so need to make sure we recalc on enter and
1329                  * exit (exit needs doing regardless because we
1330                  * should redeform).
1331                  */
1332         if (me) {
1333                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1334         }
1335
1336         if(G.f & G_WEIGHTPAINT) {
1337                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1338         }
1339         else {
1340                 freefastshade();        /* to be sure */
1341                 if(!(G.f & G_FACESELECT))
1342                         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1343         }
1344 }
1345
1346
1347 void set_vpaint(void)           /* toggle */
1348 {               
1349         Object *ob;
1350         Mesh *me;
1351         
1352         scrarea_queue_headredraw(curarea);
1353         ob= OBACT;
1354         if(ob->id.lib) {
1355                 G.f &= ~G_VERTEXPAINT;
1356                 return;
1357         }
1358         
1359         me= get_mesh(ob);
1360         
1361         if(me && me->totface>=MAXINDEX) {
1362                 error("Maximum number of faces: %d", MAXINDEX-1);
1363                 G.f &= ~G_VERTEXPAINT;
1364                 return;
1365         }
1366         
1367         if(me && me->tface==NULL && me->mcol==NULL) make_vertexcol();
1368         
1369         if(G.f & G_VERTEXPAINT){
1370                 G.f &= ~G_VERTEXPAINT;
1371         }
1372         else {
1373                 G.f |= G_VERTEXPAINT;
1374                 /* Turn off weight painting */
1375                 if (G.f & G_WEIGHTPAINT)
1376                         set_wpaint();
1377         }
1378         
1379         allqueue(REDRAWVIEW3D, 0);
1380         allqueue(REDRAWBUTSEDIT, 0);
1381         
1382         if(G.f & G_VERTEXPAINT) {
1383                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1384         }
1385         else {
1386                 freefastshade();        /* to be sure */
1387                 if (me) {
1388                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1389                 }
1390                 if((G.f & G_FACESELECT)==0) setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1391         }
1392 }
1393