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