diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.c | 867 |
1 files changed, 483 insertions, 384 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 25ff57ca87f..1a548708ec8 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -43,7 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" - +#include "MTC_matrixops.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" @@ -62,7 +62,6 @@ #include "DNA_userdef_types.h" #include "RNA_access.h" -#include "RNA_define.h" #include "BKE_armature.h" #include "BKE_brush.h" @@ -92,8 +91,6 @@ #include "ED_util.h" #include "ED_view3d.h" -#include "paint_intern.h" - /* vp->mode */ #define VP_MIX 0 #define VP_ADD 1 @@ -110,18 +107,11 @@ static void error() {} /* polling - retrieve whether cursor should be set or operator should be done */ - -/* Returns true if vertex paint mode is active */ -int vertex_paint_mode_poll(bContext *C) +static int vp_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - return ob && ob->mode == OB_MODE_VERTEX_PAINT; -} - -static int vp_poll(bContext *C) -{ - if(vertex_paint_mode_poll(C) && + if(ob && ob->mode & OB_MODE_VERTEX_PAINT && paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) { ScrArea *sa= CTX_wm_area(C); if(sa->spacetype==SPACE_VIEW3D) { @@ -149,6 +139,56 @@ static int wp_poll(bContext *C) return 0; } + +/* Cursors */ +static void vp_drawcursor(bContext *C, int x, int y, void *customdata) +{ + Brush *brush = paint_brush(&CTX_data_tool_settings(C)->vpaint->paint); + + glTranslatef((float)x, (float)y, 0.0f); + + glColor4ub(255, 255, 255, 128); + glEnable( GL_LINE_SMOOTH ); + glEnable(GL_BLEND); + glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40); + glDisable(GL_BLEND); + glDisable( GL_LINE_SMOOTH ); + + glTranslatef((float)-x, (float)-y, 0.0f); +} + +static void wp_drawcursor(bContext *C, int x, int y, void *customdata) +{ + Brush *brush = paint_brush(&CTX_data_tool_settings(C)->wpaint->paint); + + glTranslatef((float)x, (float)y, 0.0f); + + glColor4ub(200, 200, 255, 128); + glEnable( GL_LINE_SMOOTH ); + glEnable(GL_BLEND); + glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40); + glDisable(GL_BLEND); + glDisable( GL_LINE_SMOOTH ); + + glTranslatef((float)-x, (float)-y, 0.0f); +} + +static void toggle_paint_cursor(bContext *C, int wpaint) +{ + ToolSettings *ts = CTX_data_scene(C)->toolsettings; + VPaint *vp = wpaint ? ts->wpaint : ts->vpaint; + + if(vp->paintcursor) { + WM_paint_cursor_end(CTX_wm_manager(C), vp->paintcursor); + vp->paintcursor = NULL; + } + else { + vp->paintcursor = wpaint ? + WM_paint_cursor_activate(CTX_wm_manager(C), wp_poll, wp_drawcursor, NULL) : + WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor, NULL); + } +} + static VPaint *new_vpaint(int wpaint) { VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint"); @@ -295,7 +335,7 @@ void make_vertexcol(Scene *scene, int shade) /* single ob */ else memset(me->mcol, 255, 4*sizeof(MCol)*me->totface); - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } @@ -330,7 +370,34 @@ static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount) } -void clear_vpaint(Scene *scene, int selected) +void clear_vpaint(Scene *scene) +{ + Mesh *me; + Object *ob; + unsigned int *to, paintcol; + int a; + + ob= OBACT; + me= get_mesh(ob); + if(!ob || ob->id.lib) return; + + if(!(ob->mode & OB_MODE_VERTEX_PAINT)) return; + + if(me==0 || me->mcol==0 || me->totface==0) return; + + paintcol= vpaint_get_current_col(scene->toolsettings->vpaint); + + to= (unsigned int *)me->mcol; + a= 4*me->totface; + while(a--) { + *to= paintcol; + to++; + } + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + +} + +void clear_vpaint_selectedfaces(Scene *scene) { Mesh *me; MFace *mf; @@ -350,7 +417,7 @@ void clear_vpaint(Scene *scene, int selected) mf = me->mface; mcol = (unsigned int*)me->mcol; for (i = 0; i < me->totface; i++, mf++, mcol+=4) { - if (!selected || mf->flag & ME_FACE_SEL) { + if (mf->flag & ME_FACE_SEL) { mcol[0] = paintcol; mcol[1] = paintcol; mcol[2] = paintcol; @@ -358,7 +425,7 @@ void clear_vpaint(Scene *scene, int selected) } } - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } @@ -408,8 +475,8 @@ void clear_wpaint_selectedfaces(Scene *scene) if (!strcmp(curdef->name, name)) break; if(curdef==NULL) { - int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */ - curdef= ED_vgroup_add_name (ob, name); + int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ + curdef= add_defgroup_name (ob, name); ob->actdef= olddef; } @@ -431,9 +498,9 @@ void clear_wpaint_selectedfaces(Scene *scene) faceverts[3]= mface->v4; for (i=0; i<3 || faceverts[i]; i++) { if(!((me->dvert+faceverts[i])->flag)) { - dw= ED_vgroup_weight_verify(me->dvert+faceverts[i], vgroup); + dw= verify_defweight(me->dvert+faceverts[i], vgroup); if(dw) { - uw= ED_vgroup_weight_verify(wp->wpaint_prev+faceverts[i], vgroup); + uw= verify_defweight(wp->wpaint_prev+faceverts[i], vgroup); uw->weight= dw->weight; /* set the undo weight */ dw->weight= paintweight; @@ -442,11 +509,11 @@ void clear_wpaint_selectedfaces(Scene *scene) if(j>=0) { /* copy, not paint again */ if(vgroup_mirror != -1) { - dw= ED_vgroup_weight_verify(me->dvert+j, vgroup_mirror); - uw= ED_vgroup_weight_verify(wp->wpaint_prev+j, vgroup_mirror); + dw= verify_defweight(me->dvert+j, vgroup_mirror); + uw= verify_defweight(wp->wpaint_prev+j, vgroup_mirror); } else { - dw= ED_vgroup_weight_verify(me->dvert+j, vgroup); - uw= ED_vgroup_weight_verify(wp->wpaint_prev+j, vgroup); + dw= verify_defweight(me->dvert+j, vgroup); + uw= verify_defweight(wp->wpaint_prev+j, vgroup); } uw->weight= dw->weight; /* set the undo weight */ dw->weight= paintweight; @@ -468,7 +535,7 @@ void clear_wpaint_selectedfaces(Scene *scene) MEM_freeN(indexar); copy_wpaint_prev(wp, NULL, 0); - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } @@ -740,7 +807,7 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x return tot; } -static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, float *mval) +static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, short *mval) { Brush *brush = paint_brush(&vp->paint); float fac, dx, dy; @@ -923,7 +990,7 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) val= 0; // XXX pupmenu(str); if(val>=0) { ob->actdef= val+1; - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } MEM_freeN(str); } @@ -963,20 +1030,20 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) fac= MIN4(w1, w2, w3, w4); if(w1==fac) { - dw= ED_vgroup_weight_get(me->dvert+mface->v1, ob->actdef-1); + dw= get_defweight(me->dvert+mface->v1, ob->actdef-1); if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; } else if(w2==fac) { - dw= ED_vgroup_weight_get(me->dvert+mface->v2, ob->actdef-1); + dw= get_defweight(me->dvert+mface->v2, ob->actdef-1); if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; } else if(w3==fac) { - dw= ED_vgroup_weight_get(me->dvert+mface->v3, ob->actdef-1); + dw= get_defweight(me->dvert+mface->v3, ob->actdef-1); if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; } else if(w4==fac) { if(mface->v4) { - dw= ED_vgroup_weight_get(me->dvert+mface->v4, ob->actdef-1); + dw= get_defweight(me->dvert+mface->v4, ob->actdef-1); if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f; } } @@ -995,12 +1062,12 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, int vgroup= ob->actdef-1; if(wp->flag & VP_ONLYVGROUP) { - dw= ED_vgroup_weight_get(me->dvert+index, vgroup); - uw= ED_vgroup_weight_get(wp->wpaint_prev+index, vgroup); + dw= get_defweight(me->dvert+index, vgroup); + uw= get_defweight(wp->wpaint_prev+index, vgroup); } else { - dw= ED_vgroup_weight_verify(me->dvert+index, vgroup); - uw= ED_vgroup_weight_verify(wp->wpaint_prev+index, vgroup); + dw= verify_defweight(me->dvert+index, vgroup); + uw= verify_defweight(wp->wpaint_prev+index, vgroup); } if(dw==NULL || uw==NULL) return; @@ -1012,9 +1079,9 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, if(j>=0) { /* copy, not paint again */ if(vgroup_mirror != -1) - uw= ED_vgroup_weight_verify(me->dvert+j, vgroup_mirror); + uw= verify_defweight(me->dvert+j, vgroup_mirror); else - uw= ED_vgroup_weight_verify(me->dvert+j, vgroup); + uw= verify_defweight(me->dvert+j, vgroup); uw->weight= dw->weight; } @@ -1049,7 +1116,7 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ * exit (exit needs doing regardless because we * should redeform). */ - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); if(ob->mode & OB_MODE_WEIGHT_PAINT) { Object *par; @@ -1057,8 +1124,9 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ if(wp==NULL) wp= scene->toolsettings->wpaint= new_vpaint(1); - paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT); - paint_cursor_start(C, wp_poll); + paint_init(&wp->paint, "Brush"); + + toggle_paint_cursor(C, 1); mesh_octree_table(ob, NULL, NULL, 's'); @@ -1070,10 +1138,13 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ if(pchan->bone->flag & BONE_ACTIVE) break; if(pchan) - ED_vgroup_select_by_name(ob, pchan->name); + vertexgroup_select_by_name(ob, pchan->name); } } else { + if(wp) + toggle_paint_cursor(C, 1); + mesh_octree_table(ob, NULL, NULL, 'e'); } @@ -1114,11 +1185,9 @@ void PAINT_OT_weight_paint_toggle(wmOperatorType *ot) static int vpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) { - Paint *p = paint_get_active(CTX_data_scene(C)); - Brush *brush = paint_brush(p); - - WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor); - p->paint_cursor = NULL; + Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->vpaint->paint); + + toggle_paint_cursor(C, 0); brush_radial_control_invoke(op, brush, 1); return WM_radial_control_invoke(C, op, event); } @@ -1127,7 +1196,7 @@ static int vpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve { int ret = WM_radial_control_modal(C, op, event); if(ret != OPERATOR_RUNNING_MODAL) - paint_cursor_start(C, vp_poll); + toggle_paint_cursor(C, 0); return ret; } @@ -1139,11 +1208,8 @@ static int vpaint_radial_control_exec(bContext *C, wmOperator *op) static int wpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) { - Paint *p = paint_get_active(CTX_data_scene(C)); - Brush *brush = paint_brush(p); - - WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor); - p->paint_cursor = NULL; + Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->wpaint->paint); + toggle_paint_cursor(C, 1); brush_radial_control_invoke(op, brush, 1); return WM_radial_control_invoke(C, op, event); } @@ -1152,7 +1218,7 @@ static int wpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve { int ret = WM_radial_control_modal(C, op, event); if(ret != OPERATOR_RUNNING_MODAL) - paint_cursor_start(C, wp_poll); + toggle_paint_cursor(C, 1); return ret; } @@ -1204,10 +1270,207 @@ struct WPaintData { float wpimat[3][3]; }; -static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) +static void wpaint_exit(bContext *C, wmOperator *op) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + Object *ob= CTX_data_active_object(C); + struct WPaintData *wpd= op->customdata; + + if(wpd->vertexcosnos) + MEM_freeN(wpd->vertexcosnos); + MEM_freeN(wpd->indexar); + + /* frees prev buffer */ + copy_wpaint_prev(ts->wpaint, NULL, 0); + + /* and particles too */ + if(ob->particlesystem.first) { + ParticleSystem *psys; + int i; + + for(psys= ob->particlesystem.first; psys; psys= psys->next) { + for(i=0; i<PSYS_TOT_VG; i++) { + if(psys->vgroup[i]==ob->actdef) { + psys->recalc |= PSYS_RECALC_RESET; + break; + } + } + } + } + + DAG_object_flush_update(CTX_data_scene(C), ob, OB_RECALC_DATA); + + MEM_freeN(wpd); + op->customdata= NULL; +} + + +static int wpaint_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *wp= ts->wpaint; + Brush *brush = paint_brush(&wp->paint); + + switch(event->type) { + case LEFTMOUSE: + if(event->val==0) { /* release */ + wpaint_exit(C, op); + return OPERATOR_FINISHED; + } + /* pass on, first press gets painted too */ + + case MOUSEMOVE: + { + struct WPaintData *wpd= op->customdata; + ViewContext *vc= &wpd->vc; + Object *ob= vc->obact; + Mesh *me= ob->data; + float mat[4][4]; + float paintweight= ts->vgroup_weight; + int *indexar= wpd->indexar; + int totindex, index, alpha, totw; + short mval[2]; + + view3d_operator_needs_opengl(C); + + /* load projection matrix */ + wmMultMatrix(ob->obmat); + wmGetSingleMatrix(mat); + wmLoadMatrix(wpd->vc.rv3d->viewmat); + + MTC_Mat4SwapMat4(wpd->vc.rv3d->persmat, mat); + + mval[0]= event->x - vc->ar->winrct.xmin; + mval[1]= event->y - vc->ar->winrct.ymin; + + /* which faces are involved */ + if(wp->flag & VP_AREA) { + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size); + } + else { + indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + if(wp->flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + + if((G.f & G_FACESELECT) && me->mface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if((mface->flag & ME_FACE_SEL)==0) { + indexar[index]= 0; + } + } + } + } + + /* make sure each vertex gets treated only once */ + /* and calculate filter weight */ + totw= 0; + if(wp->mode==VP_BLUR) + paintweight= 0.0f; + else + paintweight= ts->vgroup_weight; + + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= me->mface + (indexar[index]-1); + + (me->dvert+mface->v1)->flag= 1; + (me->dvert+mface->v2)->flag= 1; + (me->dvert+mface->v3)->flag= 1; + if(mface->v4) (me->dvert+mface->v4)->flag= 1; + + if(wp->mode==VP_BLUR) { + MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight; + + if(wp->flag & VP_ONLYVGROUP) + dw_func= get_defweight; + + dw= dw_func(me->dvert+mface->v1, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + dw= dw_func(me->dvert+mface->v2, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + dw= dw_func(me->dvert+mface->v3, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + if(mface->v4) { + dw= dw_func(me->dvert+mface->v4, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + } + } + } + } + + if(wp->mode==VP_BLUR) + paintweight/= (float)totw; + + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= me->mface + (indexar[index]-1); + + if((me->dvert+mface->v1)->flag) { + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval); + if(alpha) { + do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror); + } + (me->dvert+mface->v1)->flag= 0; + } + + if((me->dvert+mface->v2)->flag) { + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval); + if(alpha) { + do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror); + } + (me->dvert+mface->v2)->flag= 0; + } + + if((me->dvert+mface->v3)->flag) { + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval); + if(alpha) { + do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror); + } + (me->dvert+mface->v3)->flag= 0; + } + + if((me->dvert+mface->v4)->flag) { + if(mface->v4) { + alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval); + if(alpha) { + do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror); + } + (me->dvert+mface->v4)->flag= 0; + } + } + } + } + + MTC_Mat4SwapMat4(vc->rv3d->persmat, mat); + + DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA); + ED_region_tag_redraw(vc->ar); + } + } + + return OPERATOR_RUNNING_MODAL; +} + +static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) { Scene *scene= CTX_data_scene(C); - struct PaintStroke *stroke = op->customdata; ToolSettings *ts= CTX_data_tool_settings(C); VPaint *wp= ts->wpaint; Object *ob= CTX_data_active_object(C); @@ -1216,17 +1479,17 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) float mat[4][4], imat[4][4]; if(scene->obedit) return OPERATOR_CANCELLED; + // XXX if(multires_level1_test()) return; me= get_mesh(ob); if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH; /* if nothing was added yet, we make dverts and a vertex deform group */ if (!me->dvert) - ED_vgroup_data_create(&me->id); + create_dverts(&me->id); - /* make mode data storage */ - wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData"); - paint_stroke_set_mode_data(stroke, wpd); + /* make customdata storage */ + op->customdata= wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData"); view3d_set_viewcontext(C, &wpd->vc); wpd->vgroup_mirror= -1; @@ -1256,14 +1519,14 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) if(pchan) { bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name); if(dg==NULL) - dg= ED_vgroup_add_name(ob, pchan->name); /* sets actdef */ + dg= add_defgroup_name(ob, pchan->name); /* sets actdef */ else ob->actdef= get_defgroup_num(ob, dg); } } } if(ob->defbase.first==NULL) { - ED_vgroup_add(ob); + add_defgroup(ob); } // if(ob->lay & v3d->lay); else error("Active object is not in this layer"); @@ -1288,8 +1551,8 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) if (!strcmp(curdef->name, name)) break; if(curdef==NULL) { - int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */ - curdef= ED_vgroup_add_name (ob, name); + int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ + curdef= add_defgroup_name (ob, name); ob->actdef= olddef; } @@ -1298,203 +1561,11 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) } } - return 1; -} - -static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - VPaint *wp= ts->wpaint; - Brush *brush = paint_brush(&wp->paint); - struct WPaintData *wpd= paint_stroke_mode_data(stroke); - ViewContext *vc= &wpd->vc; - Object *ob= vc->obact; - Mesh *me= ob->data; - float mat[4][4]; - float paintweight= ts->vgroup_weight; - int *indexar= wpd->indexar; - int totindex, index, alpha, totw; - float mval[2]; - - view3d_operator_needs_opengl(C); - - /* load projection matrix */ - wmMultMatrix(ob->obmat); - wmGetSingleMatrix(mat); - wmLoadMatrix(wpd->vc.rv3d->viewmat); - - RNA_float_get_array(itemptr, "mouse", mval); - mval[0]-= vc->ar->winrct.xmin; - mval[1]-= vc->ar->winrct.ymin; - - Mat4SwapMat4(wpd->vc.rv3d->persmat, mat); - - /* which faces are involved */ - if(wp->flag & VP_AREA) { - totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size); - } - else { - indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); - if(indexar[0]) totindex= 1; - else totindex= 0; - } - - if(wp->flag & VP_COLINDEX) { - for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); - - if(mface->mat_nr!=ob->actcol-1) { - indexar[index]= 0; - } - } - } - } - - if((G.f & G_FACESELECT) && me->mface) { - for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); - - if((mface->flag & ME_FACE_SEL)==0) { - indexar[index]= 0; - } - } - } - } - - /* make sure each vertex gets treated only once */ - /* and calculate filter weight */ - totw= 0; - if(wp->mode==VP_BLUR) - paintweight= 0.0f; - else - paintweight= ts->vgroup_weight; - - for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= me->mface + (indexar[index]-1); - - (me->dvert+mface->v1)->flag= 1; - (me->dvert+mface->v2)->flag= 1; - (me->dvert+mface->v3)->flag= 1; - if(mface->v4) (me->dvert+mface->v4)->flag= 1; - - if(wp->mode==VP_BLUR) { - MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = ED_vgroup_weight_verify; - - if(wp->flag & VP_ONLYVGROUP) - dw_func= ED_vgroup_weight_get; - - dw= dw_func(me->dvert+mface->v1, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - dw= dw_func(me->dvert+mface->v2, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - dw= dw_func(me->dvert+mface->v3, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - if(mface->v4) { - dw= dw_func(me->dvert+mface->v4, ob->actdef-1); - if(dw) {paintweight+= dw->weight; totw++;} - } - } - } - } - - if(wp->mode==VP_BLUR) - paintweight/= (float)totw; - - for(index=0; index<totindex; index++) { - - if(indexar[index] && indexar[index]<=me->totface) { - MFace *mface= me->mface + (indexar[index]-1); - - if((me->dvert+mface->v1)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v1)->flag= 0; - } - - if((me->dvert+mface->v2)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v2)->flag= 0; - } - - if((me->dvert+mface->v3)->flag) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v3)->flag= 0; - } - - if((me->dvert+mface->v4)->flag) { - if(mface->v4) { - alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval); - if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror); - } - (me->dvert+mface->v4)->flag= 0; - } - } - } - } - - Mat4SwapMat4(vc->rv3d->persmat, mat); - - DAG_id_flush_update(ob->data, OB_RECALC_DATA); - ED_region_tag_redraw(vc->ar); -} - -static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - Object *ob= CTX_data_active_object(C); - struct WPaintData *wpd= paint_stroke_mode_data(stroke); - - if(wpd->vertexcosnos) - MEM_freeN(wpd->vertexcosnos); - MEM_freeN(wpd->indexar); - - /* frees prev buffer */ - copy_wpaint_prev(ts->wpaint, NULL, 0); - - /* and particles too */ - if(ob->particlesystem.first) { - ParticleSystem *psys; - int i; - - for(psys= ob->particlesystem.first; psys; psys= psys->next) { - for(i=0; i<PSYS_TOT_VG; i++) { - if(psys->vgroup[i]==ob->actdef) { - psys->recalc |= PSYS_RECALC_RESET; - break; - } - } - } - } - - DAG_id_flush_update(ob->data, OB_RECALC_DATA); - - MEM_freeN(wpd); -} - - -static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - - op->customdata = paint_stroke_new(C, wpaint_stroke_test_start, - wpaint_stroke_update_step, - wpaint_stroke_done); + /* do paint once for click only paint */ + wpaint_modal(C, op, event); /* add modal handler */ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); - - op->type->modal(C, op, event); return OPERATOR_RUNNING_MODAL; } @@ -1508,14 +1579,13 @@ void PAINT_OT_weight_paint(wmOperatorType *ot) /* api callbacks */ ot->invoke= wpaint_invoke; - ot->modal= paint_stroke_modal; + ot->modal= wpaint_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ ot->poll= wp_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; - - RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); + } /* ************ set / clear vertex paint mode ********** */ @@ -1547,6 +1617,11 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ if(ob->mode & OB_MODE_VERTEX_PAINT) { ob->mode &= ~OB_MODE_VERTEX_PAINT; + + if(vp) { + toggle_paint_cursor(C, 0); + vp->paintcursor= NULL; + } } else { ob->mode |= OB_MODE_VERTEX_PAINT; @@ -1557,14 +1632,14 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ if(vp==NULL) vp= scene->toolsettings->vpaint= new_vpaint(0); - paint_cursor_start(C, vp_poll); + toggle_paint_cursor(C, 0); - paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT); + paint_init(&vp->paint, "Brush"); } if (me) /* update modifier stack for mapping requirements */ - DAG_id_flush_update(&me->id, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene); @@ -1610,24 +1685,158 @@ For future: */ -typedef struct VPaintData { +struct VPaintData { ViewContext vc; unsigned int paintcol; int *indexar; float *vertexcosnos; float vpimat[3][3]; -} VPaintData; +}; + +static void vpaint_exit(bContext *C, wmOperator *op) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + struct VPaintData *vpd= op->customdata; + + if(vpd->vertexcosnos) + MEM_freeN(vpd->vertexcosnos); + MEM_freeN(vpd->indexar); + + /* frees prev buffer */ + copy_vpaint_prev(ts->vpaint, NULL, 0); + + MEM_freeN(vpd); + op->customdata= NULL; +} + +static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + ToolSettings *ts= CTX_data_tool_settings(C); + VPaint *vp= ts->vpaint; + Brush *brush = paint_brush(&vp->paint); + + switch(event->type) { + case LEFTMOUSE: + if(event->val==0) { /* release */ + vpaint_exit(C, op); + return OPERATOR_FINISHED; + } + /* pass on, first press gets painted too */ + + case MOUSEMOVE: + { + struct VPaintData *vpd= op->customdata; + ViewContext *vc= &vpd->vc; + Object *ob= vc->obact; + Mesh *me= ob->data; + float mat[4][4]; + int *indexar= vpd->indexar; + int totindex, index; + short mval[2]; + + view3d_operator_needs_opengl(C); + + /* load projection matrix */ + wmMultMatrix(ob->obmat); + wmGetSingleMatrix(mat); + wmLoadMatrix(vc->rv3d->viewmat); + + mval[0]= event->x - vc->ar->winrct.xmin; + mval[1]= event->y - vc->ar->winrct.ymin; + + /* which faces are involved */ + if(vp->flag & VP_AREA) { + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size); + } + else { + indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + MTC_Mat4SwapMat4(vc->rv3d->persmat, mat); + + if(vp->flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + if((G.f & G_FACESELECT) && me->mface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if((mface->flag & ME_FACE_SEL)==0) + indexar[index]= 0; + } + } + } + + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + unsigned int *mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1); + unsigned int *mcolorig= ( (unsigned int *)vp->vpaint_prev) + 4*(indexar[index]-1); + int alpha; + + if(vp->mode==VP_BLUR) { + unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128); + if(mface->v4) { + unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128); + vpd->paintcol= mcol_blend( fcol1, fcol2, 128); + } + else { + vpd->paintcol= mcol_blend( mcol[2], fcol1, 170); + } + + } + + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval); + if(alpha) vpaint_blend(vp, mcol, mcolorig, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval); + if(alpha) vpaint_blend(vp, mcol+1, mcolorig+1, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval); + if(alpha) vpaint_blend(vp, mcol+2, mcolorig+2, vpd->paintcol, alpha); + + if(mface->v4) { + alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval); + if(alpha) vpaint_blend(vp, mcol+3, mcolorig+3, vpd->paintcol, alpha); + } + } + } + + MTC_Mat4SwapMat4(vc->rv3d->persmat, mat); + + do_shared_vertexcol(me); + + ED_region_tag_redraw(vc->ar); + + DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA); + } + break; + } + + return OPERATOR_RUNNING_MODAL; +} -static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event) +static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) { ToolSettings *ts= CTX_data_tool_settings(C); - struct PaintStroke *stroke = op->customdata; VPaint *vp= ts->vpaint; struct VPaintData *vpd; Object *ob= CTX_data_active_object(C); Mesh *me; float mat[4][4], imat[4][4]; - + /* context checks could be a poll() */ me= get_mesh(ob); if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH; @@ -1635,9 +1844,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0); if(me->mcol==NULL) return OPERATOR_CANCELLED; - /* make mode data storage */ - vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData"); - paint_stroke_set_mode_data(stroke, vpd); + /* make customdata storage */ + op->customdata= vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData"); view3d_set_viewcontext(C, &vpd->vc); vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob); @@ -1651,119 +1859,12 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent Mat4MulMat4(mat, ob->obmat, vpd->vc.rv3d->viewmat); Mat4Invert(imat, mat); Mat3CpyMat4(vpd->vpimat, imat); - - return 1; -} - -static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, float mval[2]) -{ - ViewContext *vc = &vpd->vc; - Mesh *me = get_mesh(ob); - MFace *mface= ((MFace*)me->mface) + index; - unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index; - unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index; - int alpha, i; - - if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) || - (G.f & G_FACESELECT && !(mface->flag & ME_FACE_SEL))) - return; - - if(vp->mode==VP_BLUR) { - unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128); - if(mface->v4) { - unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128); - vpd->paintcol= mcol_blend( fcol1, fcol2, 128); - } - else { - vpd->paintcol= mcol_blend( mcol[2], fcol1, 170); - } - - } - - for(i = 0; i < (mface->v4 ? 4 : 3); ++i) { - alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval); - if(alpha) - vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, alpha); - } -} - -static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - struct VPaintData *vpd = paint_stroke_mode_data(stroke); - VPaint *vp= ts->vpaint; - Brush *brush = paint_brush(&vp->paint); - ViewContext *vc= &vpd->vc; - Object *ob= vc->obact; - Mesh *me= ob->data; - float mat[4][4]; - int *indexar= vpd->indexar; - int totindex, index; - float mval[2]; - - RNA_float_get_array(itemptr, "mouse", mval); - - view3d_operator_needs_opengl(C); - - /* load projection matrix */ - wmMultMatrix(ob->obmat); - wmGetSingleMatrix(mat); - wmLoadMatrix(vc->rv3d->viewmat); - - mval[0]-= vc->ar->winrct.xmin; - mval[1]-= vc->ar->winrct.ymin; - - - /* which faces are involved */ - if(vp->flag & VP_AREA) { - totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size); - } - else { - indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); - if(indexar[0]) totindex= 1; - else totindex= 0; - } - - Mat4SwapMat4(vc->rv3d->persmat, mat); - - for(index=0; index<totindex; index++) { - if(indexar[index] && indexar[index]<=me->totface) - vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval); - } - - Mat4SwapMat4(vc->rv3d->persmat, mat); - - ED_region_tag_redraw(vc->ar); - - DAG_id_flush_update(ob->data, OB_RECALC_DATA); -} - -static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke) -{ - ToolSettings *ts= CTX_data_tool_settings(C); - struct VPaintData *vpd= paint_stroke_mode_data(stroke); - if(vpd->vertexcosnos) - MEM_freeN(vpd->vertexcosnos); - MEM_freeN(vpd->indexar); - - /* frees prev buffer */ - copy_vpaint_prev(ts->vpaint, NULL, 0); - - MEM_freeN(vpd); -} - -static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - - op->customdata = paint_stroke_new(C, vpaint_stroke_test_start, - vpaint_stroke_update_step, - vpaint_stroke_done); + /* do paint once for click only paint */ + vpaint_modal(C, op, event); /* add modal handler */ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); - - op->type->modal(C, op, event); return OPERATOR_RUNNING_MODAL; } @@ -1776,13 +1877,11 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) /* api callbacks */ ot->invoke= vpaint_invoke; - ot->modal= paint_stroke_modal; + ot->modal= vpaint_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ ot->poll= vp_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; - - RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } |