Made the Multi-Paint check box control what was being drawn so that it doesn't always...
[blender.git] / source / blender / editors / sculpt_paint / paint_vertex.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/editors/sculpt_paint/paint_vertex.c
31  *  \ingroup edsculpt
32  */
33
34
35 #include <math.h>
36 #include <string.h>
37
38 #ifdef WIN32
39 #include <io.h>
40 #else
41 #include <unistd.h>
42 #endif   
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_utildefines.h"
49 #include "BLI_ghash.h"
50
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53
54 #include "DNA_armature_types.h"
55 #include "DNA_mesh_types.h"
56 #include "DNA_particle_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_brush_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_meshdata_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 #include "BKE_DerivedMesh.h"
66 #include "BKE_action.h"
67 #include "BKE_brush.h"
68 #include "BKE_context.h"
69 #include "BKE_depsgraph.h"
70 #include "BKE_deform.h"
71 #include "BKE_mesh.h"
72 #include "BKE_modifier.h"
73 #include "BKE_object.h"
74 #include "BKE_paint.h"
75
76
77 #include "WM_api.h"
78 #include "WM_types.h"
79
80
81 #include "ED_armature.h"
82 #include "ED_mesh.h"
83 #include "ED_screen.h"
84 #include "ED_view3d.h"
85
86 #include "paint_intern.h"
87
88 /* brush->vertexpaint_tool */
89 #define VP_MIX  0
90 #define VP_ADD  1
91 #define VP_SUB  2
92 #define VP_MUL  3
93 #define VP_BLUR 4
94 #define VP_LIGHTEN      5
95 #define VP_DARKEN       6
96
97 /* polling - retrieve whether cursor should be set or operator should be done */
98
99
100 /* Returns true if vertex paint mode is active */
101 int vertex_paint_mode_poll(bContext *C)
102 {
103         Object *ob = CTX_data_active_object(C);
104
105         return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totface;
106 }
107
108 int vertex_paint_poll(bContext *C)
109 {
110         if(vertex_paint_mode_poll(C) && 
111            paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) {
112                 ScrArea *sa= CTX_wm_area(C);
113                 if(sa->spacetype==SPACE_VIEW3D) {
114                         ARegion *ar= CTX_wm_region(C);
115                         if(ar->regiontype==RGN_TYPE_WINDOW)
116                                 return 1;
117                         }
118                 }
119         return 0;
120 }
121
122 int weight_paint_mode_poll(bContext *C)
123 {
124         Object *ob = CTX_data_active_object(C);
125
126         return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totface;
127 }
128
129 int weight_paint_poll(bContext *C)
130 {
131         Object *ob= CTX_data_active_object(C);
132         ScrArea *sa;
133
134         if(     (ob != NULL) &&
135                 (ob->mode & OB_MODE_WEIGHT_PAINT) &&
136                 (paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
137                 (sa= CTX_wm_area(C)) &&
138                 (sa->spacetype == SPACE_VIEW3D)
139         ) {
140                 ARegion *ar= CTX_wm_region(C);
141                 if(ar->regiontype==RGN_TYPE_WINDOW) {
142                         return 1;
143                 }
144         }
145         return 0;
146 }
147
148 static VPaint *new_vpaint(int wpaint)
149 {
150         VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint");
151         
152         vp->flag= VP_AREA+VP_SPRAY;
153         
154         if(wpaint)
155                 vp->flag= VP_AREA;
156
157         return vp;
158 }
159
160 static int *get_indexarray(Mesh *me)
161 {
162         return MEM_mallocN(sizeof(int)*(me->totface+1), "vertexpaint");
163 }
164
165
166 /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! 
167    so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
168
169 static unsigned int rgba_to_mcol(float r, float g, float b, float a)
170 {
171         int ir, ig, ib, ia;
172         unsigned int col;
173         char *cp;
174         
175         ir= floor(255.0f * r);
176         if(ir<0) ir= 0; else if(ir>255) ir= 255;
177         ig= floor(255.0f * g);
178         if(ig<0) ig= 0; else if(ig>255) ig= 255;
179         ib= floor(255.0f * b);
180         if(ib<0) ib= 0; else if(ib>255) ib= 255;
181         ia= floor(255.0f * a);
182         if(ia<0) ia= 0; else if(ia>255) ia= 255;
183         
184         cp= (char *)&col;
185         cp[0]= ia;
186         cp[1]= ib;
187         cp[2]= ig;
188         cp[3]= ir;
189         
190         return col;
191         
192 }
193
194 unsigned int vpaint_get_current_col(VPaint *vp)
195 {
196         Brush *brush = paint_brush(&vp->paint);
197         return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
198 }
199
200 static void do_shared_vertexcol(Mesh *me)
201 {
202         /* if no mcol: do not do */
203         /* if tface: only the involved faces, otherwise all */
204         MFace *mface;
205         MTFace *tface;
206         int a;
207         short *scolmain, *scol;
208         char *mcol;
209         
210         if(me->mcol==NULL || me->totvert==0 || me->totface==0) return;
211         
212         scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
213         
214         tface= me->mtface;
215         mface= me->mface;
216         mcol= (char *)me->mcol;
217         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
218                 if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
219                         scol= scolmain+4*mface->v1;
220                         scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
221                         scol= scolmain+4*mface->v2;
222                         scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
223                         scol= scolmain+4*mface->v3;
224                         scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
225                         if(mface->v4) {
226                                 scol= scolmain+4*mface->v4;
227                                 scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
228                         }
229                 }
230                 if(tface) tface++;
231         }
232         
233         a= me->totvert;
234         scol= scolmain;
235         while(a--) {
236                 if(scol[0]>1) {
237                         scol[1]/= scol[0];
238                         scol[2]/= scol[0];
239                         scol[3]/= scol[0];
240                 }
241                 scol+= 4;
242         }
243         
244         tface= me->mtface;
245         mface= me->mface;
246         mcol= (char *)me->mcol;
247         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
248                 if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
249                         scol= scolmain+4*mface->v1;
250                         mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
251                         scol= scolmain+4*mface->v2;
252                         mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
253                         scol= scolmain+4*mface->v3;
254                         mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
255                         if(mface->v4) {
256                                 scol= scolmain+4*mface->v4;
257                                 mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
258                         }
259                 }
260                 if(tface) tface++;
261         }
262
263         MEM_freeN(scolmain);
264 }
265
266 static void make_vertexcol(Object *ob)  /* single ob */
267 {
268         Mesh *me;
269         if(!ob || ob->id.lib) return;
270         me= get_mesh(ob);
271         if(me==NULL) return;
272         if(me->edit_mesh) return;
273
274         /* copies from shadedisplist to mcol */
275         if(!me->mcol) {
276                 CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
277                 mesh_update_customdata_pointers(me);
278         }
279
280         //if(shade)
281         //      shadeMeshMCol(scene, ob, me);
282         //else
283
284         memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
285         
286         DAG_id_tag_update(&me->id, 0);
287         
288 }
289
290 static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
291 {
292         if(vp->vpaint_prev) {
293                 MEM_freeN(vp->vpaint_prev);
294                 vp->vpaint_prev= NULL;
295         }
296         vp->tot= tot;   
297         
298         if(mcol==NULL || tot==0) return;
299         
300         vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
301         memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
302         
303 }
304
305 static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
306 {
307         if (wp->wpaint_prev) {
308                 free_dverts(wp->wpaint_prev, wp->tot);
309                 wp->wpaint_prev= NULL;
310         }
311         
312         if(dverts && dcount) {
313                 
314                 wp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
315                 wp->tot = dcount;
316                 copy_dverts (wp->wpaint_prev, dverts, dcount);
317         }
318 }
319
320
321 void vpaint_fill(Object *ob, unsigned int paintcol)
322 {
323         Mesh *me;
324         MFace *mf;
325         unsigned int *mcol;
326         int i, selected;
327
328         me= get_mesh(ob);
329         if(me==NULL || me->totface==0) return;
330
331         if(!me->mcol)
332                 make_vertexcol(ob);
333
334         selected= (me->editflag & ME_EDIT_PAINT_MASK);
335
336         mf = me->mface;
337         mcol = (unsigned int*)me->mcol;
338         for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
339                 if (!selected || mf->flag & ME_FACE_SEL) {
340                         mcol[0] = paintcol;
341                         mcol[1] = paintcol;
342                         mcol[2] = paintcol;
343                         mcol[3] = paintcol;
344                 }
345         }
346         
347         DAG_id_tag_update(&me->id, 0);
348 }
349
350 /* fills in the selected faces with the current weight and vertex group */
351 void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
352 {
353         Mesh *me;
354         MFace *mface;
355         MDeformWeight *dw, *uw;
356         int *indexar;
357         int index, vgroup;
358         unsigned int faceverts[5]={0,0,0,0,0};
359         unsigned char i;
360         int vgroup_mirror= -1;
361         int selected;
362         
363         me= ob->data;
364         if(me==NULL || me->totface==0 || me->dvert==NULL || !me->mface) return;
365
366         selected= (me->editflag & ME_EDIT_PAINT_MASK);
367
368         indexar= get_indexarray(me);
369
370         if(selected) {
371                 for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
372                         if((mface->flag & ME_FACE_SEL)==0)
373                                 indexar[index]= 0;
374                         else
375                                 indexar[index]= index+1;
376                 }
377         }
378         else {
379                 for(index=0; index<me->totface; index++)
380                         indexar[index]= index+1;
381         }
382         
383         vgroup= ob->actdef-1;
384         
385         /* directly copied from weight_paint, should probaby split into a separate function */
386         /* if mirror painting, find the other group */          
387         if(me->editflag & ME_EDIT_MIRROR_X) {
388                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
389                 if(defgroup) {
390                         bDeformGroup *curdef;
391                         int actdef= 0;
392                         char name[32];
393
394                         flip_side_name(name, defgroup->name, FALSE);
395
396                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
397                                 if (!strcmp(curdef->name, name))
398                                         break;
399                         if(curdef==NULL) {
400                                 int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
401                                 curdef= ED_vgroup_add_name (ob, name);
402                                 ob->actdef= olddef;
403                         }
404                         
405                         if(curdef && curdef!=defgroup)
406                                 vgroup_mirror= actdef;
407                 }
408         }
409         /* end copy from weight_paint*/
410         
411         copy_wpaint_prev(wp, me->dvert, me->totvert);
412         
413         for(index=0; index<me->totface; index++) {
414                 if(indexar[index] && indexar[index]<=me->totface) {
415                         mface= me->mface + (indexar[index]-1);
416                         /* just so we can loop through the verts */
417                         faceverts[0]= mface->v1;
418                         faceverts[1]= mface->v2;
419                         faceverts[2]= mface->v3;
420                         faceverts[3]= mface->v4;
421                         for (i=0; i<3 || faceverts[i]; i++) {
422                                 if(!((me->dvert+faceverts[i])->flag)) {
423                                         dw= defvert_verify_index(me->dvert+faceverts[i], vgroup);
424                                         if(dw) {
425                                                 uw= defvert_verify_index(wp->wpaint_prev+faceverts[i], vgroup);
426                                                 uw->weight= dw->weight; /* set the undo weight */
427                                                 dw->weight= paintweight;
428                                                 
429                                                 if(me->editflag & ME_EDIT_MIRROR_X) {   /* x mirror painting */
430                                                         int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
431                                                         if(j>=0) {
432                                                                 /* copy, not paint again */
433                                                                 if(vgroup_mirror != -1) {
434                                                                         dw= defvert_verify_index(me->dvert+j, vgroup_mirror);
435                                                                         uw= defvert_verify_index(wp->wpaint_prev+j, vgroup_mirror);
436                                                                 } else {
437                                                                         dw= defvert_verify_index(me->dvert+j, vgroup);
438                                                                         uw= defvert_verify_index(wp->wpaint_prev+j, vgroup);
439                                                                 }
440                                                                 uw->weight= dw->weight; /* set the undo weight */
441                                                                 dw->weight= paintweight;
442                                                         }
443                                                 }
444                                         }
445                                         (me->dvert+faceverts[i])->flag= 1;
446                                 }
447                         }
448                 }
449         }
450         
451         index=0;
452         while (index<me->totvert) {
453                 (me->dvert+index)->flag= 0;
454                 index++;
455         }
456         
457         MEM_freeN(indexar);
458         copy_wpaint_prev(wp, NULL, 0);
459
460         DAG_id_tag_update(&me->id, 0);
461 }
462
463 /* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator
464  
465 void vpaint_dogamma(Scene *scene)
466 {
467         VPaint *vp= scene->toolsettings->vpaint;
468         Mesh *me;
469         Object *ob;
470         float igam, fac;
471         int a, temp;
472         unsigned char *cp, gamtab[256];
473
474         ob= OBACT;
475         me= get_mesh(ob);
476
477         if(!(ob->mode & OB_MODE_VERTEX_PAINT)) return;
478         if(me==0 || me->mcol==0 || me->totface==0) return;
479
480         igam= 1.0/vp->gamma;
481         for(a=0; a<256; a++) {
482                 
483                 fac= ((float)a)/255.0;
484                 fac= vp->mul*pow( fac, igam);
485                 
486                 temp= 255.9*fac;
487                 
488                 if(temp<=0) gamtab[a]= 0;
489                 else if(temp>=255) gamtab[a]= 255;
490                 else gamtab[a]= temp;
491         }
492
493         a= 4*me->totface;
494         cp= (unsigned char *)me->mcol;
495         while(a--) {
496                 
497                 cp[1]= gamtab[ cp[1] ];
498                 cp[2]= gamtab[ cp[2] ];
499                 cp[3]= gamtab[ cp[3] ];
500                 
501                 cp+= 4;
502         }
503 }
504  */
505
506 static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
507 {
508         char *cp1, *cp2, *cp;
509         int mfac;
510         unsigned int col=0;
511         
512         if(fac==0) return col1;
513         if(fac>=255) return col2;
514
515         mfac= 255-fac;
516         
517         cp1= (char *)&col1;
518         cp2= (char *)&col2;
519         cp=  (char *)&col;
520         
521         cp[0]= 255;
522         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
523         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
524         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
525         
526         return col;
527 }
528
529 static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
530 {
531         char *cp1, *cp2, *cp;
532         int temp;
533         unsigned int col=0;
534         
535         if(fac==0) return col1;
536         
537         cp1= (char *)&col1;
538         cp2= (char *)&col2;
539         cp=  (char *)&col;
540         
541         cp[0]= 255;
542         temp= cp1[1] + ((fac*cp2[1])/255);
543         if(temp>254) cp[1]= 255; else cp[1]= temp;
544         temp= cp1[2] + ((fac*cp2[2])/255);
545         if(temp>254) cp[2]= 255; else cp[2]= temp;
546         temp= cp1[3] + ((fac*cp2[3])/255);
547         if(temp>254) cp[3]= 255; else cp[3]= temp;
548         
549         return col;
550 }
551
552 static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
553 {
554         char *cp1, *cp2, *cp;
555         int temp;
556         unsigned int col=0;
557         
558         if(fac==0) return col1;
559         
560         cp1= (char *)&col1;
561         cp2= (char *)&col2;
562         cp=  (char *)&col;
563         
564         cp[0]= 255;
565         temp= cp1[1] - ((fac*cp2[1])/255);
566         if(temp<0) cp[1]= 0; else cp[1]= temp;
567         temp= cp1[2] - ((fac*cp2[2])/255);
568         if(temp<0) cp[2]= 0; else cp[2]= temp;
569         temp= cp1[3] - ((fac*cp2[3])/255);
570         if(temp<0) cp[3]= 0; else cp[3]= temp;
571         
572         return col;
573 }
574
575 static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
576 {
577         char *cp1, *cp2, *cp;
578         int mfac;
579         unsigned int col=0;
580         
581         if(fac==0) return col1;
582
583         mfac= 255-fac;
584         
585         cp1= (char *)&col1;
586         cp2= (char *)&col2;
587         cp=  (char *)&col;
588         
589         /* first mul, then blend the fac */
590         cp[0]= 255;
591         cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255)  )/255;
592         cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255)  )/255;
593         cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255)  )/255;
594
595         
596         return col;
597 }
598
599 static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
600 {
601         char *cp1, *cp2, *cp;
602         int mfac;
603         unsigned int col=0;
604         
605         if(fac==0) return col1;
606         if(fac>=255) return col2;
607
608         mfac= 255-fac;
609         
610         cp1= (char *)&col1;
611         cp2= (char *)&col2;
612         cp=  (char *)&col;
613         
614         /* See if are lighter, if so mix, else dont do anything.
615         if the paint col is darker then the original, then ignore */
616         if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
617                 return col1;
618         
619         cp[0]= 255;
620         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
621         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
622         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
623         
624         return col;
625 }
626
627 static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
628 {
629         char *cp1, *cp2, *cp;
630         int mfac;
631         unsigned int col=0;
632         
633         if(fac==0) return col1;
634         if(fac>=255) return col2;
635
636         mfac= 255-fac;
637         
638         cp1= (char *)&col1;
639         cp2= (char *)&col2;
640         cp=  (char *)&col;
641         
642         /* See if were darker, if so mix, else dont do anything.
643         if the paint col is brighter then the original, then ignore */
644         if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
645                 return col1;
646         
647         cp[0]= 255;
648         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
649         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
650         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
651         return col;
652 }
653
654 static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
655 {
656         Brush *brush = paint_brush(&vp->paint);
657
658         if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
659         else if(brush->vertexpaint_tool==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
660         else if(brush->vertexpaint_tool==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
661         else if(brush->vertexpaint_tool==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
662         else if(brush->vertexpaint_tool==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
663         else if(brush->vertexpaint_tool==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
664         
665         /* if no spray, clip color adding with colorig & orig alpha */
666         if((vp->flag & VP_SPRAY)==0) {
667                 unsigned int testcol=0, a;
668                 char *cp, *ct, *co;
669                 
670                 alpha= (int)(255.0f*brush_alpha(brush));
671                 
672                 if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
673                 else if(brush->vertexpaint_tool==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
674                 else if(brush->vertexpaint_tool==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
675                 else if(brush->vertexpaint_tool==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
676                 else if(brush->vertexpaint_tool==VP_LIGHTEN)  testcol= mcol_lighten( *colorig, paintcol, alpha);
677                 else if(brush->vertexpaint_tool==VP_DARKEN)   testcol= mcol_darken( *colorig, paintcol, alpha);
678                 
679                 cp= (char *)col;
680                 ct= (char *)&testcol;
681                 co= (char *)colorig;
682                 
683                 for(a=0; a<4; a++) {
684                         if( ct[a]<co[a] ) {
685                                 if( cp[a]<ct[a] ) cp[a]= ct[a];
686                                 else if( cp[a]>co[a] ) cp[a]= co[a];
687                         }
688                         else {
689                                 if( cp[a]<co[a] ) cp[a]= co[a];
690                                 else if( cp[a]>ct[a] ) cp[a]= ct[a];
691                         }
692                 }
693         }
694 }
695
696
697 static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
698 {
699         struct ImBuf *ibuf;
700         int a, tot=0, index;
701         
702         /* brecht: disabled this because it obviously failes for
703            brushes with size > 64, why is this here? */
704         /*if(size>64.0) size= 64.0;*/
705         
706         ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size);
707         if(ibuf) {
708                 unsigned int *rt= ibuf->rect;
709
710                 memset(indexar, 0, sizeof(int)*(totface+1));
711                 
712                 size= ibuf->x*ibuf->y;
713                 while(size--) {
714                                 
715                         if(*rt) {
716                                 index= WM_framebuffer_to_index(*rt);
717                                 if(index>0 && index<=totface)
718                                         indexar[index] = 1;
719                         }
720                 
721                         rt++;
722                 }
723                 
724                 for(a=1; a<=totface; a++) {
725                         if(indexar[a]) indexar[tot++]= a;
726                 }
727
728                 IMB_freeImBuf(ibuf);
729         }
730         
731         return tot;
732 }
733
734 static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, const float mval[2], float pressure)
735 {
736         Brush *brush = paint_brush(&vp->paint);
737         float fac, fac_2, size, dx, dy;
738         float alpha;
739         int vertco[2];
740         const int radius= brush_size(brush);
741
742         project_int_noclip(vc->ar, vert_nor, vertco);
743         dx= mval[0]-vertco[0];
744         dy= mval[1]-vertco[1];
745         
746         if (brush_use_size_pressure(brush))
747                 size = pressure * radius;
748         else
749                 size = radius;
750         
751         fac_2= dx*dx + dy*dy;
752         if(fac_2 > size*size) return 0.f;
753         fac = sqrtf(fac_2);
754         
755         alpha= brush_alpha(brush) * brush_curve_strength_clamp(brush, fac, size);
756         
757         if (brush_use_alpha_pressure(brush))
758                 alpha *= pressure;
759                 
760         if(vp->flag & VP_NORMALS) {
761                 float *no= vert_nor+3;
762                 
763                 /* transpose ! */
764                 fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
765                 if(fac > 0.0f) {
766                         dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
767                         dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
768                         
769                         alpha*= fac/sqrtf(dx*dx + dy*dy + fac*fac);
770                 }
771                 else return 0.f;
772         }
773         
774         return alpha;
775 }
776
777 static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval, int flip)
778 {
779         Brush *brush = paint_brush(&wp->paint);
780         int tool = brush->vertexpaint_tool;
781         
782         if(dw==NULL || uw==NULL) return;
783         
784         if (flip) {
785                 switch(tool) {
786                         case VP_MIX:
787                                 paintval = 1.f - paintval; break;
788                         case VP_ADD:
789                                 tool= VP_SUB; break;
790                         case VP_SUB:
791                                 tool= VP_ADD; break;
792                         case VP_LIGHTEN:
793                                 tool= VP_DARKEN; break;
794                         case VP_DARKEN:
795                                 tool= VP_LIGHTEN; break;
796                 }
797         }
798         
799         if(tool==VP_MIX || tool==VP_BLUR)
800                 dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
801         else if(tool==VP_ADD)
802                 dw->weight += paintval*alpha;
803         else if(tool==VP_SUB) 
804                 dw->weight -= paintval*alpha;
805         else if(tool==VP_MUL) 
806                 /* first mul, then blend the fac */
807                 dw->weight = ((1.0f-alpha) + alpha*paintval)*dw->weight;
808         else if(tool==VP_LIGHTEN) {
809                 if (dw->weight < paintval)
810                         dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
811         } else if(tool==VP_DARKEN) {
812                 if (dw->weight > paintval)
813                         dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
814         }
815         CLAMP(dw->weight, 0.0f, 1.0f);
816         
817         /* if no spray, clip result with orig weight & orig alpha */
818         if((wp->flag & VP_SPRAY)==0) {
819                 float testw=0.0f;
820                 
821                 alpha= brush_alpha(brush);
822                 if(tool==VP_MIX || tool==VP_BLUR)
823                         testw = paintval*alpha + uw->weight*(1.0f-alpha);
824                 else if(tool==VP_ADD)
825                         testw = uw->weight + paintval*alpha;
826                 else if(tool==VP_SUB) 
827                         testw = uw->weight - paintval*alpha;
828                 else if(tool==VP_MUL) 
829                         /* first mul, then blend the fac */
830                         testw = ((1.0f-alpha) + alpha*paintval)*uw->weight;
831                 else if(tool==VP_LIGHTEN) {
832                         if (uw->weight < paintval)
833                                 testw = paintval*alpha + uw->weight*(1.0f-alpha);
834                         else
835                                 testw = uw->weight;
836                 } else if(tool==VP_DARKEN) {
837                         if (uw->weight > paintval)
838                                 testw = paintval*alpha + uw->weight*(1.0f-alpha);
839                         else
840                                 testw = uw->weight;
841                 }
842                 CLAMP(testw, 0.0f, 1.0f);
843                 
844                 if( testw<uw->weight ) {
845                         if(dw->weight < testw) dw->weight= testw;
846                         else if(dw->weight > uw->weight) dw->weight= uw->weight;
847                 }
848                 else {
849                         if(dw->weight > testw) dw->weight= testw;
850                         else if(dw->weight < uw->weight) dw->weight= uw->weight;
851                 }
852         }
853         
854 }
855
856 /* ----------------------------------------------------- */
857
858 /* used for 3d view, on active object, assumes me->dvert exists */
859 /* if mode==1: */
860 /*     samples cursor location, and gives menu with vertex groups to activate */
861 /* else */
862 /*     sets wp->weight to the closest weight value to vertex */
863 /*     note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
864 static void sample_wpaint(Scene *scene, ARegion *ar, View3D *UNUSED(v3d), int mode)
865 {
866         ViewContext vc;
867         ToolSettings *ts= scene->toolsettings;
868         Object *ob= OBACT;
869         Mesh *me= get_mesh(ob);
870         int index;
871         int mval[2] = {0, 0}, sco[2];
872         int vgroup= ob->actdef-1;
873
874         if (!me) return;
875         
876 //      getmouseco_areawin(mval);
877         index= view3d_sample_backbuf(&vc, mval[0], mval[1]);
878         
879         if(index && index<=me->totface) {
880                 MFace *mface;
881                 
882                 mface= ((MFace *)me->mface) + index-1;
883                 
884                 if(mode==1) {   /* sampe which groups are in here */
885                         MDeformVert *dv;
886                         int a, totgroup;
887                         
888                         totgroup= BLI_countlist(&ob->defbase);
889                         if(totgroup) {
890                                 int totmenu=0;
891                                 int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
892                                 
893                                 dv= me->dvert+mface->v1;
894                                 for(a=0; a<dv->totweight; a++) {
895                                         if (dv->dw[a].def_nr<totgroup)
896                                                 groups[dv->dw[a].def_nr]= 1;
897                                 }
898                                 dv= me->dvert+mface->v2;
899                                 for(a=0; a<dv->totweight; a++) {
900                                         if (dv->dw[a].def_nr<totgroup)
901                                                 groups[dv->dw[a].def_nr]= 1;
902                                 }
903                                 dv= me->dvert+mface->v3;
904                                 for(a=0; a<dv->totweight; a++) {
905                                         if (dv->dw[a].def_nr<totgroup)
906                                                 groups[dv->dw[a].def_nr]= 1;
907                                 }
908                                 if(mface->v4) {
909                                         dv= me->dvert+mface->v4;
910                                         for(a=0; a<dv->totweight; a++) {
911                                                 if (dv->dw[a].def_nr<totgroup)
912                                                         groups[dv->dw[a].def_nr]= 1;
913                                         }
914                                 }
915                                 for(a=0; a<totgroup; a++)
916                                         if(groups[a]) totmenu++;
917                                 
918                                 if(totmenu==0) {
919                                         //notice("No Vertex Group Selected");
920                                 }
921                                 else {
922                                         bDeformGroup *dg;
923                                         short val;
924                                         char item[40], *str= MEM_mallocN(40*totmenu+40, "menu");
925                                         
926                                         strcpy(str, "Vertex Groups %t");
927                                         for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) {
928                                                 if(groups[a]) {
929                                                         sprintf(item, "|%s %%x%d", dg->name, a);
930                                                         strcat(str, item);
931                                                 }
932                                         }
933                                         
934                                         val= 0; // XXX pupmenu(str);
935                                         if(val>=0) {
936                                                 ob->actdef= val+1;
937                                                 DAG_id_tag_update(&me->id, 0);
938                                         }
939                                         MEM_freeN(str);
940                                 }
941                                 MEM_freeN(groups);
942                         }
943 //                      else notice("No Vertex Groups in Object");
944                 }
945                 else {
946                         DerivedMesh *dm;
947                         float w1, w2, w3, w4, co[3], fac;
948                         
949                         dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
950                         if(dm->getVertCo==NULL) {
951                                 //notice("Not supported yet");
952                         }
953                         else {
954                                 /* calc 3 or 4 corner weights */
955                                 dm->getVertCo(dm, mface->v1, co);
956                                 project_int_noclip(ar, co, sco);
957                                 w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
958                                 
959                                 dm->getVertCo(dm, mface->v2, co);
960                                 project_int_noclip(ar, co, sco);
961                                 w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
962                                 
963                                 dm->getVertCo(dm, mface->v3, co);
964                                 project_int_noclip(ar, co, sco);
965                                 w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
966                                 
967                                 if(mface->v4) {
968                                         dm->getVertCo(dm, mface->v4, co);
969                                         project_int_noclip(ar, co, sco);
970                                         w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
971                                 }
972                                 else w4= 1.0e10;
973                                 
974                                 fac= MIN4(w1, w2, w3, w4);
975                                 if(w1==fac) {
976                                         ts->vgroup_weight= defvert_find_weight(me->dvert+mface->v1, vgroup);
977                                 }
978                                 else if(w2==fac) {
979                                         ts->vgroup_weight= defvert_find_weight(me->dvert+mface->v2, vgroup);
980                                 }
981                                 else if(w3==fac) {
982                                         ts->vgroup_weight= defvert_find_weight(me->dvert+mface->v3, vgroup);
983                                 }
984                                 else if(w4==fac) {
985                                         if(mface->v4) {
986                                                 ts->vgroup_weight= defvert_find_weight(me->dvert+mface->v4, vgroup);
987                                         }
988                                 }
989                         }
990                         dm->release(dm);
991                 }               
992                 
993         }
994         
995 }
996
997 static void do_weight_paint_auto_normalize(MDeformVert *dvert, 
998                                            int paint_nr, char *map)
999 {
1000 //      MDeformWeight *dw = dvert->dw;
1001         float sum=0.0f, fac=0.0f, paintw=0.0f;
1002         int i, tot=0;
1003
1004         if (!map)
1005                 return;
1006
1007         for (i=0; i<dvert->totweight; i++) {
1008                 if (dvert->dw[i].def_nr == paint_nr)
1009                         paintw = dvert->dw[i].weight;
1010
1011                 if (map[dvert->dw[i].def_nr]) {
1012                         tot += 1;
1013                         if (dvert->dw[i].def_nr != paint_nr)
1014                                 sum += dvert->dw[i].weight;
1015                 }
1016         }
1017         
1018         if (!tot || sum <= (1.0f - paintw))
1019                 return;
1020
1021         fac = sum / (1.0f - paintw);
1022         fac = fac==0.0f ? 1.0f : 1.0f / fac;
1023
1024         for (i=0; i<dvert->totweight; i++) {
1025                 if (map[dvert->dw[i].def_nr]) {
1026                         if (dvert->dw[i].def_nr != paint_nr)
1027                                 dvert->dw[i].weight *= fac;
1028                 }
1029         }
1030 }
1031 // Jason was here: the active group should be involved in auto normalize
1032 static void do_weight_paint_auto_normalize_change_act_group(MDeformVert *dvert, char *map)
1033 {
1034 //      MDeformWeight *dw = dvert->dw;
1035         float sum=0.0f, fac=0.0f;
1036         int i, tot=0;
1037
1038         if (!map)
1039                 return;
1040
1041         for (i=0; i<dvert->totweight; i++) {
1042                 if (map[dvert->dw[i].def_nr]) {
1043                         tot += 1;
1044                         sum += dvert->dw[i].weight;
1045                 }
1046         }
1047         
1048         if (!tot || sum == 1.0f)
1049                 return;
1050
1051         fac = sum;
1052         fac = fac==0.0f ? 1.0f : 1.0f / fac;
1053
1054         for (i=0; i<dvert->totweight; i++) {
1055                 if (map[dvert->dw[i].def_nr]) {
1056                         dvert->dw[i].weight *= fac;
1057                 }
1058         }
1059 }
1060 /* Jason was here 
1061 this function will handle normalize with locked groups 
1062 it assumes that the current ratios (of locked groups)
1063 are the intended ratios.
1064
1065 also, it does not attempt to force them to add up to 1, that would destroy intergroup weight ratios,
1066 it simply makes the highest weight sum add up to one
1067
1068 the Mesh is needed to change the ratios across the group
1069
1070 I need to resolve a precision error issue, however:
1071 dividing can cause the weights to drop to 0
1072 */
1073 /*static void do_wp_auto_normalize_locked_groups(Mesh *me, MDeformVert *dvert, char* map)
1074 {
1075         float highestSum = 0.0f;
1076         float currentSum;
1077         int cnt;
1078         int i, k;
1079         int totvert = me->totvert;
1080         MDeformVert dv;
1081
1082         if(!map) {
1083                 return;
1084         }
1085
1086         for(i = 0; i < totvert; i++) {
1087                 dv = dvert[i];
1088                 cnt = dv.totweight;
1089                 currentSum = 0.0f;
1090                 for(k = 0; k < cnt; k++) {
1091                         if(map[dv.dw->def_nr]) {
1092                                 //printf("group %d considered\n", dv.dw->def_nr);
1093                                 currentSum += (dv.dw+k)->weight;
1094                         }
1095                 }
1096                 if(highestSum < currentSum) {
1097                         highestSum = currentSum;
1098                 }
1099         }
1100         if(highestSum == 1.0f) {
1101                 return;
1102         }
1103         for(i = 0; i < totvert; i++) {
1104                 dv = dvert[i];
1105                 cnt = dv.totweight;
1106
1107                 for(k = 0; k < cnt; k++) {
1108                         if(map[dv.dw->def_nr]) {
1109                                 (dv.dw+k)->weight /= highestSum;
1110                         }
1111                 }
1112         }
1113 }*/
1114 /* Jason was here */
1115 /*static char get_locked_flag(Object *ob, int vgroup)
1116 {
1117         int i;
1118         bDeformGroup *defgroup = ob->defbase.first;
1119         for(i = 0; i < vgroup && defgroup; i++) {
1120                 defgroup = defgroup->next;
1121         }
1122         if(defgroup) {
1123                 return defgroup->flag;
1124         }
1125         return 0;
1126 }*/
1127 /* Jason was here */
1128 /*static int locked_group_exists(Object *ob)
1129 {
1130         bDeformGroup *defgroup = ob->defbase.first;
1131         while(defgroup) {
1132                 if(defgroup->flag){
1133                         return TRUE;
1134                 }
1135                 defgroup = defgroup->next;
1136         }
1137         return FALSE;
1138 }*/
1139 /* Jason was here */
1140 /*
1141 See if the current deform vertex has a locked group
1142 */
1143 static char has_locked_group(MDeformVert *dvert, char *flags)
1144 {
1145         int i;
1146         for(i = 0; i < dvert->totweight; i++) {
1147                 if(flags[(dvert->dw+i)->def_nr] && (dvert->dw+i)->weight > 0.0f) {
1148                         return TRUE;
1149                 }
1150         }
1151         return FALSE;
1152 }
1153 /*Jason was here
1154 gen_lck_flags gets the status of "flag" for each bDeformGroup
1155 in ob->defbase and returns an array containing them
1156 */
1157 static char* gen_lck_flags(Object* ob, int defcnt, char *map)
1158 {
1159         char is_locked = FALSE;
1160         int i;
1161         //int defcnt = BLI_countlist(&ob->defbase);
1162         char *flags = MEM_mallocN(defcnt*sizeof(char), "defflags");
1163         bDeformGroup *defgroup;
1164         int selected = 0;
1165
1166         for(i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
1167                 flags[i] = defgroup->flag;
1168                 if(flags[i]) {
1169                         is_locked = TRUE;
1170                 }
1171         }
1172         if(is_locked){
1173                 return flags;
1174         }
1175         // don't forget to free it if it is unneeded
1176         MEM_freeN(flags);
1177         return NULL;
1178 }
1179 /*Jason was here
1180 this alters the weights in order to maintain the ratios to match with the change in weights of pnt_dw
1181 This was not the intended solution evidently
1182 */
1183 /*static void fix_weight_ratios(Mesh *me, MDeformWeight *pnt_dw, float oldw)
1184 {
1185         int i, k, totvert, cnt;
1186         float scaledown = 1.0f;
1187         float neww = pnt_dw->weight;
1188         int defgroup = pnt_dw->def_nr;
1189         MDeformVert *dvert;
1190         MDeformVert dv;
1191         MDeformWeight *dw;
1192         totvert = me->totvert;
1193         pnt_dw->weight = oldw;
1194
1195         if(oldw == 0 || neww == 0){
1196                 return;
1197         }
1198         dvert = me->dvert;
1199         for(i = 0; i < totvert; i++) {
1200                 dv = dvert[i];
1201                 cnt = dv.totweight;
1202                 for(k = 0; k < cnt; k++) {
1203                         dw = dv.dw+k;
1204                         if(dw->def_nr == defgroup){
1205                                 dw->weight = neww * (dw->weight / oldw);
1206                                 if(dw->weight > scaledown){
1207                                         scaledown = dw->weight;
1208                                 }
1209                                 break;
1210                         }
1211                 }
1212         }
1213         if(scaledown > 1.0f) {
1214                 for(i = 0; i < totvert; i++) {
1215                         dv = dvert[i];
1216                         cnt = dv.totweight;
1217                         for(k = 0; k < cnt; k++) {
1218                                 dw = dv.dw+k;
1219                                 if(dw->def_nr == defgroup){
1220                                         dw->weight /= scaledown;
1221                                         break;
1222                                 }
1223                         }
1224                 }
1225         }
1226 }*/
1227 /* Jason was here */
1228 /*
1229 The idea behind this function is to get the difference in weight for pnt_dw,
1230 and to redistribute that weight to the unlocked groups
1231 (if it has to, then it will put some/all of the change
1232 back onto the original group)
1233 */
1234 static void redistribute_weight_change(Object *ob, MDeformVert *dvert, int index, MDeformWeight *pnt_dw, float oldw, char* flags, int defcnt, char *map)
1235 {
1236         int i;
1237         float old_change_left;
1238         float change_left = oldw - pnt_dw->weight;
1239         // make sure the redistribution the same per loop.
1240         float change;
1241         char was_a_change;
1242         int groups_left_that_can_change = 0;
1243         char* change_status = MEM_mallocN(defcnt*sizeof(char), "defflags");
1244         MDeformWeight *dw;
1245         for(i = 0; i < defcnt; i++) {
1246                 if(pnt_dw->def_nr == i || !map[i]) {
1247                         change_status[i] = FALSE;
1248                 } else {
1249                         change_status[i] = !flags[i];
1250                 }
1251                 if(change_status[i]) {
1252                         groups_left_that_can_change++;
1253                         defvert_verify_index(dvert, i);
1254                 }
1255         }
1256         if(groups_left_that_can_change > 0) {
1257                 change = change_left/groups_left_that_can_change;
1258                 /* the division could cause it to be zero, so if it is, forget it*/
1259                 if(change == 0) {
1260                         change = change_left;
1261                 }
1262                 do {
1263                         was_a_change = FALSE;
1264                         for(i = 0; i < dvert->totweight; i++) {
1265                                 dw = (dvert->dw+i);
1266                                 if(!change_status[dw->def_nr]) {
1267                                         continue;
1268                                 }
1269
1270                                 dw->weight += change;
1271                                 old_change_left = change_left;
1272                                 change_left -= change;
1273                                 // sign change?
1274                                 if(change_left!=0 && change_left/fabs(change_left) != old_change_left/fabs(old_change_left)) {
1275                                         dw->weight -= change;
1276                                         change_left = old_change_left;
1277                                         break;
1278                                 }
1279                                 if(dw->weight >= 1.0f) {
1280
1281                                         change_left += dw->weight-1.0f;
1282                                         dw->weight = 1.0f;
1283                                         groups_left_that_can_change--;
1284                                         change_status[dw->def_nr] = FALSE;
1285
1286                                 }else if(dw->weight <= 0.0f) {
1287
1288                                         change_left += dw->weight;
1289                                         dw->weight = 0.0f;
1290                                         groups_left_that_can_change--;
1291                                         change_status[dw->def_nr] = FALSE;
1292                                 }
1293                                 was_a_change = TRUE;
1294                                 /* if it was too small, don't get stuck in an infinite loop! */
1295                                 if(old_change_left == change_left) {
1296                                         change *= 2;
1297                                 }
1298                         }
1299                 } while(groups_left_that_can_change > 0 && change_left != 0.0f && was_a_change);
1300         }
1301         // add any remaining change back to the original weight
1302         pnt_dw->weight += change_left;
1303         MEM_freeN(change_status);
1304 }
1305 /* Jason */
1306 /* return TRUE on success, FALSE on failure
1307 failure occurs when zero elements exist in the selection,
1308 nonzero elements reach zero,
1309 and if they go above 1 if auto normalize is off */
1310 static int multipaint_vgroups(MDeformVert *dvert, MDeformWeight *dw, float oldw, char* validmap, char* bone_groups, char* selection, int defcnt) {
1311         int i;
1312         float change;
1313         MDeformWeight *w;
1314         float val;
1315         if(oldw == 0 || !selection) {
1316                 return FALSE;
1317         }
1318         change = dw->weight/oldw;
1319         if(change == 1 || !change) {
1320                 return FALSE;
1321         }
1322         dw->weight = oldw;
1323         // make sure all selected dverts exist
1324         for(i = 0; i < defcnt; i++) {
1325                 if(selection[i]){
1326                         defvert_verify_index(dvert, i);
1327                 }
1328         }
1329         // see if all changes are valid before doing any
1330         for(i = 0; i < dvert->totweight; i++) {
1331                 w = (dvert->dw+i);
1332                 if(!selection[w->def_nr] || !bone_groups[w->def_nr]) {
1333                         continue;
1334                 }
1335                 if(w->weight == 0) {
1336                         if(selection[w->def_nr]) {
1337                                 return FALSE;
1338                         }
1339                         continue;
1340                 }
1341                 val = w->weight*change;
1342                 if(val <= 0 || (val > 1 && !validmap)) {
1343                         return FALSE;
1344                 }
1345         }
1346         for(i = 0; i < dvert->totweight; i++) {
1347                 w = (dvert->dw+i);
1348                 if(!selection[w->def_nr] || !bone_groups[w->def_nr] || w->weight == 0) {
1349                         continue;
1350                 }
1351                 w->weight *= change;
1352         }
1353         return TRUE;
1354 }
1355 /* Jason */
1356 static void check_locks_and_normalize(Object *ob, Mesh *me, int index, int vgroup, MDeformWeight *dw, float oldw, char *validmap, char *flags, int defcnt, char *bone_groups, char *selection, int multipaint)
1357 {
1358         if(flags && has_locked_group(me->dvert+index, flags)) {
1359                 if(flags[dw->def_nr] || multipaint) {
1360                         // cannot change locked groups!
1361                         dw->weight = oldw;
1362                 } else if(bone_groups[dw->def_nr]) {
1363                         redistribute_weight_change(ob, me->dvert+index, index, dw, oldw, flags, defcnt, bone_groups);
1364                         do_weight_paint_auto_normalize_change_act_group(me->dvert+index, validmap);//do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap);
1365                 }
1366         } else if(bone_groups[dw->def_nr]) {// disable auto normalize if the active group is not a bone group
1367                 if(multipaint) {
1368                         // try to alter the other bone groups in the dvert with the changed dw if possible, if it isn't, change it back
1369                         if(selection[dw->def_nr] && multipaint_vgroups(me->dvert+index, dw, oldw, validmap, bone_groups, selection, defcnt)) {
1370                                 do_weight_paint_auto_normalize_change_act_group(me->dvert+index, validmap);//do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap);
1371                         }else {
1372                                 // multipaint failed
1373                                 dw->weight = oldw;
1374                         }
1375                 }else {
1376                         do_weight_paint_auto_normalize_change_act_group(me->dvert+index, validmap);//do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap);
1377                 }
1378         }
1379 }
1380 /* Jason was here duplicate function I used in DerivedMesh.c*/
1381 static char* get_selected_defgroups(Object *ob, int defcnt) {
1382         bPoseChannel *chan;
1383         bPose *pose;
1384         bDeformGroup *defgroup;
1385         //Bone *bone;
1386         char was_selected = FALSE;
1387         char *dg_flags = MEM_mallocN(defcnt*sizeof(char), "dg_selected_flags");
1388         int i;
1389         Object *armob = ED_object_pose_armature(ob);
1390
1391         if(armob) {
1392                 pose = armob->pose;
1393                 for (chan=pose->chanbase.first; chan; chan=chan->next) {
1394                         for (i = 0, defgroup = ob->defbase.first; i < defcnt && defgroup; defgroup = defgroup->next, i++) {
1395                                 if(!strcmp(defgroup->name, chan->bone->name)) {
1396                                         dg_flags[i] = (chan->bone->flag & BONE_SELECTED);
1397                                         was_selected = TRUE;
1398                                 }
1399                         }
1400                 }
1401         }
1402         
1403         return dg_flags;
1404 }
1405 // Jason
1406 static char *wpaint_make_validmap(Object *ob);
1407
1408 static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, 
1409                                    float alpha, float paintweight, int flip, 
1410                                    int vgroup_mirror, char *validmap, int multipaint)
1411 {
1412         Mesh *me= ob->data;
1413         MDeformWeight *dw, *uw;
1414         int vgroup= ob->actdef-1;
1415
1416         /* Jason was here */
1417         char *flags;
1418         char *bone_groups;
1419         char *selection;
1420         float oldw;
1421         int defcnt;
1422         if(validmap) {
1423                 bone_groups = validmap;
1424         }else {
1425                 bone_groups = wpaint_make_validmap(ob);
1426         }
1427
1428         if(wp->flag & VP_ONLYVGROUP) {
1429                 dw= defvert_find_index(me->dvert+index, vgroup);
1430                 uw= defvert_find_index(wp->wpaint_prev+index, vgroup);
1431         }
1432         else {
1433                 dw= defvert_verify_index(me->dvert+index, vgroup);
1434                 uw= defvert_verify_index(wp->wpaint_prev+index, vgroup);
1435         }
1436         if(dw==NULL || uw==NULL)
1437                 return;
1438         /* Jason was here */
1439         flags = gen_lck_flags(ob, defcnt = BLI_countlist(&ob->defbase), bone_groups);
1440         selection = get_selected_defgroups(ob, defcnt);
1441         oldw = dw->weight;
1442         wpaint_blend(wp, dw, uw, alpha, paintweight, flip);
1443         /* Jason was here */
1444         check_locks_and_normalize(ob, me, index, vgroup, dw, oldw, validmap, flags, defcnt, bone_groups, selection, multipaint);
1445
1446         if(me->editflag & ME_EDIT_MIRROR_X) {   /* x mirror painting */
1447                 int j= mesh_get_x_mirror_vert(ob, index);
1448                 if(j>=0) {
1449                         /* copy, not paint again */
1450                         if(vgroup_mirror != -1)
1451                                 uw= defvert_verify_index(me->dvert+j, vgroup_mirror);
1452                         else
1453                                 uw= defvert_verify_index(me->dvert+j, vgroup);
1454                         /* Jason */
1455                         oldw = uw->weight;
1456
1457                         uw->weight= dw->weight;
1458                         /* Jason */
1459                         check_locks_and_normalize(ob, me, j, vgroup, uw, oldw, validmap, flags, defcnt, bone_groups, selection, multipaint);
1460                 }
1461         }
1462         /* Jason */
1463         if(flags) {
1464                 MEM_freeN(flags);
1465         }
1466         if(selection) {
1467                 MEM_freeN(selection);
1468         }
1469         if(!validmap) {
1470                 MEM_freeN(bone_groups);
1471         }
1472 }
1473
1474 /* *************** set wpaint operator ****************** */
1475
1476 static int set_wpaint(bContext *C, wmOperator *UNUSED(op))              /* toggle */
1477 {               
1478         Object *ob= CTX_data_active_object(C);
1479         Scene *scene= CTX_data_scene(C);
1480         VPaint *wp= scene->toolsettings->wpaint;
1481         Mesh *me;
1482         
1483         me= get_mesh(ob);
1484         if(ob->id.lib || me==NULL) return OPERATOR_PASS_THROUGH;
1485         
1486         if(ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
1487         else ob->mode |= OB_MODE_WEIGHT_PAINT;
1488         
1489         
1490         /* Weightpaint works by overriding colors in mesh,
1491                 * so need to make sure we recalc on enter and
1492                 * exit (exit needs doing regardless because we
1493                                 * should redeform).
1494                 */
1495         DAG_id_tag_update(&me->id, 0);
1496         
1497         if(ob->mode & OB_MODE_WEIGHT_PAINT) {
1498                 Object *par;
1499                 
1500                 if(wp==NULL)
1501                         wp= scene->toolsettings->wpaint= new_vpaint(1);
1502
1503                 paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
1504                 paint_cursor_start(C, weight_paint_poll);
1505                 
1506                 mesh_octree_table(ob, NULL, NULL, 's');
1507                 
1508                 /* verify if active weight group is also active bone */
1509                 par= modifiers_isDeformedByArmature(ob);
1510                 if(par && (par->mode & OB_MODE_POSE)) {
1511                         bArmature *arm= par->data;
1512
1513                         if(arm->act_bone)
1514                                 ED_vgroup_select_by_name(ob, arm->act_bone->name);
1515                 }
1516         }
1517         else {
1518                 mesh_octree_table(NULL, NULL, NULL, 'e');
1519                 mesh_mirrtopo_table(NULL, 'e');
1520         }
1521         
1522         WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
1523         
1524         return OPERATOR_FINISHED;
1525 }
1526
1527 /* for switching to/from mode */
1528 static int paint_poll_test(bContext *C)
1529 {
1530         if(CTX_data_edit_object(C))
1531                 return 0;
1532         if(CTX_data_active_object(C)==NULL)
1533                 return 0;
1534         return 1;
1535 }
1536
1537 void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
1538 {
1539         
1540         /* identifiers */
1541         ot->name= "Weight Paint Mode";
1542         ot->idname= "PAINT_OT_weight_paint_toggle";
1543         
1544         /* api callbacks */
1545         ot->exec= set_wpaint;
1546         ot->poll= paint_poll_test;
1547         
1548         /* flags */
1549         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1550         
1551 }
1552
1553 /* ************ weight paint operator ********** */
1554
1555 struct WPaintData {
1556         ViewContext vc;
1557         int *indexar;
1558         int vgroup_mirror;
1559         float *vertexcosnos;
1560         float wpimat[3][3];
1561         
1562         /*variables for auto normalize*/
1563         int auto_normalize;
1564         char *vgroup_validmap; /*stores if vgroups tie to deforming bones or not*/
1565 };
1566
1567 static char *wpaint_make_validmap(Object *ob)
1568 {
1569         bDeformGroup *dg;
1570         ModifierData *md;
1571         char *validmap;
1572         bPose *pose;
1573         bPoseChannel *chan;
1574         ArmatureModifierData *amd;
1575         GHash *gh = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "wpaint_make_validmap gh");
1576         int i = 0, step1=1;
1577
1578         /*add all names to a hash table*/
1579         for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1580                 BLI_ghash_insert(gh, dg->name, NULL);
1581         }
1582
1583         if (!i)
1584                 return NULL;
1585
1586         validmap = MEM_callocN(i, "wpaint valid map");
1587
1588         /*now loop through the armature modifiers and identify deform bones*/
1589         for (md = ob->modifiers.first; md; md= !md->next && step1 ? (step1=0), modifiers_getVirtualModifierList(ob) : md->next) {
1590                 if (!(md->mode & (eModifierMode_Realtime|eModifierMode_Virtual)))
1591                         continue;
1592
1593                 if (md->type == eModifierType_Armature) 
1594                 {
1595                         amd = (ArmatureModifierData*) md;
1596
1597                         if(amd->object && amd->object->pose) {
1598                                 pose = amd->object->pose;
1599                                 
1600                                 for (chan=pose->chanbase.first; chan; chan=chan->next) {
1601                                         if (chan->bone->flag & BONE_NO_DEFORM)
1602                                                 continue;
1603
1604                                         if (BLI_ghash_haskey(gh, chan->name)) {
1605                                                 BLI_ghash_remove(gh, chan->name, NULL, NULL);
1606                                                 BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
1607                                         }
1608                                 }
1609                         }
1610                 }
1611         }
1612         
1613         /*add all names to a hash table*/
1614         for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1615                 if (BLI_ghash_lookup(gh, dg->name) != NULL) {
1616                         validmap[i] = 1;
1617                 }
1618         }
1619
1620         BLI_ghash_free(gh, NULL, NULL);
1621
1622         return validmap;
1623 }
1624
1625 static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1626 {
1627         Scene *scene= CTX_data_scene(C);
1628         struct PaintStroke *stroke = op->customdata;
1629         ToolSettings *ts= CTX_data_tool_settings(C);
1630         VPaint *wp= ts->wpaint;
1631         Object *ob= CTX_data_active_object(C);
1632         struct WPaintData *wpd;
1633         Mesh *me;
1634         float mat[4][4], imat[4][4];
1635
1636         if(scene->obedit) return OPERATOR_CANCELLED;
1637         
1638         me= get_mesh(ob);
1639         if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
1640         
1641         /* if nothing was added yet, we make dverts and a vertex deform group */
1642         if (!me->dvert) {
1643                 ED_vgroup_data_create(&me->id);
1644                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
1645         }
1646
1647
1648         /* make mode data storage */
1649         wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
1650         paint_stroke_set_mode_data(stroke, wpd);
1651         view3d_set_viewcontext(C, &wpd->vc);
1652         wpd->vgroup_mirror= -1;
1653
1654         /*set up auto-normalize, and generate map for detecting which
1655           vgroups affect deform bones*/
1656         wpd->auto_normalize = ts->auto_normalize;
1657         if (wpd->auto_normalize)
1658                 wpd->vgroup_validmap = wpaint_make_validmap(ob);
1659         
1660         //      if(qual & LR_CTRLKEY) {
1661         //              sample_wpaint(scene, ar, v3d, 0);
1662         //              return;
1663         //      }
1664         //      if(qual & LR_SHIFTKEY) {
1665         //              sample_wpaint(scene, ar, v3d, 1);
1666         //              return;
1667         //      }
1668         
1669         /* ALLOCATIONS! no return after this line */
1670         /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1671         wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
1672         wpd->indexar= get_indexarray(me);
1673         copy_wpaint_prev(wp, me->dvert, me->totvert);
1674         
1675         /* this happens on a Bone select, when no vgroup existed yet */
1676         if(ob->actdef<=0) {
1677                 Object *modob;
1678                 if((modob = modifiers_isDeformedByArmature(ob))) {
1679                         Bone *actbone= ((bArmature *)modob->data)->act_bone;
1680                         if(actbone) {
1681                                 bPoseChannel *pchan= get_pose_channel(modob->pose, actbone->name);
1682
1683                                 if(pchan) {
1684                                         bDeformGroup *dg= defgroup_find_name(ob, pchan->name);
1685                                         if(dg==NULL)
1686                                                 dg= ED_vgroup_add_name(ob, pchan->name);        /* sets actdef */
1687                                         else
1688                                                 ob->actdef= 1 + defgroup_find_index(ob, dg);
1689                                 }
1690                         }
1691                 }
1692         }
1693         if(ob->defbase.first==NULL) {
1694                 ED_vgroup_add(ob);
1695         }
1696         
1697         //      if(ob->lay & v3d->lay); else error("Active object is not in this layer");
1698         
1699         /* imat for normals */
1700         mul_m4_m4m4(mat, ob->obmat, wpd->vc.rv3d->viewmat);
1701         invert_m4_m4(imat, mat);
1702         copy_m3_m4(wpd->wpimat, imat);
1703         
1704         /* if mirror painting, find the other group */
1705         if(me->editflag & ME_EDIT_MIRROR_X) {
1706                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
1707                 if(defgroup) {
1708                         bDeformGroup *curdef;
1709                         int actdef= 0;
1710                         char name[32];
1711
1712                         flip_side_name(name, defgroup->name, FALSE);
1713
1714                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
1715                                 if (!strcmp(curdef->name, name))
1716                                         break;
1717                         if(curdef==NULL) {
1718                                 int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
1719                                 curdef= ED_vgroup_add_name (ob, name);
1720                                 ob->actdef= olddef;
1721                         }
1722                         
1723                         if(curdef && curdef!=defgroup)
1724                                 wpd->vgroup_mirror= actdef;
1725                 }
1726         }
1727
1728         return 1;
1729 }
1730
1731 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
1732 {
1733         ToolSettings *ts= CTX_data_tool_settings(C);
1734         VPaint *wp= ts->wpaint;
1735         Brush *brush = paint_brush(&wp->paint);
1736         struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1737         ViewContext *vc;
1738         Object *ob;
1739         Mesh *me;
1740         float mat[4][4];
1741         float paintweight;
1742         int *indexar;
1743         int totindex, index, totw, flip;
1744         float alpha;
1745         float mval[2], pressure;
1746         
1747         /* cannot paint if there is no stroke data */
1748         if (wpd == NULL) {
1749                 // XXX: force a redraw here, since even though we can't paint, 
1750                 // at least view won't freeze until stroke ends
1751                 ED_region_tag_redraw(CTX_wm_region(C));
1752                 return;
1753         }
1754                 
1755         vc= &wpd->vc;
1756         ob= vc->obact;
1757         me= ob->data;
1758         indexar= wpd->indexar;
1759         
1760         view3d_operator_needs_opengl(C);
1761                 
1762         /* load projection matrix */
1763         mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
1764
1765         flip = RNA_boolean_get(itemptr, "pen_flip");
1766         pressure = RNA_float_get(itemptr, "pressure");
1767         RNA_float_get_array(itemptr, "mouse", mval);
1768         mval[0]-= vc->ar->winrct.xmin;
1769         mval[1]-= vc->ar->winrct.ymin;
1770                         
1771         swap_m4m4(wpd->vc.rv3d->persmat, mat);
1772                         
1773         /* which faces are involved */
1774         if(wp->flag & VP_AREA) {
1775                 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
1776         }
1777         else {
1778                 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
1779                 if(indexar[0]) totindex= 1;
1780                 else totindex= 0;
1781         }
1782                         
1783         if(wp->flag & VP_COLINDEX) {
1784                 for(index=0; index<totindex; index++) {
1785                         if(indexar[index] && indexar[index]<=me->totface) {
1786                                 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1787                                                 
1788                                 if(mface->mat_nr!=ob->actcol-1) {
1789                                         indexar[index]= 0;
1790                                 }
1791                         }
1792                 }
1793         }
1794                         
1795         if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
1796                 for(index=0; index<totindex; index++) {
1797                         if(indexar[index] && indexar[index]<=me->totface) {
1798                                 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1799                                                 
1800                                 if((mface->flag & ME_FACE_SEL)==0) {
1801                                         indexar[index]= 0;
1802                                 }
1803                         }                                       
1804                 }
1805         }
1806                         
1807         /* make sure each vertex gets treated only once */
1808         /* and calculate filter weight */
1809         totw= 0;
1810         if(brush->vertexpaint_tool==VP_BLUR) 
1811                 paintweight= 0.0f;
1812         else
1813                 paintweight= ts->vgroup_weight;
1814                         
1815         for(index=0; index<totindex; index++) {
1816                 if(indexar[index] && indexar[index]<=me->totface) {
1817                         MFace *mface= me->mface + (indexar[index]-1);
1818                                         
1819                         (me->dvert+mface->v1)->flag= 1;
1820                         (me->dvert+mface->v2)->flag= 1;
1821                         (me->dvert+mface->v3)->flag= 1;
1822                         if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1823                                         
1824                         if(brush->vertexpaint_tool==VP_BLUR) {
1825                                 MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
1826                                                 
1827                                 if(wp->flag & VP_ONLYVGROUP)
1828                                         dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
1829                                 else
1830                                         dw_func= defvert_verify_index;
1831                                                 
1832                                 dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
1833                                 if(dw) {paintweight+= dw->weight; totw++;}
1834                                 dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
1835                                 if(dw) {paintweight+= dw->weight; totw++;}
1836                                 dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
1837                                 if(dw) {paintweight+= dw->weight; totw++;}
1838                                 if(mface->v4) {
1839                                         dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
1840                                         if(dw) {paintweight+= dw->weight; totw++;}
1841                                 }
1842                         }
1843                 }
1844         }
1845                         
1846         if(brush->vertexpaint_tool==VP_BLUR) 
1847                 paintweight/= (float)totw;
1848                         
1849         for(index=0; index<totindex; index++) {
1850                                 
1851                 if(indexar[index] && indexar[index]<=me->totface) {
1852                         MFace *mface= me->mface + (indexar[index]-1);
1853                                         
1854                         if((me->dvert+mface->v1)->flag) {
1855                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval, pressure);
1856                                 if(alpha) {
1857                                         do_weight_paint_vertex(wp, ob, mface->v1, 
1858                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1859                                                 wpd->vgroup_validmap, ts->multipaint);
1860                                 }
1861                                 (me->dvert+mface->v1)->flag= 0;
1862                         }
1863                                         
1864                         if((me->dvert+mface->v2)->flag) {
1865                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval, pressure);
1866                                 if(alpha) {
1867                                         do_weight_paint_vertex(wp, ob, mface->v2, 
1868                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1869                                                 wpd->vgroup_validmap, ts->multipaint);
1870                                 }
1871                                 (me->dvert+mface->v2)->flag= 0;
1872                         }
1873                                         
1874                         if((me->dvert+mface->v3)->flag) {
1875                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval, pressure);
1876                                 if(alpha) {
1877                                         do_weight_paint_vertex(wp, ob, mface->v3, 
1878                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1879                                                 wpd->vgroup_validmap, ts->multipaint);
1880                                 }
1881                                 (me->dvert+mface->v3)->flag= 0;
1882                         }
1883                                         
1884                         if((me->dvert+mface->v4)->flag) {
1885                                 if(mface->v4) {
1886                                         alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval, pressure);
1887                                         if(alpha) {
1888                                                 do_weight_paint_vertex(wp, ob, mface->v4, 
1889                                                         alpha, paintweight, flip, wpd->vgroup_mirror,
1890                                                         wpd->vgroup_validmap, ts->multipaint);
1891                                         }
1892                                         (me->dvert+mface->v4)->flag= 0;
1893                                 }
1894                         }
1895                 }
1896         }
1897                         
1898         swap_m4m4(vc->rv3d->persmat, mat);
1899                         
1900         DAG_id_tag_update(ob->data, 0);
1901         ED_region_tag_redraw(vc->ar);
1902 }
1903
1904 static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
1905 {
1906         ToolSettings *ts= CTX_data_tool_settings(C);
1907         Object *ob= CTX_data_active_object(C);
1908         struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1909         
1910         if(wpd) {
1911                 if(wpd->vertexcosnos)
1912                         MEM_freeN(wpd->vertexcosnos);
1913                 MEM_freeN(wpd->indexar);
1914                 
1915                 if (wpd->vgroup_validmap)
1916                         MEM_freeN(wpd->vgroup_validmap);
1917                 
1918                 MEM_freeN(wpd);
1919         }
1920         
1921         /* frees prev buffer */
1922         copy_wpaint_prev(ts->wpaint, NULL, 0);
1923         
1924         /* and particles too */
1925         if(ob->particlesystem.first) {
1926                 ParticleSystem *psys;
1927                 int i;
1928                 
1929                 for(psys= ob->particlesystem.first; psys; psys= psys->next) {
1930                         for(i=0; i<PSYS_TOT_VG; i++) {
1931                                 if(psys->vgroup[i]==ob->actdef) {
1932                                         psys->recalc |= PSYS_RECALC_RESET;
1933                                         break;
1934                                 }
1935                         }
1936                 }
1937         }
1938         
1939         DAG_id_tag_update(ob->data, 0);
1940 }
1941
1942
1943 static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
1944 {
1945         
1946         op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
1947                                           wpaint_stroke_update_step,
1948                                           wpaint_stroke_done, event->type);
1949         
1950         /* add modal handler */
1951         WM_event_add_modal_handler(C, op);
1952
1953         op->type->modal(C, op, event);
1954         
1955         return OPERATOR_RUNNING_MODAL;
1956 }
1957
1958 void PAINT_OT_weight_paint(wmOperatorType *ot)
1959 {
1960         
1961         /* identifiers */
1962         ot->name= "Weight Paint";
1963         ot->idname= "PAINT_OT_weight_paint";
1964         
1965         /* api callbacks */
1966         ot->invoke= wpaint_invoke;
1967         ot->modal= paint_stroke_modal;
1968         /* ot->exec= vpaint_exec; <-- needs stroke property */
1969         ot->poll= weight_paint_poll;
1970         
1971         /* flags */
1972         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
1973
1974         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1975 }
1976
1977 static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
1978 {
1979         struct Scene *scene= CTX_data_scene(C);
1980         Object *obact = CTX_data_active_object(C);
1981
1982         wpaint_fill(scene->toolsettings->wpaint, obact, scene->toolsettings->vgroup_weight);
1983         ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
1984         return OPERATOR_FINISHED;
1985 }
1986
1987 void PAINT_OT_weight_set(wmOperatorType *ot)
1988 {
1989         /* identifiers */
1990         ot->name= "Set Weight";
1991         ot->idname= "PAINT_OT_weight_set";
1992
1993         /* api callbacks */
1994         ot->exec= weight_paint_set_exec;
1995         ot->poll= facemask_paint_poll;
1996
1997         /* flags */
1998         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1999 }
2000
2001 /* ************ set / clear vertex paint mode ********** */
2002
2003
2004 static int set_vpaint(bContext *C, wmOperator *op)              /* toggle */
2005 {       
2006         Object *ob= CTX_data_active_object(C);
2007         Scene *scene= CTX_data_scene(C);
2008         VPaint *vp= scene->toolsettings->vpaint;
2009         Mesh *me;
2010         
2011         me= get_mesh(ob);
2012         
2013         if(me==NULL || object_data_is_libdata(ob)) {
2014                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2015                 return OPERATOR_PASS_THROUGH;
2016         }
2017         
2018         if(me && me->mcol==NULL) make_vertexcol(ob);
2019         
2020         /* toggle: end vpaint */
2021         if(ob->mode & OB_MODE_VERTEX_PAINT) {
2022                 
2023                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2024         }
2025         else {
2026                 ob->mode |= OB_MODE_VERTEX_PAINT;
2027                 /* Turn off weight painting */
2028                 if (ob->mode & OB_MODE_WEIGHT_PAINT)
2029                         set_wpaint(C, op);
2030                 
2031                 if(vp==NULL)
2032                         vp= scene->toolsettings->vpaint= new_vpaint(0);
2033                 
2034                 paint_cursor_start(C, vertex_paint_poll);
2035
2036                 paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
2037         }
2038         
2039         if (me)
2040                 /* update modifier stack for mapping requirements */
2041                 DAG_id_tag_update(&me->id, 0);
2042         
2043         WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
2044         
2045         return OPERATOR_FINISHED;
2046 }
2047
2048 void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
2049 {
2050         
2051         /* identifiers */
2052         ot->name= "Vertex Paint Mode";
2053         ot->idname= "PAINT_OT_vertex_paint_toggle";
2054         
2055         /* api callbacks */
2056         ot->exec= set_vpaint;
2057         ot->poll= paint_poll_test;
2058         
2059         /* flags */
2060         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2061 }
2062
2063
2064
2065 /* ********************** vertex paint operator ******************* */
2066
2067 /* Implementation notes:
2068
2069 Operator->invoke()
2070   - validate context (add mcol)
2071   - create customdata storage
2072   - call paint once (mouse click)
2073   - add modal handler 
2074
2075 Operator->modal()
2076   - for every mousemove, apply vertex paint
2077   - exit on mouse release, free customdata
2078         (return OPERATOR_FINISHED also removes handler and operator)
2079
2080 For future:
2081   - implement a stroke event (or mousemove with past positons)
2082   - revise whether op->customdata should be added in object, in set_vpaint
2083
2084 */
2085
2086 typedef struct VPaintData {
2087         ViewContext vc;
2088         unsigned int paintcol;
2089         int *indexar;
2090         float *vertexcosnos;
2091         float vpimat[3][3];
2092 } VPaintData;
2093
2094 static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
2095 {
2096         ToolSettings *ts= CTX_data_tool_settings(C);
2097         struct PaintStroke *stroke = op->customdata;
2098         VPaint *vp= ts->vpaint;
2099         struct VPaintData *vpd;
2100         Object *ob= CTX_data_active_object(C);
2101         Mesh *me;
2102         float mat[4][4], imat[4][4];
2103
2104         /* context checks could be a poll() */
2105         me= get_mesh(ob);
2106         if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
2107         
2108         if(me->mcol==NULL) make_vertexcol(ob);
2109         if(me->mcol==NULL) return OPERATOR_CANCELLED;
2110         
2111         /* make mode data storage */
2112         vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
2113         paint_stroke_set_mode_data(stroke, vpd);
2114         view3d_set_viewcontext(C, &vpd->vc);
2115         
2116         vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
2117         vpd->indexar= get_indexarray(me);
2118         vpd->paintcol= vpaint_get_current_col(vp);
2119         
2120         /* for filtering */
2121         copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
2122         
2123         /* some old cruft to sort out later */
2124         mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
2125         invert_m4_m4(imat, mat);
2126         copy_m3_m4(vpd->vpimat, imat);
2127
2128         return 1;
2129 }
2130
2131 static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
2132 {
2133         ViewContext *vc = &vpd->vc;
2134         Brush *brush = paint_brush(&vp->paint);
2135         Mesh *me = get_mesh(ob);
2136         MFace *mface= ((MFace*)me->mface) + index;
2137         unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
2138         unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
2139         float alpha;
2140         int i;
2141         
2142         if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
2143            ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
2144                 return;
2145
2146         if(brush->vertexpaint_tool==VP_BLUR) {
2147                 unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
2148                 if(mface->v4) {
2149                         unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
2150                         vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
2151                 }
2152                 else {
2153                         vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
2154                 }
2155                 
2156         }
2157
2158         for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
2159                 alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval, pressure);
2160                 if(alpha)
2161                         vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
2162         }
2163 }
2164
2165 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2166 {
2167         ToolSettings *ts= CTX_data_tool_settings(C);
2168         struct VPaintData *vpd = paint_stroke_mode_data(stroke);
2169         VPaint *vp= ts->vpaint;
2170         Brush *brush = paint_brush(&vp->paint);
2171         ViewContext *vc= &vpd->vc;
2172         Object *ob= vc->obact;
2173         Mesh *me= ob->data;
2174         float mat[4][4];
2175         int *indexar= vpd->indexar;
2176         int totindex, index, flip;
2177         float pressure, mval[2];
2178
2179         RNA_float_get_array(itemptr, "mouse", mval);
2180         flip = RNA_boolean_get(itemptr, "pen_flip");
2181         pressure = RNA_float_get(itemptr, "pressure");
2182                         
2183         view3d_operator_needs_opengl(C);
2184                         
2185         /* load projection matrix */
2186         mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
2187
2188         mval[0]-= vc->ar->winrct.xmin;
2189         mval[1]-= vc->ar->winrct.ymin;
2190
2191                         
2192         /* which faces are involved */
2193         if(vp->flag & VP_AREA) {
2194                 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
2195         }
2196         else {
2197                 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
2198                 if(indexar[0]) totindex= 1;
2199                 else totindex= 0;
2200         }
2201                         
2202         swap_m4m4(vc->rv3d->persmat, mat);
2203                         
2204         for(index=0; index<totindex; index++) {                         
2205                 if(indexar[index] && indexar[index]<=me->totface)
2206                         vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
2207         }
2208                                                 
2209         swap_m4m4(vc->rv3d->persmat, mat);
2210
2211         /* was disabled because it is slow, but necessary for blur */
2212         if(brush->vertexpaint_tool == VP_BLUR)
2213                 do_shared_vertexcol(me);
2214                         
2215         ED_region_tag_redraw(vc->ar);
2216                         
2217         DAG_id_tag_update(ob->data, 0);
2218 }
2219
2220 static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
2221 {
2222         ToolSettings *ts= CTX_data_tool_settings(C);
2223         struct VPaintData *vpd= paint_stroke_mode_data(stroke);
2224         
2225         if(vpd->vertexcosnos)
2226                 MEM_freeN(vpd->vertexcosnos);
2227         MEM_freeN(vpd->indexar);
2228         
2229         /* frees prev buffer */
2230         copy_vpaint_prev(ts->vpaint, NULL, 0);
2231         
2232         MEM_freeN(vpd);
2233 }
2234
2235 static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
2236 {
2237         
2238         op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
2239                                           vpaint_stroke_update_step,
2240                                           vpaint_stroke_done, event->type);
2241         
2242         /* add modal handler */
2243         WM_event_add_modal_handler(C, op);
2244
2245         op->type->modal(C, op, event);
2246         
2247         return OPERATOR_RUNNING_MODAL;
2248 }
2249
2250 void PAINT_OT_vertex_paint(wmOperatorType *ot)
2251 {
2252         /* identifiers */
2253         ot->name= "Vertex Paint";
2254         ot->idname= "PAINT_OT_vertex_paint";
2255         
2256         /* api callbacks */
2257         ot->invoke= vpaint_invoke;
2258         ot->modal= paint_stroke_modal;
2259         /* ot->exec= vpaint_exec; <-- needs stroke property */
2260         ot->poll= vertex_paint_poll;
2261         
2262         /* flags */
2263         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
2264
2265         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
2266 }
2267
2268 /* ********************** weight from bones operator ******************* */
2269
2270 static int weight_from_bones_poll(bContext *C)
2271 {
2272         Object *ob= CTX_data_active_object(C);
2273
2274         return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob));
2275 }
2276
2277 static int weight_from_bones_exec(bContext *C, wmOperator *op)
2278 {
2279         Scene *scene= CTX_data_scene(C);
2280         Object *ob= CTX_data_active_object(C);
2281         Object *armob= modifiers_isDeformedByArmature(ob);
2282         Mesh *me= ob->data;
2283         int type= RNA_enum_get(op->ptr, "type");
2284
2285         create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
2286
2287         DAG_id_tag_update(&me->id, 0);
2288         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
2289
2290         return OPERATOR_FINISHED;
2291 }
2292
2293 void PAINT_OT_weight_from_bones(wmOperatorType *ot)
2294 {
2295         static EnumPropertyItem type_items[]= {
2296                 {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights froms bones"},
2297                 {ARM_GROUPS_ENVELOPE, "ENVELOPES", 0, "From Envelopes", "Weights from envelopes with user defined radius"},
2298                 {0, NULL, 0, NULL, NULL}};
2299
2300         /* identifiers */
2301         ot->name= "Weight from Bones";
2302         ot->idname= "PAINT_OT_weight_from_bones";
2303         
2304         /* api callbacks */
2305         ot->exec= weight_from_bones_exec;
2306         ot->invoke= WM_menu_invoke;
2307         ot->poll= weight_from_bones_poll;
2308         
2309         /* flags */
2310         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2311
2312         /* properties */
2313         ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights.");
2314 }
2315