4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
30 /** \file blender/editors/sculpt_paint/paint_vertex.c
44 #include "MEM_guardedalloc.h"
46 #include "BLI_blenlib.h"
48 #include "BLI_utildefines.h"
49 #include "BLI_ghash.h"
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
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"
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
66 #include "BKE_DerivedMesh.h"
67 #include "BKE_action.h"
68 #include "BKE_brush.h"
69 #include "BKE_context.h"
70 #include "BKE_depsgraph.h"
71 #include "BKE_deform.h"
73 #include "BKE_modifier.h"
74 #include "BKE_object.h"
75 #include "BKE_paint.h"
76 #include "BKE_report.h"
82 #include "ED_armature.h"
84 #include "ED_screen.h"
85 #include "ED_view3d.h"
87 #include "paint_intern.h"
89 /* brush->vertexpaint_tool */
98 /* polling - retrieve whether cursor should be set or operator should be done */
101 /* Returns true if vertex paint mode is active */
102 int vertex_paint_mode_poll(bContext *C)
104 Object *ob = CTX_data_active_object(C);
106 return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totface;
109 int vertex_paint_poll(bContext *C)
111 if(vertex_paint_mode_poll(C) &&
112 paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) {
113 ScrArea *sa= CTX_wm_area(C);
114 if(sa->spacetype==SPACE_VIEW3D) {
115 ARegion *ar= CTX_wm_region(C);
116 if(ar->regiontype==RGN_TYPE_WINDOW)
123 int weight_paint_mode_poll(bContext *C)
125 Object *ob = CTX_data_active_object(C);
127 return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totface;
130 int weight_paint_poll(bContext *C)
132 Object *ob= CTX_data_active_object(C);
136 (ob->mode & OB_MODE_WEIGHT_PAINT) &&
137 (paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
138 (sa= CTX_wm_area(C)) &&
139 (sa->spacetype == SPACE_VIEW3D)
141 ARegion *ar= CTX_wm_region(C);
142 if(ar->regiontype==RGN_TYPE_WINDOW) {
149 static VPaint *new_vpaint(int wpaint)
151 VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint");
153 vp->flag= VP_AREA+VP_SPRAY;
161 static int *get_indexarray(Mesh *me)
163 return MEM_mallocN(sizeof(int)*(me->totface+1), "vertexpaint");
167 /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte!
168 so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
170 static unsigned int rgba_to_mcol(float r, float g, float b, float a)
176 ir= floor(255.0f * r);
177 if(ir<0) ir= 0; else if(ir>255) ir= 255;
178 ig= floor(255.0f * g);
179 if(ig<0) ig= 0; else if(ig>255) ig= 255;
180 ib= floor(255.0f * b);
181 if(ib<0) ib= 0; else if(ib>255) ib= 255;
182 ia= floor(255.0f * a);
183 if(ia<0) ia= 0; else if(ia>255) ia= 255;
195 unsigned int vpaint_get_current_col(VPaint *vp)
197 Brush *brush = paint_brush(&vp->paint);
198 return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
201 static void do_shared_vertexcol(Mesh *me)
203 /* if no mcol: do not do */
204 /* if tface: only the involved faces, otherwise all */
208 short *scolmain, *scol;
211 if(me->mcol==NULL || me->totvert==0 || me->totface==0) return;
213 scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
217 mcol= (char *)me->mcol;
218 for(a=me->totface; a>0; a--, mface++, mcol+=16) {
219 if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
220 scol= scolmain+4*mface->v1;
221 scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
222 scol= scolmain+4*mface->v2;
223 scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
224 scol= scolmain+4*mface->v3;
225 scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
227 scol= scolmain+4*mface->v4;
228 scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
247 mcol= (char *)me->mcol;
248 for(a=me->totface; a>0; a--, mface++, mcol+=16) {
249 if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
250 scol= scolmain+4*mface->v1;
251 mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
252 scol= scolmain+4*mface->v2;
253 mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
254 scol= scolmain+4*mface->v3;
255 mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
257 scol= scolmain+4*mface->v4;
258 mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
267 static void make_vertexcol(Object *ob) /* single ob */
270 if(!ob || ob->id.lib) return;
273 if(me->edit_mesh) return;
275 /* copies from shadedisplist to mcol */
277 CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
278 mesh_update_customdata_pointers(me);
282 // shadeMeshMCol(scene, ob, me);
285 memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
287 DAG_id_tag_update(&me->id, 0);
291 static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
293 if(vp->vpaint_prev) {
294 MEM_freeN(vp->vpaint_prev);
295 vp->vpaint_prev= NULL;
299 if(mcol==NULL || tot==0) return;
301 vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
302 memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
306 static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
308 if (wp->wpaint_prev) {
309 free_dverts(wp->wpaint_prev, wp->tot);
310 wp->wpaint_prev= NULL;
313 if(dverts && dcount) {
315 wp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
317 copy_dverts (wp->wpaint_prev, dverts, dcount);
322 void vpaint_fill(Object *ob, unsigned int paintcol)
330 if(me==NULL || me->totface==0) return;
335 selected= (me->editflag & ME_EDIT_PAINT_MASK);
338 mcol = (unsigned int*)me->mcol;
339 for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
340 if (!selected || mf->flag & ME_FACE_SEL) {
348 DAG_id_tag_update(&me->id, 0);
352 /* fills in the selected faces with the current weight and vertex group */
353 void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
357 MDeformWeight *dw, *uw;
360 unsigned int faceverts[5]={0,0,0,0,0};
362 int vgroup_mirror= -1;
366 if(me==NULL || me->totface==0 || me->dvert==NULL || !me->mface) return;
368 selected= (me->editflag & ME_EDIT_PAINT_MASK);
370 indexar= get_indexarray(me);
373 for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
374 if((mface->flag & ME_FACE_SEL)==0)
377 indexar[index]= index+1;
381 for(index=0; index<me->totface; index++)
382 indexar[index]= index+1;
385 vgroup= ob->actdef-1;
387 /* directly copied from weight_paint, should probaby split into a separate function */
388 /* if mirror painting, find the other group */
389 if(me->editflag & ME_EDIT_MIRROR_X) {
390 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
392 bDeformGroup *curdef;
396 flip_side_name(name, defgroup->name, FALSE);
398 for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
399 if (!strcmp(curdef->name, name))
402 int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
403 curdef= ED_vgroup_add_name (ob, name);
407 if(curdef && curdef!=defgroup)
408 vgroup_mirror= actdef;
411 /* end copy from weight_paint*/
413 copy_wpaint_prev(wp, me->dvert, me->totvert);
415 for(index=0; index<me->totface; index++) {
416 if(indexar[index] && indexar[index]<=me->totface) {
417 mface= me->mface + (indexar[index]-1);
418 /* just so we can loop through the verts */
419 faceverts[0]= mface->v1;
420 faceverts[1]= mface->v2;
421 faceverts[2]= mface->v3;
422 faceverts[3]= mface->v4;
423 for (i=0; i<3 || faceverts[i]; i++) {
424 if(!((me->dvert+faceverts[i])->flag)) {
425 dw= defvert_verify_index(me->dvert+faceverts[i], vgroup);
427 uw= defvert_verify_index(wp->wpaint_prev+faceverts[i], vgroup);
428 uw->weight= dw->weight; /* set the undo weight */
429 dw->weight= paintweight;
431 if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
432 int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
434 /* copy, not paint again */
435 if(vgroup_mirror != -1) {
436 dw= defvert_verify_index(me->dvert+j, vgroup_mirror);
437 uw= defvert_verify_index(wp->wpaint_prev+j, vgroup_mirror);
439 dw= defvert_verify_index(me->dvert+j, vgroup);
440 uw= defvert_verify_index(wp->wpaint_prev+j, vgroup);
442 uw->weight= dw->weight; /* set the undo weight */
443 dw->weight= paintweight;
447 (me->dvert+faceverts[i])->flag= 1;
454 while (index<me->totvert) {
455 (me->dvert+index)->flag= 0;
460 copy_wpaint_prev(wp, NULL, 0);
462 DAG_id_tag_update(&me->id, 0);
465 /* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator
467 void vpaint_dogamma(Scene *scene)
469 VPaint *vp= scene->toolsettings->vpaint;
474 unsigned char *cp, gamtab[256];
479 if(!(ob->mode & OB_MODE_VERTEX_PAINT)) return;
480 if(me==0 || me->mcol==0 || me->totface==0) return;
483 for(a=0; a<256; a++) {
485 fac= ((float)a)/255.0;
486 fac= vp->mul*pow( fac, igam);
490 if(temp<=0) gamtab[a]= 0;
491 else if(temp>=255) gamtab[a]= 255;
492 else gamtab[a]= temp;
496 cp= (unsigned char *)me->mcol;
499 cp[1]= gamtab[ cp[1] ];
500 cp[2]= gamtab[ cp[2] ];
501 cp[3]= gamtab[ cp[3] ];
508 static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
510 char *cp1, *cp2, *cp;
514 if(fac==0) return col1;
515 if(fac>=255) return col2;
524 cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
525 cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
526 cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
531 static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
533 char *cp1, *cp2, *cp;
537 if(fac==0) return col1;
544 temp= cp1[1] + ((fac*cp2[1])/255);
545 if(temp>254) cp[1]= 255; else cp[1]= temp;
546 temp= cp1[2] + ((fac*cp2[2])/255);
547 if(temp>254) cp[2]= 255; else cp[2]= temp;
548 temp= cp1[3] + ((fac*cp2[3])/255);
549 if(temp>254) cp[3]= 255; else cp[3]= temp;
554 static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
556 char *cp1, *cp2, *cp;
560 if(fac==0) return col1;
567 temp= cp1[1] - ((fac*cp2[1])/255);
568 if(temp<0) cp[1]= 0; else cp[1]= temp;
569 temp= cp1[2] - ((fac*cp2[2])/255);
570 if(temp<0) cp[2]= 0; else cp[2]= temp;
571 temp= cp1[3] - ((fac*cp2[3])/255);
572 if(temp<0) cp[3]= 0; else cp[3]= temp;
577 static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
579 char *cp1, *cp2, *cp;
583 if(fac==0) return col1;
591 /* first mul, then blend the fac */
593 cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255;
594 cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255;
595 cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255;
601 static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
603 char *cp1, *cp2, *cp;
607 if(fac==0) return col1;
608 if(fac>=255) return col2;
616 /* See if are lighter, if so mix, else dont do anything.
617 if the paint col is darker then the original, then ignore */
618 if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
622 cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
623 cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
624 cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
629 static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
631 char *cp1, *cp2, *cp;
635 if(fac==0) return col1;
636 if(fac>=255) return col2;
644 /* See if were darker, if so mix, else dont do anything.
645 if the paint col is brighter then the original, then ignore */
646 if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
650 cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
651 cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
652 cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
656 static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
658 Brush *brush = paint_brush(&vp->paint);
660 if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
661 else if(brush->vertexpaint_tool==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
662 else if(brush->vertexpaint_tool==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
663 else if(brush->vertexpaint_tool==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
664 else if(brush->vertexpaint_tool==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
665 else if(brush->vertexpaint_tool==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
667 /* if no spray, clip color adding with colorig & orig alpha */
668 if((vp->flag & VP_SPRAY)==0) {
669 unsigned int testcol=0, a;
672 alpha= (int)(255.0f*brush_alpha(brush));
674 if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
675 else if(brush->vertexpaint_tool==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
676 else if(brush->vertexpaint_tool==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
677 else if(brush->vertexpaint_tool==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
678 else if(brush->vertexpaint_tool==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha);
679 else if(brush->vertexpaint_tool==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha);
682 ct= (char *)&testcol;
687 if( cp[a]<ct[a] ) cp[a]= ct[a];
688 else if( cp[a]>co[a] ) cp[a]= co[a];
691 if( cp[a]<co[a] ) cp[a]= co[a];
692 else if( cp[a]>ct[a] ) cp[a]= ct[a];
699 static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
704 /* brecht: disabled this because it obviously failes for
705 brushes with size > 64, why is this here? */
706 /*if(size>64.0) size= 64.0;*/
708 ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size);
710 unsigned int *rt= ibuf->rect;
712 memset(indexar, 0, sizeof(int)*(totface+1));
714 size= ibuf->x*ibuf->y;
718 index= WM_framebuffer_to_index(*rt);
719 if(index>0 && index<=totface)
726 for(a=1; a<=totface; a++) {
727 if(indexar[a]) indexar[tot++]= a;
736 static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, const float mval[2], float pressure)
738 Brush *brush = paint_brush(&vp->paint);
739 float fac, fac_2, size, dx, dy;
742 const int radius= brush_size(brush);
744 project_int_noclip(vc->ar, vert_nor, vertco);
745 dx= mval[0]-vertco[0];
746 dy= mval[1]-vertco[1];
748 if (brush_use_size_pressure(brush))
749 size = pressure * radius;
753 fac_2= dx*dx + dy*dy;
754 if(fac_2 > size*size) return 0.f;
757 alpha= brush_alpha(brush) * brush_curve_strength_clamp(brush, fac, size);
759 if (brush_use_alpha_pressure(brush))
762 if(vp->flag & VP_NORMALS) {
763 float *no= vert_nor+3;
766 fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
768 dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
769 dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
771 alpha*= fac/sqrtf(dx*dx + dy*dy + fac*fac);
779 static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval, int flip)
781 Brush *brush = paint_brush(&wp->paint);
782 int tool = brush->vertexpaint_tool;
784 if(dw==NULL || uw==NULL) return;
789 paintval = 1.f - paintval; break;
795 tool= VP_DARKEN; break;
797 tool= VP_LIGHTEN; break;
801 if(tool==VP_MIX || tool==VP_BLUR)
802 dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
803 else if(tool==VP_ADD)
804 dw->weight += paintval*alpha;
805 else if(tool==VP_SUB)
806 dw->weight -= paintval*alpha;
807 else if(tool==VP_MUL)
808 /* first mul, then blend the fac */
809 dw->weight = ((1.0f-alpha) + alpha*paintval)*dw->weight;
810 else if(tool==VP_LIGHTEN) {
811 if (dw->weight < paintval)
812 dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
813 } else if(tool==VP_DARKEN) {
814 if (dw->weight > paintval)
815 dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
817 CLAMP(dw->weight, 0.0f, 1.0f);
819 /* if no spray, clip result with orig weight & orig alpha */
820 if((wp->flag & VP_SPRAY)==0) {
823 alpha= brush_alpha(brush);
824 if(tool==VP_MIX || tool==VP_BLUR)
825 testw = paintval*alpha + uw->weight*(1.0f-alpha);
826 else if(tool==VP_ADD)
827 testw = uw->weight + paintval*alpha;
828 else if(tool==VP_SUB)
829 testw = uw->weight - paintval*alpha;
830 else if(tool==VP_MUL)
831 /* first mul, then blend the fac */
832 testw = ((1.0f-alpha) + alpha*paintval)*uw->weight;
833 else if(tool==VP_LIGHTEN) {
834 if (uw->weight < paintval)
835 testw = paintval*alpha + uw->weight*(1.0f-alpha);
838 } else if(tool==VP_DARKEN) {
839 if (uw->weight > paintval)
840 testw = paintval*alpha + uw->weight*(1.0f-alpha);
844 CLAMP(testw, 0.0f, 1.0f);
846 if( testw<uw->weight ) {
847 if(dw->weight < testw) dw->weight= testw;
848 else if(dw->weight > uw->weight) dw->weight= uw->weight;
851 if(dw->weight > testw) dw->weight= testw;
852 else if(dw->weight < uw->weight) dw->weight= uw->weight;
858 /* ----------------------------------------------------- */
861 /* sets wp->weight to the closest weight value to vertex */
862 /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
863 static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
869 view3d_set_viewcontext(C, &vc);
870 me= get_mesh(vc.obact);
872 if (me && me->dvert && vc.v3d && vc.rv3d) {
875 view3d_operator_needs_opengl(C);
877 index= view3d_sample_backbuf(&vc, event->mval[0], event->mval[1]);
879 if(index && index<=me->totface) {
880 DerivedMesh *dm= mesh_get_derived_final(vc.scene, vc.obact, CD_MASK_BAREMESH);
882 if(dm->getVertCo==NULL) {
883 BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
886 MFace *mf= ((MFace *)me->mface) + index-1;
887 const int vgroup= vc.obact->actdef - 1;
888 ToolSettings *ts= vc.scene->toolsettings;
892 float len_best= FLT_MAX;
894 mval_f[0]= (float)event->mval[0];
895 mval_f[1]= (float)event->mval[1];
899 float co[3], sco[3], len;
900 const int v_idx= (*(&mf->v1 + fidx));
901 dm->getVertCo(dm, v_idx, co);
902 project_float_noclip(vc.ar, co, sco);
903 len= len_squared_v2v2(mval_f, sco);
910 if(v_idx_best != -1) { /* should always be valid */
911 ts->vgroup_weight= defvert_find_weight(&me->dvert[v_idx_best], vgroup);
920 /* not really correct since the brush didnt change, but redraws the toolbar */
921 WM_main_add_notifier(NC_BRUSH|NA_EDITED, NULL); /* ts->wpaint->paint.brush */
923 return OPERATOR_FINISHED;
926 return OPERATOR_CANCELLED;
930 void PAINT_OT_weight_sample(wmOperatorType *ot)
933 ot->name= "Weight Paint Sample Weight";
934 ot->idname= "PAINT_OT_weight_sample";
937 ot->invoke= weight_sample_invoke;
938 ot->poll= weight_paint_mode_poll;
941 ot->flag= OPTYPE_UNDO;
944 /* samples cursor location, and gives menu with vertex groups to activate */
945 static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
948 wmWindow *win= CTX_wm_window(C);
949 if(win && win->eventstate) {
953 view3d_set_viewcontext(C, &vc);
954 me= get_mesh(vc.obact);
956 if (me && me->dvert && vc.v3d && vc.rv3d) {
959 view3d_operator_needs_opengl(C);
961 index= view3d_sample_backbuf(&vc, win->eventstate->x - vc.ar->winrct.xmin, win->eventstate->y - vc.ar->winrct.ymin);
963 if(index && index<=me->totface) {
964 const int totgroup= BLI_countlist(&vc.obact->defbase);
966 MFace *mf= ((MFace *)me->mface) + index-1;
967 int fidx= mf->v4 ? 3:2;
968 int *groups= MEM_callocN(totgroup*sizeof(int), "groups");
972 MDeformVert *dvert= me->dvert + (*(&mf->v1 + fidx));
973 int i= dvert->totweight;
975 for(dw= dvert->dw; i > 0; dw++, i--) {
976 groups[dw->def_nr]= TRUE;
985 EnumPropertyItem *item= NULL, item_tmp= {0};
989 for(dg= vc.obact->defbase.first; dg && i<totgroup; i++, dg= dg->next) {
991 item_tmp.identifier= item_tmp.name= dg->name;
993 RNA_enum_item_add(&item, &totitem, &item_tmp);
997 RNA_enum_item_end(&item, &totitem);
1009 return DummyRNA_NULL_items;
1012 static int weight_sample_group_exec(bContext *C, wmOperator *op)
1014 int type= RNA_enum_get(op->ptr, "group");
1016 view3d_set_viewcontext(C, &vc);
1018 vc.obact->actdef= type + 1;
1020 DAG_id_tag_update(&vc.obact->id, OB_RECALC_DATA);
1021 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, vc.obact);
1022 return OPERATOR_FINISHED;
1025 /* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active rather then its own operator */
1026 void PAINT_OT_weight_sample_group(wmOperatorType *ot)
1028 PropertyRNA *prop= NULL;
1031 ot->name= "Weight Paint Sample Group";
1032 ot->idname= "PAINT_OT_weight_sample_group";
1035 ot->exec= weight_sample_group_exec;
1036 ot->invoke= WM_menu_invoke;
1037 ot->poll= weight_paint_mode_poll;
1040 ot->flag= OPTYPE_UNDO;
1042 /* keyingset to use (dynamic enum) */
1043 prop= RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
1044 RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
1049 static void do_weight_paint_auto_normalize(MDeformVert *dvert,
1050 int paint_nr, char *map)
1052 // MDeformWeight *dw = dvert->dw;
1053 float sum=0.0f, fac=0.0f, paintw=0.0f;
1059 for (i=0; i<dvert->totweight; i++) {
1060 if (dvert->dw[i].def_nr == paint_nr)
1061 paintw = dvert->dw[i].weight;
1063 if (map[dvert->dw[i].def_nr]) {
1065 if (dvert->dw[i].def_nr != paint_nr)
1066 sum += dvert->dw[i].weight;
1070 if (!tot || sum <= (1.0f - paintw))
1073 fac = sum / (1.0f - paintw);
1074 fac = fac==0.0f ? 1.0f : 1.0f / fac;
1076 for (i=0; i<dvert->totweight; i++) {
1077 if (map[dvert->dw[i].def_nr]) {
1078 if (dvert->dw[i].def_nr != paint_nr)
1079 dvert->dw[i].weight *= fac;
1084 static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
1085 float alpha, float paintweight, int flip,
1086 int vgroup_mirror, char *validmap)
1089 MDeformWeight *dw, *uw;
1090 int vgroup= ob->actdef-1;
1092 if(wp->flag & VP_ONLYVGROUP) {
1093 dw= defvert_find_index(me->dvert+index, vgroup);
1094 uw= defvert_find_index(wp->wpaint_prev+index, vgroup);
1097 dw= defvert_verify_index(me->dvert+index, vgroup);
1098 uw= defvert_verify_index(wp->wpaint_prev+index, vgroup);
1100 if(dw==NULL || uw==NULL)
1103 wpaint_blend(wp, dw, uw, alpha, paintweight, flip);
1104 do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap);
1106 if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
1107 int j= mesh_get_x_mirror_vert(ob, index);
1109 /* copy, not paint again */
1110 if(vgroup_mirror != -1)
1111 uw= defvert_verify_index(me->dvert+j, vgroup_mirror);
1113 uw= defvert_verify_index(me->dvert+j, vgroup);
1115 uw->weight= dw->weight;
1117 do_weight_paint_auto_normalize(me->dvert+j, vgroup, validmap);
1123 /* *************** set wpaint operator ****************** */
1125 static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
1127 Object *ob= CTX_data_active_object(C);
1128 Scene *scene= CTX_data_scene(C);
1129 VPaint *wp= scene->toolsettings->wpaint;
1133 if(ob->id.lib || me==NULL) return OPERATOR_PASS_THROUGH;
1135 if(ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
1136 else ob->mode |= OB_MODE_WEIGHT_PAINT;
1139 /* Weightpaint works by overriding colors in mesh,
1140 * so need to make sure we recalc on enter and
1141 * exit (exit needs doing regardless because we
1144 DAG_id_tag_update(&me->id, 0);
1146 if(ob->mode & OB_MODE_WEIGHT_PAINT) {
1150 wp= scene->toolsettings->wpaint= new_vpaint(1);
1152 paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
1153 paint_cursor_start(C, weight_paint_poll);
1155 mesh_octree_table(ob, NULL, NULL, 's');
1157 /* verify if active weight group is also active bone */
1158 par= modifiers_isDeformedByArmature(ob);
1159 if(par && (par->mode & OB_MODE_POSE)) {
1160 bArmature *arm= par->data;
1163 ED_vgroup_select_by_name(ob, arm->act_bone->name);
1167 mesh_octree_table(NULL, NULL, NULL, 'e');
1168 mesh_mirrtopo_table(NULL, 'e');
1171 WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
1173 return OPERATOR_FINISHED;
1176 /* for switching to/from mode */
1177 static int paint_poll_test(bContext *C)
1179 if(CTX_data_edit_object(C))
1181 if(CTX_data_active_object(C)==NULL)
1186 void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
1190 ot->name= "Weight Paint Mode";
1191 ot->idname= "PAINT_OT_weight_paint_toggle";
1194 ot->exec= set_wpaint;
1195 ot->poll= paint_poll_test;
1198 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1202 /* ************ weight paint operator ********** */
1208 float *vertexcosnos;
1211 /*variables for auto normalize*/
1213 char *vgroup_validmap; /*stores if vgroups tie to deforming bones or not*/
1216 static char *wpaint_make_validmap(Object *ob)
1223 ArmatureModifierData *amd;
1224 GHash *gh = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "wpaint_make_validmap gh");
1227 /*add all names to a hash table*/
1228 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1229 BLI_ghash_insert(gh, dg->name, NULL);
1235 validmap = MEM_callocN(i, "wpaint valid map");
1237 /*now loop through the armature modifiers and identify deform bones*/
1238 for (md = ob->modifiers.first; md; md= !md->next && step1 ? (step1=0), modifiers_getVirtualModifierList(ob) : md->next) {
1239 if (!(md->mode & (eModifierMode_Realtime|eModifierMode_Virtual)))
1242 if (md->type == eModifierType_Armature)
1244 amd = (ArmatureModifierData*) md;
1246 if(amd->object && amd->object->pose) {
1247 pose = amd->object->pose;
1249 for (chan=pose->chanbase.first; chan; chan=chan->next) {
1250 if (chan->bone->flag & BONE_NO_DEFORM)
1253 if (BLI_ghash_haskey(gh, chan->name)) {
1254 BLI_ghash_remove(gh, chan->name, NULL, NULL);
1255 BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
1262 /*add all names to a hash table*/
1263 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
1264 if (BLI_ghash_lookup(gh, dg->name) != NULL) {
1269 BLI_ghash_free(gh, NULL, NULL);
1274 static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1276 Scene *scene= CTX_data_scene(C);
1277 struct PaintStroke *stroke = op->customdata;
1278 ToolSettings *ts= CTX_data_tool_settings(C);
1279 VPaint *wp= ts->wpaint;
1280 Object *ob= CTX_data_active_object(C);
1281 struct WPaintData *wpd;
1283 float mat[4][4], imat[4][4];
1285 if(scene->obedit) return OPERATOR_CANCELLED;
1288 if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
1290 /* if nothing was added yet, we make dverts and a vertex deform group */
1292 ED_vgroup_data_create(&me->id);
1293 WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
1296 /* make mode data storage */
1297 wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
1298 paint_stroke_set_mode_data(stroke, wpd);
1299 view3d_set_viewcontext(C, &wpd->vc);
1300 wpd->vgroup_mirror= -1;
1302 /*set up auto-normalize, and generate map for detecting which
1303 vgroups affect deform bones*/
1304 wpd->auto_normalize = ts->auto_normalize;
1305 if (wpd->auto_normalize)
1306 wpd->vgroup_validmap = wpaint_make_validmap(ob);
1308 // if(qual & LR_CTRLKEY) {
1309 // sample_wpaint(scene, ar, v3d, 0);
1312 // if(qual & LR_SHIFTKEY) {
1313 // sample_wpaint(scene, ar, v3d, 1);
1317 /* ALLOCATIONS! no return after this line */
1318 /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1319 wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
1320 wpd->indexar= get_indexarray(me);
1321 copy_wpaint_prev(wp, me->dvert, me->totvert);
1323 /* this happens on a Bone select, when no vgroup existed yet */
1326 if((modob = modifiers_isDeformedByArmature(ob))) {
1327 Bone *actbone= ((bArmature *)modob->data)->act_bone;
1329 bPoseChannel *pchan= get_pose_channel(modob->pose, actbone->name);
1332 bDeformGroup *dg= defgroup_find_name(ob, pchan->name);
1334 dg= ED_vgroup_add_name(ob, pchan->name); /* sets actdef */
1336 ob->actdef= 1 + defgroup_find_index(ob, dg);
1341 if(ob->defbase.first==NULL) {
1345 // if(ob->lay & v3d->lay); else error("Active object is not in this layer");
1347 /* imat for normals */
1348 mul_m4_m4m4(mat, ob->obmat, wpd->vc.rv3d->viewmat);
1349 invert_m4_m4(imat, mat);
1350 copy_m3_m4(wpd->wpimat, imat);
1352 /* if mirror painting, find the other group */
1353 if(me->editflag & ME_EDIT_MIRROR_X) {
1354 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
1356 bDeformGroup *curdef;
1360 flip_side_name(name, defgroup->name, FALSE);
1362 for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
1363 if (!strcmp(curdef->name, name))
1366 int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
1367 curdef= ED_vgroup_add_name (ob, name);
1371 if(curdef && curdef!=defgroup)
1372 wpd->vgroup_mirror= actdef;
1379 static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
1381 ToolSettings *ts= CTX_data_tool_settings(C);
1382 VPaint *wp= ts->wpaint;
1383 Brush *brush = paint_brush(&wp->paint);
1384 struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1391 int totindex, index, totw, flip;
1393 float mval[2], pressure;
1395 /* cannot paint if there is no stroke data */
1397 // XXX: force a redraw here, since even though we can't paint,
1398 // at least view won't freeze until stroke ends
1399 ED_region_tag_redraw(CTX_wm_region(C));
1406 indexar= wpd->indexar;
1408 view3d_operator_needs_opengl(C);
1410 /* load projection matrix */
1411 mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
1413 flip = RNA_boolean_get(itemptr, "pen_flip");
1414 pressure = RNA_float_get(itemptr, "pressure");
1415 RNA_float_get_array(itemptr, "mouse", mval);
1416 mval[0]-= vc->ar->winrct.xmin;
1417 mval[1]-= vc->ar->winrct.ymin;
1419 swap_m4m4(wpd->vc.rv3d->persmat, mat);
1421 /* which faces are involved */
1422 if(wp->flag & VP_AREA) {
1423 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
1426 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
1427 if(indexar[0]) totindex= 1;
1431 if(wp->flag & VP_COLINDEX) {
1432 for(index=0; index<totindex; index++) {
1433 if(indexar[index] && indexar[index]<=me->totface) {
1434 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1436 if(mface->mat_nr!=ob->actcol-1) {
1443 if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
1444 for(index=0; index<totindex; index++) {
1445 if(indexar[index] && indexar[index]<=me->totface) {
1446 MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
1448 if((mface->flag & ME_FACE_SEL)==0) {
1455 /* make sure each vertex gets treated only once */
1456 /* and calculate filter weight */
1458 if(brush->vertexpaint_tool==VP_BLUR)
1461 paintweight= ts->vgroup_weight;
1463 for(index=0; index<totindex; index++) {
1464 if(indexar[index] && indexar[index]<=me->totface) {
1465 MFace *mface= me->mface + (indexar[index]-1);
1467 (me->dvert+mface->v1)->flag= 1;
1468 (me->dvert+mface->v2)->flag= 1;
1469 (me->dvert+mface->v3)->flag= 1;
1470 if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1472 if(brush->vertexpaint_tool==VP_BLUR) {
1473 MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
1475 if(wp->flag & VP_ONLYVGROUP)
1476 dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
1478 dw_func= defvert_verify_index;
1480 dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
1481 if(dw) {paintweight+= dw->weight; totw++;}
1482 dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
1483 if(dw) {paintweight+= dw->weight; totw++;}
1484 dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
1485 if(dw) {paintweight+= dw->weight; totw++;}
1487 dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
1488 if(dw) {paintweight+= dw->weight; totw++;}
1494 if(brush->vertexpaint_tool==VP_BLUR)
1495 paintweight/= (float)totw;
1497 for(index=0; index<totindex; index++) {
1499 if(indexar[index] && indexar[index]<=me->totface) {
1500 MFace *mface= me->mface + (indexar[index]-1);
1502 if((me->dvert+mface->v1)->flag) {
1503 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval, pressure);
1505 do_weight_paint_vertex(wp, ob, mface->v1,
1506 alpha, paintweight, flip, wpd->vgroup_mirror,
1507 wpd->vgroup_validmap);
1509 (me->dvert+mface->v1)->flag= 0;
1512 if((me->dvert+mface->v2)->flag) {
1513 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval, pressure);
1515 do_weight_paint_vertex(wp, ob, mface->v2,
1516 alpha, paintweight, flip, wpd->vgroup_mirror,
1517 wpd->vgroup_validmap);
1519 (me->dvert+mface->v2)->flag= 0;
1522 if((me->dvert+mface->v3)->flag) {
1523 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval, pressure);
1525 do_weight_paint_vertex(wp, ob, mface->v3,
1526 alpha, paintweight, flip, wpd->vgroup_mirror,
1527 wpd->vgroup_validmap);
1529 (me->dvert+mface->v3)->flag= 0;
1532 if((me->dvert+mface->v4)->flag) {
1534 alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval, pressure);
1536 do_weight_paint_vertex(wp, ob, mface->v4,
1537 alpha, paintweight, flip, wpd->vgroup_mirror,
1538 wpd->vgroup_validmap);
1540 (me->dvert+mface->v4)->flag= 0;
1546 swap_m4m4(vc->rv3d->persmat, mat);
1548 DAG_id_tag_update(ob->data, 0);
1549 ED_region_tag_redraw(vc->ar);
1552 static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
1554 ToolSettings *ts= CTX_data_tool_settings(C);
1555 Object *ob= CTX_data_active_object(C);
1556 struct WPaintData *wpd= paint_stroke_mode_data(stroke);
1559 if(wpd->vertexcosnos)
1560 MEM_freeN(wpd->vertexcosnos);
1561 MEM_freeN(wpd->indexar);
1563 if (wpd->vgroup_validmap)
1564 MEM_freeN(wpd->vgroup_validmap);
1569 /* frees prev buffer */
1570 copy_wpaint_prev(ts->wpaint, NULL, 0);
1572 /* and particles too */
1573 if(ob->particlesystem.first) {
1574 ParticleSystem *psys;
1577 for(psys= ob->particlesystem.first; psys; psys= psys->next) {
1578 for(i=0; i<PSYS_TOT_VG; i++) {
1579 if(psys->vgroup[i]==ob->actdef) {
1580 psys->recalc |= PSYS_RECALC_RESET;
1587 DAG_id_tag_update(ob->data, 0);
1591 static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
1594 op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
1595 wpaint_stroke_update_step,
1596 wpaint_stroke_done, event->type);
1598 /* add modal handler */
1599 WM_event_add_modal_handler(C, op);
1601 op->type->modal(C, op, event);
1603 return OPERATOR_RUNNING_MODAL;
1606 void PAINT_OT_weight_paint(wmOperatorType *ot)
1610 ot->name= "Weight Paint";
1611 ot->idname= "PAINT_OT_weight_paint";
1614 ot->invoke= wpaint_invoke;
1615 ot->modal= paint_stroke_modal;
1616 /* ot->exec= vpaint_exec; <-- needs stroke property */
1617 ot->poll= weight_paint_poll;
1620 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
1622 RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1625 static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
1627 struct Scene *scene= CTX_data_scene(C);
1628 Object *obact = CTX_data_active_object(C);
1630 wpaint_fill(scene->toolsettings->wpaint, obact, scene->toolsettings->vgroup_weight);
1631 ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
1632 return OPERATOR_FINISHED;
1635 void PAINT_OT_weight_set(wmOperatorType *ot)
1638 ot->name= "Set Weight";
1639 ot->idname= "PAINT_OT_weight_set";
1642 ot->exec= weight_paint_set_exec;
1643 ot->poll= facemask_paint_poll;
1646 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1649 /* ************ set / clear vertex paint mode ********** */
1652 static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
1654 Object *ob= CTX_data_active_object(C);
1655 Scene *scene= CTX_data_scene(C);
1656 VPaint *vp= scene->toolsettings->vpaint;
1661 if(me==NULL || object_data_is_libdata(ob)) {
1662 ob->mode &= ~OB_MODE_VERTEX_PAINT;
1663 return OPERATOR_PASS_THROUGH;
1666 if(me && me->mcol==NULL) make_vertexcol(ob);
1668 /* toggle: end vpaint */
1669 if(ob->mode & OB_MODE_VERTEX_PAINT) {
1671 ob->mode &= ~OB_MODE_VERTEX_PAINT;
1674 ob->mode |= OB_MODE_VERTEX_PAINT;
1675 /* Turn off weight painting */
1676 if (ob->mode & OB_MODE_WEIGHT_PAINT)
1680 vp= scene->toolsettings->vpaint= new_vpaint(0);
1682 paint_cursor_start(C, vertex_paint_poll);
1684 paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
1688 /* update modifier stack for mapping requirements */
1689 DAG_id_tag_update(&me->id, 0);
1691 WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
1693 return OPERATOR_FINISHED;
1696 void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
1700 ot->name= "Vertex Paint Mode";
1701 ot->idname= "PAINT_OT_vertex_paint_toggle";
1704 ot->exec= set_vpaint;
1705 ot->poll= paint_poll_test;
1708 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1713 /* ********************** vertex paint operator ******************* */
1715 /* Implementation notes:
1718 - validate context (add mcol)
1719 - create customdata storage
1720 - call paint once (mouse click)
1724 - for every mousemove, apply vertex paint
1725 - exit on mouse release, free customdata
1726 (return OPERATOR_FINISHED also removes handler and operator)
1729 - implement a stroke event (or mousemove with past positons)
1730 - revise whether op->customdata should be added in object, in set_vpaint
1734 typedef struct VPaintData {
1736 unsigned int paintcol;
1738 float *vertexcosnos;
1742 static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
1744 ToolSettings *ts= CTX_data_tool_settings(C);
1745 struct PaintStroke *stroke = op->customdata;
1746 VPaint *vp= ts->vpaint;
1747 struct VPaintData *vpd;
1748 Object *ob= CTX_data_active_object(C);
1750 float mat[4][4], imat[4][4];
1752 /* context checks could be a poll() */
1754 if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
1756 if(me->mcol==NULL) make_vertexcol(ob);
1757 if(me->mcol==NULL) return OPERATOR_CANCELLED;
1759 /* make mode data storage */
1760 vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
1761 paint_stroke_set_mode_data(stroke, vpd);
1762 view3d_set_viewcontext(C, &vpd->vc);
1764 vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
1765 vpd->indexar= get_indexarray(me);
1766 vpd->paintcol= vpaint_get_current_col(vp);
1769 copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
1771 /* some old cruft to sort out later */
1772 mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
1773 invert_m4_m4(imat, mat);
1774 copy_m3_m4(vpd->vpimat, imat);
1779 static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
1781 ViewContext *vc = &vpd->vc;
1782 Brush *brush = paint_brush(&vp->paint);
1783 Mesh *me = get_mesh(ob);
1784 MFace *mface= ((MFace*)me->mface) + index;
1785 unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
1786 unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
1790 if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
1791 ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
1794 if(brush->vertexpaint_tool==VP_BLUR) {
1795 unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
1797 unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
1798 vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
1801 vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
1806 for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
1807 alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval, pressure);
1809 vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
1813 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
1815 ToolSettings *ts= CTX_data_tool_settings(C);
1816 struct VPaintData *vpd = paint_stroke_mode_data(stroke);
1817 VPaint *vp= ts->vpaint;
1818 Brush *brush = paint_brush(&vp->paint);
1819 ViewContext *vc= &vpd->vc;
1820 Object *ob= vc->obact;
1823 int *indexar= vpd->indexar;
1824 int totindex, index, flip;
1825 float pressure, mval[2];
1827 RNA_float_get_array(itemptr, "mouse", mval);
1828 flip = RNA_boolean_get(itemptr, "pen_flip");
1829 pressure = RNA_float_get(itemptr, "pressure");
1831 view3d_operator_needs_opengl(C);
1833 /* load projection matrix */
1834 mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
1836 mval[0]-= vc->ar->winrct.xmin;
1837 mval[1]-= vc->ar->winrct.ymin;
1840 /* which faces are involved */
1841 if(vp->flag & VP_AREA) {
1842 totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
1845 indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
1846 if(indexar[0]) totindex= 1;
1850 swap_m4m4(vc->rv3d->persmat, mat);
1852 for(index=0; index<totindex; index++) {
1853 if(indexar[index] && indexar[index]<=me->totface)
1854 vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
1857 swap_m4m4(vc->rv3d->persmat, mat);
1859 /* was disabled because it is slow, but necessary for blur */
1860 if(brush->vertexpaint_tool == VP_BLUR)
1861 do_shared_vertexcol(me);
1863 ED_region_tag_redraw(vc->ar);
1865 DAG_id_tag_update(ob->data, 0);
1868 static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
1870 ToolSettings *ts= CTX_data_tool_settings(C);
1871 struct VPaintData *vpd= paint_stroke_mode_data(stroke);
1873 if(vpd->vertexcosnos)
1874 MEM_freeN(vpd->vertexcosnos);
1875 MEM_freeN(vpd->indexar);
1877 /* frees prev buffer */
1878 copy_vpaint_prev(ts->vpaint, NULL, 0);
1883 static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
1886 op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
1887 vpaint_stroke_update_step,
1888 vpaint_stroke_done, event->type);
1890 /* add modal handler */
1891 WM_event_add_modal_handler(C, op);
1893 op->type->modal(C, op, event);
1895 return OPERATOR_RUNNING_MODAL;
1898 void PAINT_OT_vertex_paint(wmOperatorType *ot)
1901 ot->name= "Vertex Paint";
1902 ot->idname= "PAINT_OT_vertex_paint";
1905 ot->invoke= vpaint_invoke;
1906 ot->modal= paint_stroke_modal;
1907 /* ot->exec= vpaint_exec; <-- needs stroke property */
1908 ot->poll= vertex_paint_poll;
1911 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
1913 RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
1916 /* ********************** weight from bones operator ******************* */
1918 static int weight_from_bones_poll(bContext *C)
1920 Object *ob= CTX_data_active_object(C);
1922 return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob));
1925 static int weight_from_bones_exec(bContext *C, wmOperator *op)
1927 Scene *scene= CTX_data_scene(C);
1928 Object *ob= CTX_data_active_object(C);
1929 Object *armob= modifiers_isDeformedByArmature(ob);
1931 int type= RNA_enum_get(op->ptr, "type");
1933 create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
1935 DAG_id_tag_update(&me->id, 0);
1936 WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
1938 return OPERATOR_FINISHED;
1941 void PAINT_OT_weight_from_bones(wmOperatorType *ot)
1943 static EnumPropertyItem type_items[]= {
1944 {ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights froms bones"},
1945 {ARM_GROUPS_ENVELOPE, "ENVELOPES", 0, "From Envelopes", "Weights from envelopes with user defined radius"},
1946 {0, NULL, 0, NULL, NULL}};
1949 ot->name= "Weight from Bones";
1950 ot->idname= "PAINT_OT_weight_from_bones";
1953 ot->exec= weight_from_bones_exec;
1954 ot->invoke= WM_menu_invoke;
1955 ot->poll= weight_from_bones_poll;
1958 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1961 ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights.");