5485401d5c950cd980d88e3cf123f4f103a54b18
[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                                         // TODO get BONE_SELECTED flag
1397                                         dg_flags[i] = (chan->bone->flag & 1);
1398                                         was_selected = TRUE;
1399                                 }
1400                         }
1401                 }
1402         }
1403         
1404         return dg_flags;
1405 }
1406 // Jason
1407 static char *wpaint_make_validmap(Object *ob);
1408
1409 static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, 
1410                                    float alpha, float paintweight, int flip, 
1411                                    int vgroup_mirror, char *validmap, int multipaint)
1412 {
1413         Mesh *me= ob->data;
1414         MDeformWeight *dw, *uw;
1415         int vgroup= ob->actdef-1;
1416
1417         /* Jason was here */
1418         char *flags;
1419         char *bone_groups;
1420         char *selection;
1421         float oldw;
1422         int defcnt;
1423         if(validmap) {
1424                 bone_groups = validmap;
1425         }else {
1426                 bone_groups = wpaint_make_validmap(ob);
1427         }
1428
1429         if(wp->flag & VP_ONLYVGROUP) {
1430                 dw= defvert_find_index(me->dvert+index, vgroup);
1431                 uw= defvert_find_index(wp->wpaint_prev+index, vgroup);
1432         }
1433         else {
1434                 dw= defvert_verify_index(me->dvert+index, vgroup);
1435                 uw= defvert_verify_index(wp->wpaint_prev+index, vgroup);
1436         }
1437         if(dw==NULL || uw==NULL)
1438                 return;
1439         /* Jason was here */
1440         flags = gen_lck_flags(ob, defcnt = BLI_countlist(&ob->defbase), bone_groups);
1441         selection = get_selected_defgroups(ob, defcnt);
1442         oldw = dw->weight;
1443         wpaint_blend(wp, dw, uw, alpha, paintweight, flip);
1444         /* Jason was here */
1445         check_locks_and_normalize(ob, me, index, vgroup, dw, oldw, validmap, flags, defcnt, bone_groups, selection, multipaint);
1446
1447         if(me->editflag & ME_EDIT_MIRROR_X) {   /* x mirror painting */
1448                 int j= mesh_get_x_mirror_vert(ob, index);
1449                 if(j>=0) {
1450                         /* copy, not paint again */
1451                         if(vgroup_mirror != -1)
1452                                 uw= defvert_verify_index(me->dvert+j, vgroup_mirror);
1453                         else
1454                                 uw= defvert_verify_index(me->dvert+j, vgroup);
1455                         /* Jason */
1456                         oldw = uw->weight;
1457
1458                         uw->weight= dw->weight;
1459                         /* Jason */
1460                         check_locks_and_normalize(ob, me, j, vgroup, uw, oldw, validmap, flags, defcnt, bone_groups, selection, multipaint);
1461                 }
1462         }
1463         /* Jason */
1464         if(flags) {
1465                 MEM_freeN(flags);
1466         }
1467         if(selection) {
1468                 MEM_freeN(selection);
1469         }
1470         if(!validmap) {
1471                 MEM_freeN(bone_groups);
1472         }
1473 }
1474
1475
1476 /* *************** set wpaint operator ****************** */
1477
1478 static int set_wpaint(bContext *C, wmOperator *UNUSED(op))              /* toggle */
1479 {               
1480         Object *ob= CTX_data_active_object(C);
1481         Scene *scene= CTX_data_scene(C);
1482         VPaint *wp= scene->toolsettings->wpaint;
1483         Mesh *me;
1484         
1485         me= get_mesh(ob);
1486         if(ob->id.lib || me==NULL) return OPERATOR_PASS_THROUGH;
1487         
1488         if(ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
1489         else ob->mode |= OB_MODE_WEIGHT_PAINT;
1490         
1491         
1492         /* Weightpaint works by overriding colors in mesh,
1493                 * so need to make sure we recalc on enter and
1494                 * exit (exit needs doing regardless because we
1495                                 * should redeform).
1496                 */
1497         DAG_id_tag_update(&me->id, 0);
1498         
1499         if(ob->mode & OB_MODE_WEIGHT_PAINT) {
1500                 Object *par;
1501                 
1502                 if(wp==NULL)
1503                         wp= scene->toolsettings->wpaint= new_vpaint(1);
1504
1505                 paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
1506                 paint_cursor_start(C, weight_paint_poll);
1507                 
1508                 mesh_octree_table(ob, NULL, NULL, 's');
1509                 
1510                 /* verify if active weight group is also active bone */
1511                 par= modifiers_isDeformedByArmature(ob);
1512                 if(par && (par->mode & OB_MODE_POSE)) {
1513                         bArmature *arm= par->data;
1514
1515                         if(arm->act_bone)
1516                                 ED_vgroup_select_by_name(ob, arm->act_bone->name);
1517                 }
1518         }
1519         else {
1520                 mesh_octree_table(NULL, NULL, NULL, 'e');
1521                 mesh_mirrtopo_table(NULL, 'e');
1522         }
1523         
1524         WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
1525         
1526         return OPERATOR_FINISHED;
1527 }
1528
1529 /* for switching to/from mode */
1530 static int paint_poll_test(bContext *C)
1531 {
1532         if(CTX_data_edit_object(C))
1533                 return 0;
1534         if(CTX_data_active_object(C)==NULL)
1535                 return 0;
1536         return 1;
1537 }
1538
1539 void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
1540 {
1541         
1542         /* identifiers */
1543         ot->name= "Weight Paint Mode";
1544         ot->idname= "PAINT_OT_weight_paint_toggle";
1545         
1546         /* api callbacks */
1547         ot->exec= set_wpaint;
1548         ot->poll= paint_poll_test;
1549         
1550         /* flags */
1551         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1552         
1553 }
1554
1555 /* ************ weight paint operator ********** */
1556
1557 struct WPaintData {
1558         ViewContext vc;
1559         int *indexar;
1560         int vgroup_mirror;
1561         float *vertexcosnos;
1562         float wpimat[3][3];
1563         
1564         /*variables for auto normalize*/
1565         int auto_normalize;
1566         char *vgroup_validmap; /*stores if vgroups tie to deforming bones or not*/
1567 };
1568
1569 static char *wpaint_make_validmap(Object *ob)
1570 {
1571         bDeformGroup *dg;
1572         ModifierData *md;
1573         char *validmap;
1574         bPose *pose;
1575         bPoseChannel *chan;
1576         ArmatureModifierData *amd;
1577         GHash *gh = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "wpaint_make_validmap gh");
1578         int i = 0, step1=1;
1579
1580         /*add all names to a hash table*/
1581         for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1582                 BLI_ghash_insert(gh, dg->name, NULL);
1583         }
1584
1585         if (!i)
1586                 return NULL;
1587
1588         validmap = MEM_callocN(i, "wpaint valid map");
1589
1590         /*now loop through the armature modifiers and identify deform bones*/
1591         for (md = ob->modifiers.first; md; md= !md->next && step1 ? (step1=0), modifiers_getVirtualModifierList(ob) : md->next) {
1592                 if (!(md->mode & (eModifierMode_Realtime|eModifierMode_Virtual)))
1593                         continue;
1594
1595                 if (md->type == eModifierType_Armature) 
1596                 {
1597                         amd = (ArmatureModifierData*) md;
1598
1599                         if(amd->object && amd->object->pose) {
1600                                 pose = amd->object->pose;
1601                                 
1602                                 for (chan=pose->chanbase.first; chan; chan=chan->next) {
1603                                         if (chan->bone->flag & BONE_NO_DEFORM)
1604                                                 continue;
1605
1606                                         if (BLI_ghash_haskey(gh, chan->name)) {
1607                                                 BLI_ghash_remove(gh, chan->name, NULL, NULL);
1608                                                 BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
1609                                         }
1610                                 }
1611                         }
1612                 }
1613         }
1614         
1615         /*add all names to a hash table*/
1616         for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1617                 if (BLI_ghash_lookup(gh, dg->name) != NULL) {
1618                         validmap[i] = 1;
1619                 }
1620         }
1621
1622         BLI_ghash_free(gh, NULL, NULL);
1623
1624         return validmap;
1625 }
1626
1627 static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1628 {
1629         Scene *scene= CTX_data_scene(C);
1630         struct PaintStroke *stroke = op->customdata;
1631         ToolSettings *ts= CTX_data_tool_settings(C);
1632         VPaint *wp= ts->wpaint;
1633         Object *ob= CTX_data_active_object(C);
1634         struct WPaintData *wpd;
1635         Mesh *me;
1636         float mat[4][4], imat[4][4];
1637
1638         if(scene->obedit) return OPERATOR_CANCELLED;
1639         
1640         me= get_mesh(ob);
1641         if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
1642         
1643         /* if nothing was added yet, we make dverts and a vertex deform group */
1644         if (!me->dvert) {
1645                 ED_vgroup_data_create(&me->id);
1646                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
1647         }
1648
1649
1650         /* make mode data storage */
1651         wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
1652         paint_stroke_set_mode_data(stroke, wpd);
1653         view3d_set_viewcontext(C, &wpd->vc);
1654         wpd->vgroup_mirror= -1;
1655
1656         /*set up auto-normalize, and generate map for detecting which
1657           vgroups affect deform bones*/
1658         wpd->auto_normalize = ts->auto_normalize;
1659         if (wpd->auto_normalize)
1660                 wpd->vgroup_validmap = wpaint_make_validmap(ob);
1661         
1662         //      if(qual & LR_CTRLKEY) {
1663         //              sample_wpaint(scene, ar, v3d, 0);
1664         //              return;
1665         //      }
1666         //      if(qual & LR_SHIFTKEY) {
1667         //              sample_wpaint(scene, ar, v3d, 1);
1668         //              return;
1669         //      }
1670         
1671         /* ALLOCATIONS! no return after this line */
1672         /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1673         wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
1674         wpd->indexar= get_indexarray(me);
1675         copy_wpaint_prev(wp, me->dvert, me->totvert);
1676         
1677         /* this happens on a Bone select, when no vgroup existed yet */
1678         if(ob->actdef<=0) {
1679                 Object *modob;
1680                 if((modob = modifiers_isDeformedByArmature(ob))) {
1681                         Bone *actbone= ((bArmature *)modob->data)->act_bone;
1682                         if(actbone) {
1683                                 bPoseChannel *pchan= get_pose_channel(modob->pose, actbone->name);
1684
1685                                 if(pchan) {
1686                                         bDeformGroup *dg= defgroup_find_name(ob, pchan->name);
1687                                         if(dg==NULL)
1688                                                 dg= ED_vgroup_add_name(ob, pchan->name);        /* sets actdef */
1689                                         else
1690                                                 ob->actdef= 1 + defgroup_find_index(ob, dg);
1691                                 }
1692                         }
1693                 }
1694         }
1695         if(ob->defbase.first==NULL) {
1696                 ED_vgroup_add(ob);
1697         }
1698         
1699         //      if(ob->lay & v3d->lay); else error("Active object is not in this layer");
1700         
1701         /* imat for normals */
1702         mul_m4_m4m4(mat, ob->obmat, wpd->vc.rv3d->viewmat);
1703         invert_m4_m4(imat, mat);
1704         copy_m3_m4(wpd->wpimat, imat);
1705         
1706         /* if mirror painting, find the other group */
1707         if(me->editflag & ME_EDIT_MIRROR_X) {
1708                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
1709                 if(defgroup) {
1710                         bDeformGroup *curdef;
1711                         int actdef= 0;
1712                         char name[32];
1713
1714                         flip_side_name(name, defgroup->name, FALSE);
1715
1716                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
1717                                 if (!strcmp(curdef->name, name))
1718                                         break;
1719                         if(curdef==NULL) {
1720                                 int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
1721                                 curdef= ED_vgroup_add_name (ob, name);
1722                                 ob->actdef= olddef;
1723                         }
1724                         
1725                         if(curdef && curdef!=defgroup)
1726                                 wpd->vgroup_mirror= actdef;
1727                 }
1728         }
1729
1730         return 1;
1731 }
1732
1733 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
1734 {
1735         ToolSettings *ts= CTX_data_tool_settings(C);
1736         VPaint *wp= ts->wpaint;
1737         Brush *brush = paint_brush(&wp->paint);
1738         struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1739         ViewContext *vc;
1740         Object *ob;
1741         Mesh *me;
1742         float mat[4][4];
1743         float paintweight;
1744         int *indexar;
1745         int totindex, index, totw, flip;
1746         float alpha;
1747         float mval[2], pressure;
1748         
1749         /* cannot paint if there is no stroke data */
1750         if (wpd == NULL) {
1751                 // XXX: force a redraw here, since even though we can't paint, 
1752                 // at least view won't freeze until stroke ends
1753                 ED_region_tag_redraw(CTX_wm_region(C));
1754                 return;
1755         }
1756                 
1757         vc= &wpd->vc;
1758         ob= vc->obact;
1759         me= ob->data;
1760         indexar= wpd->indexar;
1761         
1762         view3d_operator_needs_opengl(C);
1763                 
1764         /* load projection matrix */
1765         mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
1766
1767         flip = RNA_boolean_get(itemptr, "pen_flip");
1768         pressure = RNA_float_get(itemptr, "pressure");
1769         RNA_float_get_array(itemptr, "mouse", mval);
1770         mval[0]-= vc->ar->winrct.xmin;
1771         mval[1]-= vc->ar->winrct.ymin;
1772                         
1773         swap_m4m4(wpd->vc.rv3d->persmat, mat);
1774                         
1775         /* which faces are involved */
1776         if(wp->flag & VP_AREA) {
1777                 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
1778         }
1779         else {
1780                 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
1781                 if(indexar[0]) totindex= 1;
1782                 else totindex= 0;
1783         }
1784                         
1785         if(wp->flag & VP_COLINDEX) {
1786                 for(index=0; index<totindex; index++) {
1787                         if(indexar[index] && indexar[index]<=me->totface) {
1788                                 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1789                                                 
1790                                 if(mface->mat_nr!=ob->actcol-1) {
1791                                         indexar[index]= 0;
1792                                 }
1793                         }
1794                 }
1795         }
1796                         
1797         if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
1798                 for(index=0; index<totindex; index++) {
1799                         if(indexar[index] && indexar[index]<=me->totface) {
1800                                 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1801                                                 
1802                                 if((mface->flag & ME_FACE_SEL)==0) {
1803                                         indexar[index]= 0;
1804                                 }
1805                         }                                       
1806                 }
1807         }
1808                         
1809         /* make sure each vertex gets treated only once */
1810         /* and calculate filter weight */
1811         totw= 0;
1812         if(brush->vertexpaint_tool==VP_BLUR) 
1813                 paintweight= 0.0f;
1814         else
1815                 paintweight= ts->vgroup_weight;
1816                         
1817         for(index=0; index<totindex; index++) {
1818                 if(indexar[index] && indexar[index]<=me->totface) {
1819                         MFace *mface= me->mface + (indexar[index]-1);
1820                                         
1821                         (me->dvert+mface->v1)->flag= 1;
1822                         (me->dvert+mface->v2)->flag= 1;
1823                         (me->dvert+mface->v3)->flag= 1;
1824                         if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1825                                         
1826                         if(brush->vertexpaint_tool==VP_BLUR) {
1827                                 MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
1828                                                 
1829                                 if(wp->flag & VP_ONLYVGROUP)
1830                                         dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
1831                                 else
1832                                         dw_func= defvert_verify_index;
1833                                                 
1834                                 dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
1835                                 if(dw) {paintweight+= dw->weight; totw++;}
1836                                 dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
1837                                 if(dw) {paintweight+= dw->weight; totw++;}
1838                                 dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
1839                                 if(dw) {paintweight+= dw->weight; totw++;}
1840                                 if(mface->v4) {
1841                                         dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
1842                                         if(dw) {paintweight+= dw->weight; totw++;}
1843                                 }
1844                         }
1845                 }
1846         }
1847                         
1848         if(brush->vertexpaint_tool==VP_BLUR) 
1849                 paintweight/= (float)totw;
1850                         
1851         for(index=0; index<totindex; index++) {
1852                                 
1853                 if(indexar[index] && indexar[index]<=me->totface) {
1854                         MFace *mface= me->mface + (indexar[index]-1);
1855                                         
1856                         if((me->dvert+mface->v1)->flag) {
1857                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval, pressure);
1858                                 if(alpha) {
1859                                         do_weight_paint_vertex(wp, ob, mface->v1, 
1860                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1861                                                 wpd->vgroup_validmap, ts->multipaint);
1862                                 }
1863                                 (me->dvert+mface->v1)->flag= 0;
1864                         }
1865                                         
1866                         if((me->dvert+mface->v2)->flag) {
1867                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval, pressure);
1868                                 if(alpha) {
1869                                         do_weight_paint_vertex(wp, ob, mface->v2, 
1870                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1871                                                 wpd->vgroup_validmap, ts->multipaint);
1872                                 }
1873                                 (me->dvert+mface->v2)->flag= 0;
1874                         }
1875                                         
1876                         if((me->dvert+mface->v3)->flag) {
1877                                 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval, pressure);
1878                                 if(alpha) {
1879                                         do_weight_paint_vertex(wp, ob, mface->v3, 
1880                                                 alpha, paintweight, flip, wpd->vgroup_mirror, 
1881                                                 wpd->vgroup_validmap, ts->multipaint);
1882                                 }
1883                                 (me->dvert+mface->v3)->flag= 0;
1884                         }
1885                                         
1886                         if((me->dvert+mface->v4)->flag) {
1887                                 if(mface->v4) {
1888                                         alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval, pressure);
1889                                         if(alpha) {
1890                                                 do_weight_paint_vertex(wp, ob, mface->v4, 
1891                                                         alpha, paintweight, flip, wpd->vgroup_mirror,
1892                                                         wpd->vgroup_validmap, ts->multipaint);
1893                                         }
1894                                         (me->dvert+mface->v4)->flag= 0;
1895                                 }
1896                         }
1897                 }
1898         }
1899                         
1900         swap_m4m4(vc->rv3d->persmat, mat);
1901                         
1902         DAG_id_tag_update(ob->data, 0);
1903         ED_region_tag_redraw(vc->ar);
1904 }
1905
1906 static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
1907 {
1908         ToolSettings *ts= CTX_data_tool_settings(C);
1909         Object *ob= CTX_data_active_object(C);
1910         struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1911         
1912         if(wpd) {
1913                 if(wpd->vertexcosnos)
1914                         MEM_freeN(wpd->vertexcosnos);
1915                 MEM_freeN(wpd->indexar);
1916                 
1917                 if (wpd->vgroup_validmap)
1918                         MEM_freeN(wpd->vgroup_validmap);
1919                 
1920                 MEM_freeN(wpd);
1921         }
1922         
1923         /* frees prev buffer */
1924         copy_wpaint_prev(ts->wpaint, NULL, 0);
1925         
1926         /* and particles too */
1927         if(ob->particlesystem.first) {
1928                 ParticleSystem *psys;
1929                 int i;
1930                 
1931                 for(psys= ob->particlesystem.first; psys; psys= psys->next) {
1932                         for(i=0; i<PSYS_TOT_VG; i++) {
1933                                 if(psys->vgroup[i]==ob->actdef) {
1934                                         psys->recalc |= PSYS_RECALC_RESET;
1935                                         break;
1936                                 }
1937                         }
1938                 }
1939         }
1940         
1941         DAG_id_tag_update(ob->data, 0);
1942 }
1943
1944
1945 static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
1946 {
1947         
1948         op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
1949                                           wpaint_stroke_update_step,
1950                                           wpaint_stroke_done, event->type);
1951         
1952         /* add modal handler */
1953         WM_event_add_modal_handler(C, op);
1954
1955         op->type->modal(C, op, event);
1956         
1957         return OPERATOR_RUNNING_MODAL;
1958 }
1959
1960 void PAINT_OT_weight_paint(wmOperatorType *ot)
1961 {
1962         
1963         /* identifiers */
1964         ot->name= "Weight Paint";
1965         ot->idname= "PAINT_OT_weight_paint";
1966         
1967         /* api callbacks */
1968         ot->invoke= wpaint_invoke;
1969         ot->modal= paint_stroke_modal;
1970         /* ot->exec= vpaint_exec; <-- needs stroke property */
1971         ot->poll= weight_paint_poll;
1972         
1973         /* flags */
1974         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
1975
1976         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1977 }
1978
1979 static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
1980 {
1981         struct Scene *scene= CTX_data_scene(C);
1982         Object *obact = CTX_data_active_object(C);
1983
1984         wpaint_fill(scene->toolsettings->wpaint, obact, scene->toolsettings->vgroup_weight);
1985         ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
1986         return OPERATOR_FINISHED;
1987 }
1988
1989 void PAINT_OT_weight_set(wmOperatorType *ot)
1990 {
1991         /* identifiers */
1992         ot->name= "Set Weight";
1993         ot->idname= "PAINT_OT_weight_set";
1994
1995         /* api callbacks */
1996         ot->exec= weight_paint_set_exec;
1997         ot->poll= facemask_paint_poll;
1998
1999         /* flags */
2000         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2001 }
2002
2003 /* ************ set / clear vertex paint mode ********** */
2004
2005
2006 static int set_vpaint(bContext *C, wmOperator *op)              /* toggle */
2007 {       
2008         Object *ob= CTX_data_active_object(C);
2009         Scene *scene= CTX_data_scene(C);
2010         VPaint *vp= scene->toolsettings->vpaint;
2011         Mesh *me;
2012         
2013         me= get_mesh(ob);
2014         
2015         if(me==NULL || object_data_is_libdata(ob)) {
2016                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2017                 return OPERATOR_PASS_THROUGH;
2018         }
2019         
2020         if(me && me->mcol==NULL) make_vertexcol(ob);
2021         
2022         /* toggle: end vpaint */
2023         if(ob->mode & OB_MODE_VERTEX_PAINT) {
2024                 
2025                 ob->mode &= ~OB_MODE_VERTEX_PAINT;
2026         }
2027         else {
2028                 ob->mode |= OB_MODE_VERTEX_PAINT;
2029                 /* Turn off weight painting */
2030                 if (ob->mode & OB_MODE_WEIGHT_PAINT)
2031                         set_wpaint(C, op);
2032                 
2033                 if(vp==NULL)
2034                         vp= scene->toolsettings->vpaint= new_vpaint(0);
2035                 
2036                 paint_cursor_start(C, vertex_paint_poll);
2037
2038                 paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
2039         }
2040         
2041         if (me)
2042                 /* update modifier stack for mapping requirements */
2043                 DAG_id_tag_update(&me->id, 0);
2044         
2045         WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
2046         
2047         return OPERATOR_FINISHED;
2048 }
2049
2050 void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
2051 {
2052         
2053         /* identifiers */
2054         ot->name= "Vertex Paint Mode";
2055         ot->idname= "PAINT_OT_vertex_paint_toggle";
2056         
2057         /* api callbacks */
2058         ot->exec= set_vpaint;
2059         ot->poll= paint_poll_test;
2060         
2061         /* flags */
2062         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2063 }
2064
2065
2066
2067 /* ********************** vertex paint operator ******************* */
2068
2069 /* Implementation notes:
2070
2071 Operator->invoke()
2072   - validate context (add mcol)
2073   - create customdata storage
2074   - call paint once (mouse click)
2075   - add modal handler 
2076
2077 Operator->modal()
2078   - for every mousemove, apply vertex paint
2079   - exit on mouse release, free customdata
2080         (return OPERATOR_FINISHED also removes handler and operator)
2081
2082 For future:
2083   - implement a stroke event (or mousemove with past positons)
2084   - revise whether op->customdata should be added in object, in set_vpaint
2085
2086 */
2087
2088 typedef struct VPaintData {
2089         ViewContext vc;
2090         unsigned int paintcol;
2091         int *indexar;
2092         float *vertexcosnos;
2093         float vpimat[3][3];
2094 } VPaintData;
2095
2096 static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
2097 {
2098         ToolSettings *ts= CTX_data_tool_settings(C);
2099         struct PaintStroke *stroke = op->customdata;
2100         VPaint *vp= ts->vpaint;
2101         struct VPaintData *vpd;
2102         Object *ob= CTX_data_active_object(C);
2103         Mesh *me;
2104         float mat[4][4], imat[4][4];
2105
2106         /* context checks could be a poll() */
2107         me= get_mesh(ob);
2108         if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
2109         
2110         if(me->mcol==NULL) make_vertexcol(ob);
2111         if(me->mcol==NULL) return OPERATOR_CANCELLED;
2112         
2113         /* make mode data storage */
2114         vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
2115         paint_stroke_set_mode_data(stroke, vpd);
2116         view3d_set_viewcontext(C, &vpd->vc);
2117         
2118         vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
2119         vpd->indexar= get_indexarray(me);
2120         vpd->paintcol= vpaint_get_current_col(vp);
2121         
2122         /* for filtering */
2123         copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
2124         
2125         /* some old cruft to sort out later */
2126         mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
2127         invert_m4_m4(imat, mat);
2128         copy_m3_m4(vpd->vpimat, imat);
2129
2130         return 1;
2131 }
2132
2133 static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
2134 {
2135         ViewContext *vc = &vpd->vc;
2136         Brush *brush = paint_brush(&vp->paint);
2137         Mesh *me = get_mesh(ob);
2138         MFace *mface= ((MFace*)me->mface) + index;
2139         unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
2140         unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
2141         float alpha;
2142         int i;
2143         
2144         if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
2145            ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
2146                 return;
2147
2148         if(brush->vertexpaint_tool==VP_BLUR) {
2149                 unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
2150                 if(mface->v4) {
2151                         unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
2152                         vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
2153                 }
2154                 else {
2155                         vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
2156                 }
2157                 
2158         }
2159
2160         for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
2161                 alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval, pressure);
2162                 if(alpha)
2163                         vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
2164         }
2165 }
2166
2167 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
2168 {
2169         ToolSettings *ts= CTX_data_tool_settings(C);
2170         struct VPaintData *vpd = paint_stroke_mode_data(stroke);
2171         VPaint *vp= ts->vpaint;
2172         Brush *brush = paint_brush(&vp->paint);
2173         ViewContext *vc= &vpd->vc;
2174         Object *ob= vc->obact;
2175         Mesh *me= ob->data;
2176         float mat[4][4];
2177         int *indexar= vpd->indexar;
2178         int totindex, index, flip;
2179         float pressure, mval[2];
2180
2181         RNA_float_get_array(itemptr, "mouse", mval);
2182         flip = RNA_boolean_get(itemptr, "pen_flip");
2183         pressure = RNA_float_get(itemptr, "pressure");
2184                         
2185         view3d_operator_needs_opengl(C);
2186                         
2187         /* load projection matrix */
2188         mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
2189
2190         mval[0]-= vc->ar->winrct.xmin;
2191         mval[1]-= vc->ar->winrct.ymin;
2192
2193                         
2194         /* which faces are involved */
2195         if(vp->flag & VP_AREA) {
2196                 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
2197         }
2198         else {
2199                 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
2200                 if(indexar[0]) totindex= 1;
2201                 else totindex= 0;
2202         }
2203                         
2204         swap_m4m4(vc->rv3d->persmat, mat);
2205                         
2206         for(index=0; index<totindex; index++) {                         
2207                 if(indexar[index] && indexar[index]<=me->totface)
2208                         vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
2209         }
2210                                                 
2211         swap_m4m4(vc->rv3d->persmat, mat);
2212
2213         /* was disabled because it is slow, but necessary for blur */
2214         if(brush->vertexpaint_tool == VP_BLUR)
2215                 do_shared_vertexcol(me);
2216                         
2217         ED_region_tag_redraw(vc->ar);
2218                         
2219         DAG_id_tag_update(ob->data, 0);
2220 }
2221
2222 static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
2223 {
2224         ToolSettings *ts= CTX_data_tool_settings(C);
2225         struct VPaintData *vpd= paint_stroke_mode_data(stroke);
2226         
2227         if(vpd->vertexcosnos)
2228                 MEM_freeN(vpd->vertexcosnos);
2229         MEM_freeN(vpd->indexar);
2230         
2231         /* frees prev buffer */
2232         copy_vpaint_prev(ts->vpaint, NULL, 0);
2233         
2234         MEM_freeN(vpd);
2235 }
2236
2237 static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
2238 {
2239         
2240         op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
2241                                           vpaint_stroke_update_step,
2242                                           vpaint_stroke_done, event->type);
2243         
2244         /* add modal handler */
2245         WM_event_add_modal_handler(C, op);
2246
2247         op->type->modal(C, op, event);
2248         
2249         return OPERATOR_RUNNING_MODAL;
2250 }
2251
2252 void PAINT_OT_vertex_paint(wmOperatorType *ot)
2253 {
2254         /* identifiers */
2255         ot->name= "Vertex Paint";
2256         ot->idname= "PAINT_OT_vertex_paint";
2257         
2258         /* api callbacks */
2259         ot->invoke= vpaint_invoke;
2260         ot->modal= paint_stroke_modal;
2261         /* ot->exec= vpaint_exec; <-- needs stroke property */
2262         ot->poll= vertex_paint_poll;
2263         
2264         /* flags */
2265         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
2266
2267         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
2268 }
2269
2270 /* ********************** weight from bones operator ******************* */
2271
2272 static int weight_from_bones_poll(bContext *C)
2273 {
2274         Object *ob= CTX_data_active_object(C);
2275
2276         return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob));
2277 }
2278
2279 static int weight_from_bones_exec(bContext *C, wmOperator *op)
2280 {
2281         Scene *scene= CTX_data_scene(C);
2282         Object *ob= CTX_data_active_object(C);
2283         Object *armob= modifiers_isDeformedByArmature(ob);
2284         Mesh *me= ob->data;
2285         int type= RNA_enum_get(op->ptr, "type");
2286
2287         create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
2288
2289         DAG_id_tag_update(&me->id, 0);
2290         WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
2291
2292         return OPERATOR_FINISHED;
2293 }
2294
2295 void PAINT_OT_weight_from_bones(wmOperatorType *ot)
2296 {
2297         static EnumPropertyItem type_items[]= {
2298                 {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights froms bones"},
2299                 {ARM_GROUPS_ENVELOPE, "ENVELOPES", 0, "From Envelopes", "Weights from envelopes with user defined radius"},
2300                 {0, NULL, 0, NULL, NULL}};
2301
2302         /* identifiers */
2303         ot->name= "Weight from Bones";
2304         ot->idname= "PAINT_OT_weight_from_bones";
2305         
2306         /* api callbacks */
2307         ot->exec= weight_from_bones_exec;
2308         ot->invoke= WM_menu_invoke;
2309         ot->poll= weight_from_bones_poll;
2310         
2311         /* flags */
2312         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2313
2314         /* properties */
2315         ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights.");
2316 }
2317