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