diff options
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 6 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 21 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 48 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 3 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_header.c | 37 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_intern.h | 6 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_ops.c | 7 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_select.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/vpaint.c | 536 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_windowmanager_types.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 105 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 34 | ||||
-rw-r--r-- | source/blender/windowmanager/wm.h | 7 |
16 files changed, 522 insertions, 299 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 042516e518e..ac0b819aa6b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3828,7 +3828,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->operators.first= wm->operators.last= NULL; wm->keymaps.first= wm->keymaps.last= NULL; - + wm->paintcursors.first= wm->paintcursors.last= NULL; wm->queue.first= wm->queue.last= NULL; wm->reports.first= wm->reports.last= NULL; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 7b3b31cbe30..60a5ff8481e 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -40,6 +40,7 @@ struct EditEdge; struct EditFace; struct ImBuf; struct Scene; +struct bContext; /* for derivedmesh drawing callbacks, for view3d_select, .... */ typedef struct ViewContext { @@ -60,6 +61,8 @@ typedef struct VPaint { int tot, pad; /* allocation size of prev buffers */ unsigned int *vpaint_prev; /* previous mesh colors */ struct MDeformVert *wpaint_prev; /* previous vertex weights */ + + void *paintcursor; /* wm handle */ } VPaint; /* Gvp.flag and Gwp.flag */ @@ -112,6 +115,9 @@ unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); #define MAXPICKBUF 10000 short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, rcti *input); +/* modes */ +void ED_view3d_exit_paint_modes(struct bContext *C); + #endif /* ED_VIEW3D_H */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 2650bd96b39..e3fa8b22463 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -180,8 +180,8 @@ void ED_base_object_activate(bContext *C, Base *base) Base *tbase; /* activating a non-mesh, should end a couple of modes... */ - // if(base && base->object->type!=OB_MESH) - // XXX exit_paint_modes(); + if(base && base->object->type!=OB_MESH) + ED_view3d_exit_paint_modes(C); /* sets scene->basact */ BASACT= base; @@ -235,19 +235,6 @@ int object_data_is_libdata(Object *ob) -void exit_paint_modes(void) -{ -#if 0 - if(G.f & G_VERTEXPAINT) set_vpaint(); - if(G.f & G_TEXTUREPAINT) set_texturepaint(); - if(G.f & G_WEIGHTPAINT) set_wpaint(); - if(G.f & G_SCULPTMODE) set_sculptmode(); - if(G.f & G_PARTICLEEDIT) PE_set_particle_edit(); - - G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT); -#endif -} - /* exported */ void ED_object_base_init_from_view(Scene *scene, View3D *v3d, Base *base) { @@ -284,7 +271,7 @@ void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menu { Object *ob; - exit_paint_modes(); +// ED_view3d_exit_paint_modes(C); // XXX if (obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */ ob= add_object(scene, type); @@ -362,7 +349,7 @@ void delete_obj(Scene *scene, View3D *v3d, int ok) } } - exit_paint_modes(); +// ED_view3d_exit_paint_modes(C); if(base->object->type==OB_LAMP) islamp= 1; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index e2cafeceb9e..5aa8a5b466b 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -206,33 +206,31 @@ void ED_region_do_draw(bContext *C, ARegion *ar) /* note; this sets state, so we can use wmOrtho and friends */ wmSubWindowSet(win, ar->swinid); - if(ar->swinid) { - /* optional header info instead? */ - if(ar->headerstr) { - float col[3]; - UI_SetTheme(sa); - UI_GetThemeColor3fv(TH_HEADER, col); - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - UI_ThemeColor(TH_MENU_TEXT); - glRasterPos2i(20, 6); - BMF_DrawString(G.font, ar->headerstr); - } - else if(at->draw) { - UI_SetTheme(sa); - at->draw(C, ar); - UI_SetTheme(NULL); - } - - if(sa) - region_draw_emboss(ar); - - uiFreeInactiveBlocks(C, &ar->uiblocks); + /* optional header info instead? */ + if(ar->headerstr) { + float col[3]; + UI_SetTheme(sa); + UI_GetThemeColor3fv(TH_HEADER, col); + glClearColor(col[0], col[1], col[2], 0.0); + glClear(GL_COLOR_BUFFER_BIT); - /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */ - ED_region_pixelspace(ar); + UI_ThemeColor(TH_MENU_TEXT); + glRasterPos2i(20, 6); + BMF_DrawString(G.font, ar->headerstr); } + else if(at->draw) { + UI_SetTheme(sa); + at->draw(C, ar); + UI_SetTheme(NULL); + } + + if(sa) + region_draw_emboss(ar); + + uiFreeInactiveBlocks(C, &ar->uiblocks); + + /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */ + ED_region_pixelspace(ar); ar->do_draw= 0; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 536ce9cee74..d78fdbbae6e 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1119,7 +1119,8 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event) } -/* called in wm_event_system.c. sets state var in screen */ +/* called in wm_event_system.c. sets state vars in screen, cursors */ +/* event type is mouse move */ void ED_screen_set_subwinactive(wmWindow *win, wmEvent *event) { if(win->screen) { diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 3caa2d25da7..d8025698f02 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -136,6 +136,25 @@ static int retopo_mesh_paint_check() {return 0;} /* end XXX ************* */ + +/* well... in this file a lot of view mode manipulation happens, so let's have it defined here */ +void ED_view3d_exit_paint_modes(bContext *C) +{ + if(G.f & G_VERTEXPAINT) + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + +// if(G.f & G_TEXTUREPAINT) set_texturepaint(); +// if(G.f & G_WEIGHTPAINT) set_wpaint(); +// if(G.f & G_SCULPTMODE) set_sculptmode(); +// if(G.f & G_PARTICLEEDIT) PE_set_particle_edit(); + + G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT); +} + + + + + static void do_view3d_buttons(bContext *C, void *arg, int event); #define B_SCENELOCK 101 @@ -5368,7 +5387,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) if (v3d->modeselect == V3D_OBJECTMODE_SEL) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); ED_armature_exit_posemode(basact); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ @@ -5376,7 +5395,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_EDITMODE_SEL) { if(!obedit) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); ED_object_enter_editmode(C, EM_WAITCURSOR); ED_undo_push(C, "Original"); /* here, because all over code enter_editmode is abused */ } @@ -5384,7 +5403,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_SCULPTMODE_SEL) { if (!(G.f & G_SCULPTMODE)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEUNDO); /* exit editmode and undo */ // XXX set_sculptmode(); @@ -5393,16 +5412,16 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_VERTEXPAINTMODE_SEL) { if (!(G.f & G_VERTEXPAINT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ - -// XXX set_vpaint(); + + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); } } else if (v3d->modeselect == V3D_TEXTUREPAINTMODE_SEL) { if (!(G.f & G_TEXTUREPAINT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ // XXX set_texturepaint(); @@ -5411,7 +5430,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_WEIGHTPAINTMODE_SEL) { if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) ) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ @@ -5431,7 +5450,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if(v3d->modeselect == V3D_PARTICLEEDITMODE_SEL){ if (!(G.f & G_PARTICLEEDIT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ // XXX PE_set_particle_edit(); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d9d58b188ea..7fb17071e71 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -116,6 +116,12 @@ void VIEW3D_OT_circle_select(struct wmOperatorType *ot); void VIEW3D_OT_borderselect(struct wmOperatorType *ot); void VIEW3D_OT_lasso_select(struct wmOperatorType *ot); +void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc); + +/* vpaint.c */ +void VIEW3D_OT_vpaint_toggle(struct wmOperatorType *ot); +void VIEW3D_OT_vpaint(struct wmOperatorType *ot); + /* view3d_view.c */ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 73329ac5aa3..da4b752f370 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -79,6 +79,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_lasso_select); WM_operatortype_append(VIEW3D_OT_setcameratoview); WM_operatortype_append(VIEW3D_OT_drawtype); + WM_operatortype_append(VIEW3D_OT_vpaint_toggle); + WM_operatortype_append(VIEW3D_OT_vpaint); transform_operatortypes(); } @@ -88,6 +90,9 @@ void view3d_keymap(wmWindowManager *wm) ListBase *keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); wmKeymapItem *km; + /* paint poll checks mode */ + WM_keymap_verify_item(keymap, "VIEW3D_OT_vpaint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_viewrotate", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -148,6 +153,8 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_set_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0); + + WM_keymap_add_item(keymap, "VIEW3D_OT_vpaint_toggle", VKEY, KM_PRESS, 0, 0); /* TODO - this is just while we have no way to load a text datablock */ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_run_pyfile", PKEY, KM_PRESS, 0, 0)->ptr, "filename", "test.py"); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index e1cc1f65c15..6664ac11877 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -89,7 +89,7 @@ #include "view3d_intern.h" // own include -static void view3d_set_viewcontext(bContext *C, ViewContext *vc) +void view3d_set_viewcontext(bContext *C, ViewContext *vc) { memset(vc, 0, sizeof(ViewContext)); vc->ar= CTX_wm_region(C); diff --git a/source/blender/editors/space_view3d/vpaint.c b/source/blender/editors/space_view3d/vpaint.c index df21b2de096..f253612259f 100644 --- a/source/blender/editors/space_view3d/vpaint.c +++ b/source/blender/editors/space_view3d/vpaint.c @@ -64,6 +64,7 @@ #include "BKE_armature.h" #include "BKE_DerivedMesh.h" #include "BKE_cloth.h" +#include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_deform.h" @@ -76,11 +77,15 @@ #include "BKE_utildefines.h" #include "WM_api.h" +#include "WM_types.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "ED_mesh.h" #include "ED_object.h" +#include "ED_screen.h" +#include "ED_util.h" #include "ED_view3d.h" #include "view3d_intern.h" @@ -344,7 +349,7 @@ void clear_vpaint_selectedfaces(Scene *scene) /* fills in the selected faces with the current weight and vertex group */ void clear_wpaint_selectedfaces(Scene *scene) { - extern float editbutvweight; + float editbutvweight; float paintweight= editbutvweight; Mesh *me; MFace *mface; @@ -721,69 +726,51 @@ static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int } -static int sample_backbuf_area(ARegion *ar, int *indexar, int totface, int x, int y, float size) +static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size) { - unsigned int *rt; struct ImBuf *ibuf; - int x1, y1, x2, y2, a, tot=0, index; + int a, tot=0, index; if(totface+4>=MAXINDEX) return 0; if(size>64.0) size= 64.0; - x1= x-size; - x2= x+size; - CLAMP(x1, 0, ar->winx-1); - CLAMP(x2, 0, ar->winx-1); - y1= y-size; - y2= y+size; - CLAMP(y1, 0, ar->winy-1); - CLAMP(y2, 0, ar->winy-1); - - if(x1>=x2 || y1>=y2) return 0; - - ibuf = IMB_allocImBuf(2*size + 4, 2*size + 4, 32, IB_rect, 0); - glReadPixels(x1+ar->winrct.xmin, y1+ar->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - glReadBuffer(GL_BACK); - - if(ENDIAN_ORDER==B_ENDIAN) { - IMB_convert_rgba_to_abgr(ibuf); - } - - rt= ibuf->rect; - size= (y2-y1)*(x2-x1); - if(size<=0) return 0; + ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size); + if(ibuf) { + unsigned int *rt= ibuf->rect; - memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */ - - while(size--) { - - if(*rt) { - index= WM_framebuffer_to_index(*rt); - if(index>0 && index<=totface) - indexar[index] = 1; + memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */ + + size= ibuf->x*ibuf->y; + while(size--) { + + if(*rt) { + index= WM_framebuffer_to_index(*rt); + if(index>0 && index<=totface) + indexar[index] = 1; + } + + rt++; + } + + for(a=1; a<=totface; a++) { + if(indexar[a]) indexar[tot++]= a; } - - rt++; - } - - for(a=1; a<=totface; a++) { - if(indexar[a]) indexar[tot++]= a; - } - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); + } return tot; } -static int calc_vp_alpha_dl(VPaint *vp, ARegion *ar, View3D *v3d, float vpimat[][3], float *vert_nor, short *mval) +static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, short *mval) { float fac, dx, dy; int alpha; short vertco[2]; if(vp->flag & VP_SOFT) { - project_short_noclip(ar, v3d, vert_nor, vertco); + project_short_noclip(vc->ar, vc->v3d, vert_nor, vertco); dx= mval[0]-vertco[0]; dy= mval[1]-vertco[1]; @@ -967,7 +954,7 @@ static void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) else { DerivedMesh *dm; MDeformWeight *dw; - extern float editbutvweight; + float editbutvweight; float w1, w2, w3, w4, co[3], fac; dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); @@ -1055,6 +1042,7 @@ static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paint } } + void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) { ViewContext vc; @@ -1170,7 +1158,7 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) /* which faces are involved */ if(Gwp.flag & VP_AREA) { - totindex= sample_backbuf_area(ar, indexar, me->totface, mval[0], mval[1], Gwp.size); + totindex= sample_backbuf_area(&vc, indexar, me->totface, mval[0], mval[1], Gwp.size); } else { indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]); @@ -1252,7 +1240,7 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) mface= me->mface + (indexar[index]-1); if((me->dvert+mface->v1)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v1, mval); + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v1, mval); if(alpha) { do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror); } @@ -1260,7 +1248,7 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) } if((me->dvert+mface->v2)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v2, mval); + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v2, mval); if(alpha) { do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror); } @@ -1268,7 +1256,7 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) } if((me->dvert+mface->v3)->flag) { - alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v3, mval); + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v3, mval); if(alpha) { do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror); } @@ -1277,7 +1265,7 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) if((me->dvert+mface->v4)->flag) { if(mface->v4) { - alpha= calc_vp_alpha_dl(&Gwp, ar, v3d, vpimat, vertexcosnos+6*mface->v4, mval); + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v4, mval); if(alpha) { do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror); } @@ -1335,84 +1323,243 @@ void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) BIF_undo_push("Weight Paint"); } -void vertex_paint(Scene *scene, ARegion *ar, View3D *v3d) -{ - ViewContext vc; - Object *ob; +void set_wpaint(bContext *C, wmOperator *op) /* toggle */ +{ + Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); Mesh *me; - MFace *mface; - float mat[4][4], imat[4][4], *vertexcosnos; - float vpimat[3][3]; - unsigned int paintcol=0, *mcol, *mcolorig, fcol1, fcol2; - int *indexar, index, alpha, totindex; - short mval[2], mvalo[2], firsttime=1; - - if((G.f & G_VERTEXPAINT)==0) return; - if(scene->obedit) return; ob= OBACT; if(!ob || ob->id.lib) return; - me= get_mesh(ob); - if(me==NULL || me->totface==0) return; - if(ob->lay & v3d->lay); else error("Active object is not in this layer"); - if(me->mcol==NULL) make_vertexcol(scene, 0); - - if(me->mcol==NULL) return; + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_WEIGHTPAINT; + return; + } - /* ALLOCATIONS! No return after his line */ + if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; + else G.f |= G_WEIGHTPAINT; - /* painting on subsurfs should give correct points too, this returns me->totvert amount */ - vertexcosnos= mesh_get_mapped_verts_nors(scene, ob); - indexar= get_indexarray(); - copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface); - /* opengl/matrix stuff */ -// XXX persp(PERSP_VIEW); - /* imat for normals */ - Mat4MulMat4(mat, ob->obmat, v3d->viewmat); - Mat4Invert(imat, mat); - Mat3CpyMat4(vpimat, imat); + /* Weightpaint works by overriding colors in mesh, + * so need to make sure we recalc on enter and + * exit (exit needs doing regardless because we + * should redeform). + */ + if (me) { + DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); + } - /* load projection matrix */ - wmMultMatrix(ob->obmat); - wmGetSingleMatrix(mat); - wmLoadMatrix(v3d->viewmat); + if(G.f & G_WEIGHTPAINT) { + Object *par; + + mesh_octree_table(ob, NULL, NULL, 's'); + + /* verify if active weight group is also active bone */ + par= modifiers_isDeformedByArmature(ob); + if(par && (par->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->bone->flag & BONE_ACTIVE) + break; + // if(pchan) + // XXX vertexgroup_select_by_name(ob, pchan->name); + } + } + else { + mesh_octree_table(ob, NULL, NULL, 'e'); + } +} + +/* ************ set / clear vertex paint mode ********** */ + +/* retrieve whether cursor should be set or operator should be done */ +static int vp_poll(bContext *C) +{ + if(G.f & G_VERTEXPAINT) { + ScrArea *sa= CTX_wm_area(C); + if(sa->spacetype==SPACE_VIEW3D) { + ARegion *ar= CTX_wm_region(C); + if(ar->regiontype==RGN_TYPE_WINDOW) + return 1; + } + } + return 0; +} + +static void vp_drawcursor(bContext *C, int x, int y) +{ + glTranslatef((float)x, (float)y, 0.0f); - paintcol= vpaint_get_current_col(&Gvp); + glColor4ub(255, 255, 255, 128); + glEnable( GL_LINE_SMOOTH ); + glEnable(GL_BLEND); + glutil_draw_lined_arc(0.0, M_PI*2.0, Gvp.size, 40); + glDisable(GL_BLEND); + glDisable( GL_LINE_SMOOTH ); -// getmouseco_areawin(mvalo); + glTranslatef((float)-x, (float)-y, 0.0f); +} + +static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ +{ + Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); + Mesh *me; -// getmouseco_areawin(mval); - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; + if(object_data_is_libdata(ob)) { + G.f &= ~G_VERTEXPAINT; + return OPERATOR_FINISHED; + } - while (get_mbut() & 0) { -// getmouseco_areawin(mval); + me= get_mesh(ob); + + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_VERTEXPAINT; + return OPERATOR_FINISHED; + } + + if(me && me->mcol==NULL) make_vertexcol(scene, 0); + + /* toggle: end vpaint */ + if(G.f & G_VERTEXPAINT){ + G.f &= ~G_VERTEXPAINT; - if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + WM_paint_cursor_end(CTX_wm_manager(C), Gvp.paintcursor); + Gvp.paintcursor= NULL; + } + else { + G.f |= G_VERTEXPAINT; + /* Turn off weight painting */ + if (G.f & G_WEIGHTPAINT) + set_wpaint(C, op); + + Gvp.paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor); + } + + if (me) + /* update modifier stack for mapping requirements */ + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + WM_event_add_notifier(C, NC_SCENE|ND_MODE, ob); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_vpaint_toggle(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Vpaint mode"; + ot->idname= "VIEW3D_OT_vpaint_toggle"; + + /* api callbacks */ + ot->exec= set_vpaint; + ot->poll= ED_operator_object_active; + +} - firsttime= 0; + +/* ********************** vertex paint operator ******************* */ + +/* Implementation notes: + +Operator->invoke() + - validate context (add mcol) + - create customdata storage + - call paint once (mouse click) + - add modal handler + +Operator->modal() + - for every mousemove, apply vertex paint + - exit on mouse release, free customdata + (return OPERATOR_FINISHED also removes handler and operator) + +For future: + - implement a stroke event (or mousemove with past positons) + - revise whether customdata should be added in object, in set_vpaint + - store Gvp locally (in scene?) + +*/ + +struct VPaintData { + ViewContext vc; + unsigned int paintcol; + int *indexar; + float *vertexcosnos; + float vpimat[3][3]; +}; + +static void vpaint_exit(bContext *C, wmOperator *op) +{ + struct VPaintData *vpd= op->customdata; + + if(vpd->vertexcosnos) + MEM_freeN(vpd->vertexcosnos); + MEM_freeN(vpd->indexar); + + /* frees prev buffer */ + copy_vpaint_prev(&Gvp, NULL, 0); + + ED_undo_push(C, "Vertex Paint"); + + MEM_freeN(vpd); + op->customdata= NULL; +} + +static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + + 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->v3d->viewmat); + + mval[0]= event->x - vc->ar->winrct.xmin; + mval[1]= event->y - vc->ar->winrct.ymin; + /* which faces are involved */ if(Gvp.flag & VP_AREA) { - totindex= sample_backbuf_area(ar, indexar, me->totface, mval[0], mval[1], Gvp.size); + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], Gvp.size); } else { - indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]); + indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); if(indexar[0]) totindex= 1; else totindex= 0; } - MTC_Mat4SwapMat4(v3d->persmat, mat); + MTC_Mat4SwapMat4(vc->v3d->persmat, mat); if(Gvp.flag & VP_COLINDEX) { for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - - mface= ((MFace *)me->mface) + (indexar[index]-1); - + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + if(mface->mat_nr!=ob->actcol-1) { indexar[index]= 0; } @@ -1422,163 +1569,116 @@ void vertex_paint(Scene *scene, ARegion *ar, View3D *v3d) if((G.f & G_FACESELECT) && me->mface) { for(index=0; index<totindex; index++) { if(indexar[index] && indexar[index]<=me->totface) { - mface= ((MFace *)me->mface) + (indexar[index]-1); - + 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 *)me->mface) + (indexar[index]-1); - mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1); - mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1); - + 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 *)Gvp.vpaint_prev) + 4*(indexar[index]-1); + int alpha; + if(Gvp.mode==VP_BLUR) { - fcol1= mcol_blend( mcol[0], mcol[1], 128); + unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128); if(mface->v4) { - fcol2= mcol_blend( mcol[2], mcol[3], 128); - paintcol= mcol_blend( fcol1, fcol2, 128); + unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128); + vpd->paintcol= mcol_blend( fcol1, fcol2, 128); } else { - paintcol= mcol_blend( mcol[2], fcol1, 170); + vpd->paintcol= mcol_blend( mcol[2], fcol1, 170); } } - alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v1, mval); - if(alpha) vpaint_blend( mcol, mcolorig, paintcol, alpha); + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval); + if(alpha) vpaint_blend( mcol, mcolorig, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval); + if(alpha) vpaint_blend( mcol+1, mcolorig+1, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval); + if(alpha) vpaint_blend( mcol+2, mcolorig+2, vpd->paintcol, alpha); - alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v2, mval); - if(alpha) vpaint_blend( mcol+1, mcolorig+1, paintcol, alpha); - - alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v3, mval); - if(alpha) vpaint_blend( mcol+2, mcolorig+2, paintcol, alpha); - if(mface->v4) { - alpha= calc_vp_alpha_dl(&Gvp, ar, v3d, vpimat, vertexcosnos+6*mface->v4, mval); - if(alpha) vpaint_blend( mcol+3, mcolorig+3, paintcol, alpha); + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval); + if(alpha) vpaint_blend( mcol+3, mcolorig+3, vpd->paintcol, alpha); } } } - - MTC_Mat4SwapMat4(v3d->persmat, mat); + + MTC_Mat4SwapMat4(vc->v3d->persmat, mat); do_shared_vertexcol(me); - - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - - if(Gvp.flag & (VP_AREA|VP_SOFT)) { - /* draw circle in backbuf! */ -// XXX persp(PERSP_WIN); -// fdrawXORcirc((float)mval[0], (float)mval[1], Gvp.size); -// persp(PERSP_VIEW); - } - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; + ED_region_tag_redraw(vc->ar); + + DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA); } - } - - if(vertexcosnos) - MEM_freeN(vertexcosnos); - MEM_freeN(indexar); - - /* frees prev buffer */ - copy_vpaint_prev(&Gvp, NULL, 0); + break; + } - BIF_undo_push("Vertex Paint"); - + return OPERATOR_RUNNING_MODAL; } -void set_wpaint(Scene *scene) /* toggle */ -{ - Object *ob; +static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + struct VPaintData *vpd; + Object *ob= CTX_data_active_object(C); Mesh *me; + float mat[4][4], imat[4][4]; - ob= OBACT; - if(!ob || ob->id.lib) return; + /* context checks could be a poll() */ me= get_mesh(ob); - - if(me && me->totface>=MAXINDEX) { - error("Maximum number of faces: %d", MAXINDEX-1); - G.f &= ~G_WEIGHTPAINT; - return; - } + if(me==NULL || me->totface==0) return OPERATOR_CANCELLED; - if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; - else G.f |= G_WEIGHTPAINT; + if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0); + if(me->mcol==NULL) return OPERATOR_CANCELLED; + /* make customdata storage */ + op->customdata= vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData"); + view3d_set_viewcontext(C, &vpd->vc); - /* Weightpaint works by overriding colors in mesh, - * so need to make sure we recalc on enter and - * exit (exit needs doing regardless because we - * should redeform). - */ - if (me) { - DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); - } - - if(G.f & G_WEIGHTPAINT) { - Object *par; - - mesh_octree_table(ob, NULL, NULL, 's'); - - /* verify if active weight group is also active bone */ - par= modifiers_isDeformedByArmature(ob); - if(par && (par->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) - if(pchan->bone->flag & BONE_ACTIVE) - break; -// if(pchan) -// XXX vertexgroup_select_by_name(ob, pchan->name); - } - } - else { - mesh_octree_table(ob, NULL, NULL, 'e'); - } -} - - -void set_vpaint(Scene *scene) /* toggle */ -{ - Object *ob; - Mesh *me; + vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob); + vpd->indexar= get_indexarray(); + vpd->paintcol= vpaint_get_current_col(&Gvp); - ob= OBACT; - if(!ob || object_data_is_libdata(ob)) { - G.f &= ~G_VERTEXPAINT; - return; - } + /* for filtering */ + copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface); - me= get_mesh(ob); + /* some old cruft to sort out later */ + Mat4MulMat4(mat, ob->obmat, vpd->vc.v3d->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(vpd->vpimat, imat); - if(me && me->totface>=MAXINDEX) { - error("Maximum number of faces: %d", MAXINDEX-1); - G.f &= ~G_VERTEXPAINT; - return; - } + /* do paint once for click only paint */ + vpaint_modal(C, op, event); - if(me && me->mcol==NULL) make_vertexcol(scene, 0); + /* add modal handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); - if(G.f & G_VERTEXPAINT){ - G.f &= ~G_VERTEXPAINT; - } - else { - G.f |= G_VERTEXPAINT; - /* Turn off weight painting */ - if (G.f & G_WEIGHTPAINT) - set_wpaint(scene); - } - - if (me) - /* update modifier stack for mapping requirements */ - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + return OPERATOR_RUNNING_MODAL; +} +void VIEW3D_OT_vpaint(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Vpaint"; + ot->idname= "VIEW3D_OT_vpaint"; + + /* api callbacks */ + ot->invoke= vpaint_invoke; + ot->modal= vpaint_modal; + /* ot->exec= vpaint_exec; <-- needs stroke property */ + ot->poll= vp_poll; + } + diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index a563e2af210..5b1ffdd35f2 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -68,6 +68,8 @@ typedef struct wmWindowManager { ListBase reports; /* information and error reports */ + ListBase paintcursors; /* extra overlay cursors to draw, like circles */ + /* used keymaps, optionally/partially saved */ ListBase keymaps; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 40a67c3c67a..c4cd6d655a3 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -63,6 +63,9 @@ void WM_cursor_restore (struct wmWindow *win); void WM_cursor_wait (struct wmWindow *win, int val); void WM_timecursor (struct wmWindow *win, int nr); +void *WM_paint_cursor_activate(struct wmWindowManager *wm, int (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int)); +void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); + /* keymap */ wmKeymapItem *WM_keymap_set_item (ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 1533cc636db..f76bfb511b3 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -168,6 +168,8 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) BLI_freelistN(&wm->queue); + BLI_freelistN(&wm->paintcursors); + if(C && CTX_wm_manager(C)==wm) CTX_wm_manager_set(C, NULL); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 046fbdefb64..161ab66f3fd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -277,6 +277,23 @@ static int wm_draw_update_test_window(wmWindow *win) return 0; } +static void wm_paintcursor_draw(bContext *C) +{ + wmWindowManager *wm= CTX_wm_manager(C); + + if(wm->paintcursors.first) { + wmWindow *win= CTX_wm_window(C); + wmPaintCursor *pc; + + for(pc= wm->paintcursors.first; pc; pc= pc->next) { + if(pc->poll(C)) { + ARegion *ar= CTX_wm_region(C); + pc->draw(C, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin); + } + } + } +} + void wm_draw_update(bContext *C) { wmWindowManager *wm= CTX_wm_manager(C); @@ -304,12 +321,16 @@ void wm_draw_update(bContext *C) CTX_wm_area_set(C, sa); for(ar=sa->regionbase.first; ar; ar= ar->next) { - CTX_wm_region_set(C, ar); - if(ar->swinid && ar->do_draw) + if(ar->swinid && ar->do_draw) { + CTX_wm_region_set(C, ar); + ED_region_do_draw(C, ar); - - CTX_wm_region_set(C, NULL); + if(win->screen->subwinactive==ar->swinid) + wm_paintcursor_draw(C); + + CTX_wm_region_set(C, NULL); + } } CTX_wm_area_set(C, NULL); @@ -509,7 +530,6 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe /* ********************* handlers *************** */ - /* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */ static void wm_event_free_handler(wmEventHandler *handler) { @@ -799,11 +819,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) static int wm_event_inside_i(wmEvent *event, rcti *rect) { - return BLI_in_rcti(rect, event->x, event->y); -} - -static int wm_event_prev_inside_i(wmEvent *event, rcti *rect) -{ if(BLI_in_rcti(rect, event->x, event->y)) return 1; if(event->type==MOUSEMOVE) { @@ -815,19 +830,19 @@ static int wm_event_prev_inside_i(wmEvent *event, rcti *rect) return 0; } -static ScrArea *area_event_inside(bContext *C, wmEvent *event) +static ScrArea *area_event_inside(bContext *C, int x, int y) { bScreen *screen= CTX_wm_screen(C); ScrArea *sa; if(screen) for(sa= screen->areabase.first; sa; sa= sa->next) - if(BLI_in_rcti(&sa->totrct, event->x, event->y)) + if(BLI_in_rcti(&sa->totrct, x, y)) return sa; return NULL; } -static ARegion *region_event_inside(bContext *C, wmEvent *event) +static ARegion *region_event_inside(bContext *C, int x, int y) { bScreen *screen= CTX_wm_screen(C); ScrArea *area= CTX_wm_area(C); @@ -835,11 +850,44 @@ static ARegion *region_event_inside(bContext *C, wmEvent *event) if(screen && area) for(ar= area->regionbase.first; ar; ar= ar->next) - if(BLI_in_rcti(&ar->winrct, event->x, event->y)) + if(BLI_in_rcti(&ar->winrct, x, y)) return ar; return NULL; } +static void wm_paintcursor_tag(bContext *C, wmPaintCursor *pc, ARegion *ar) +{ + if(ar) + for(; pc; pc= pc->next) + if(pc->poll(C)) + ED_region_tag_redraw(ar); +} + +/* called on mousemove, check updates for paintcursors */ +/* context was set on active area and region */ +static void wm_paintcursor_test(bContext *C, wmEvent *event) +{ + wmWindowManager *wm= CTX_wm_manager(C); + + if(wm->paintcursors.first) { + ARegion *ar= CTX_wm_region(C); + if(ar) + wm_paintcursor_tag(C, wm->paintcursors.first, ar); + + /* if previous position was not in current region, we have to set a temp new context */ + if(ar==NULL || !BLI_in_rcti(&ar->winrct, event->prevx, event->prevy)) { + ScrArea *sa= CTX_wm_area(C); + + CTX_wm_area_set(C, area_event_inside(C, event->prevx, event->prevy)); + CTX_wm_region_set(C, region_event_inside(C, event->prevx, event->prevy)); + + wm_paintcursor_tag(C, wm->paintcursors.first, CTX_wm_region(C)); + + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + } + } +} /* called in main loop */ /* goes over entire hierarchy: events -> window -> screen -> area -> region */ @@ -857,8 +905,9 @@ void wm_event_do_handlers(bContext *C) int action; CTX_wm_window_set(C, win); - CTX_wm_area_set(C, area_event_inside(C, event)); - CTX_wm_region_set(C, region_event_inside(C, event)); + /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ + CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); + CTX_wm_region_set(C, region_event_inside(C, event->x, event->y)); /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ wm_window_make_drawable(C, win); @@ -871,22 +920,26 @@ void wm_event_do_handlers(bContext *C) int doit= 0; /* XXX to solve, here screen handlers? */ - if(!wm_event_always_pass(event)) + if(event->type==MOUSEMOVE) { ED_screen_set_subwinactive(win, event); /* state variables in screen, cursors */ + wm_paintcursor_test(C, event); + } for(sa= win->screen->areabase.first; sa; sa= sa->next) { - if(wm_event_always_pass(event) || wm_event_prev_inside_i(event, &sa->totrct)) { - doit= 1; + if(wm_event_always_pass(event) || wm_event_inside_i(event, &sa->totrct)) { + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, NULL); action= wm_handlers_do(C, event, &sa->handlers); if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) { for(ar=sa->regionbase.first; ar; ar= ar->next) { - if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct) || wm_event_prev_inside_i(event, &ar->winrct)) { + if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); action= wm_handlers_do(C, event, &ar->handlers); - CTX_wm_region_set(C, NULL); + doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y)); + if(!wm_event_always_pass(event)) { if(action==WM_HANDLER_BREAK) break; @@ -894,21 +947,21 @@ void wm_event_do_handlers(bContext *C) } } } - - CTX_wm_area_set(C, NULL); /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */ } } /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad? doing it on ghost queue gives errors when mousemoves go over area borders */ - if(doit) { - CTX_wm_window(C)->eventstate->prevx= event->x; - CTX_wm_window(C)->eventstate->prevy= event->y; + if(doit && win->screen->subwinactive != win->screen->mainwin) { + win->eventstate->prevx= event->x; + win->eventstate->prevy= event->y; } } wm_event_free(event); CTX_wm_window_set(C, NULL); + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); } } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 92a233d1067..a2eefad05a5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -391,6 +391,38 @@ static void WM_OT_exit_blender(wmOperatorType *ot) ot->poll= WM_operator_winactive; } +/* ************ default paint cursors, draw always around cursor *********** */ +/* + - returns handler to free + - poll(bContext): returns 1 if draw should happen + - draw(bContext): drawing callback for paint cursor +*/ + +void *WM_paint_cursor_activate(wmWindowManager *wm, int (*poll)(bContext *C), void (*draw)(bContext *C, int, int)) +{ + wmPaintCursor *pc= MEM_callocN(sizeof(wmPaintCursor), "paint cursor"); + + BLI_addtail(&wm->paintcursors, pc); + + pc->poll= poll; + pc->draw= draw; + + return pc; +} + +void WM_paint_cursor_end(wmWindowManager *wm, void *handle) +{ + wmPaintCursor *pc; + + for(pc= wm->paintcursors.first; pc; pc= pc->next) { + if(pc == (wmPaintCursor *)handle) { + BLI_remlink(&wm->paintcursors, pc); + MEM_freeN(pc); + return; + } + } +} + /* ************ window gesture operator-callback definitions ************** */ /* * These are default callbacks for use in operators requiring gesture input @@ -496,7 +528,7 @@ int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) } /* **************** circle gesture *************** */ -/* works now only for selection or modal paint stuff, calls exec while hold mouse */ +/* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event) { diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 1835a475323..c063226b96f 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -30,6 +30,13 @@ struct wmWindow; +typedef struct wmPaintCursor { + struct wmPaintCursor *next, *prev; + + int (*poll)(struct bContext *C); + void (*draw)(bContext *C, int, int); +} wmPaintCursor; + extern void wm_close_and_free(bContext *C, wmWindowManager *); extern void wm_close_and_free_all(bContext *C, ListBase *); |