Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/editors/include/ED_view3d.h6
-rw-r--r--source/blender/editors/object/object_edit.c21
-rw-r--r--source/blender/editors/screen/area.c48
-rw-r--r--source/blender/editors/screen/screen_edit.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h6
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c2
-rw-r--r--source/blender/editors/space_view3d/vpaint.c536
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h2
-rw-r--r--source/blender/windowmanager/WM_api.h3
-rw-r--r--source/blender/windowmanager/intern/wm.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c105
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c34
-rw-r--r--source/blender/windowmanager/wm.h7
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 *);