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