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:
authorTon Roosendaal <ton@blender.org>2009-01-09 16:55:45 +0300
committerTon Roosendaal <ton@blender.org>2009-01-09 16:55:45 +0300
commitc7fa55eebdd74812c5bd993e8ec54ec5b04197f2 (patch)
tree823862dd9602abdc6329fa2385f3384db8e0f933
parenta93e253103a222063d71c1628d0ac7729de813ca (diff)
2.5
Vertex Paint back! Added WM level "paint cursor" system, which manages a custom painting cursor for tools or modes. - Activate it with WM_paint_cursor_activate(). That function wants two callbacks, a poll(C) to check whether there's a cursor in given context and ARegion, and a draw(C, x, y) which gets called when appropriate. - While paintcursor is active, the WM handles necessary redrawing events for all regions, also to nicely clear the cursor on region exit. - WM_paint_cursor_activate returns a handle, which you have to use to end the paint cursor. This handle also means you can register as many custom cursors as you want. At the moment, vertex paint mode registers only a mousemove handler, all other events are still normally handled. This is stuff for the future todo.
-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 *);