2.5
authorTon Roosendaal <ton@blender.org>
Fri, 9 Jan 2009 13:55:45 +0000 (13:55 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 9 Jan 2009 13:55:45 +0000 (13:55 +0000)
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.

16 files changed:
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/object/object_edit.c
source/blender/editors/screen/area.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/vpaint.c
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/wm.h

index 042516e518e531a61f79438a8cdcdc3dda8b2579..ac0b819aa6b82b747998fd7a56d29d27b29c215f 100644 (file)
@@ -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;
        
index 7b3b31cbe3037b37aa171db88f94eb8f06a3a77a..60a5ff8481e7bab7e1d735bdae7a82712db23677 100644 (file)
@@ -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 */
 
index 2650bd96b39e9b170c4774ce306ea4a891c3515f..e3fa8b22463976df9f666c6eebbecda75d066cc3 100644 (file)
@@ -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;
 
index e2cafeceb9e257afb5f5c244d28a57a024354ba1..5aa8a5b466bf9cd08a99f5bcdc48006627c30aa0 100644 (file)
@@ -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;
 }
index 536ce9cee74bf8843767a56ba6471fc37ba1f71c..d78fdbbae6e21092f964bd4a3f99c3b940d19bd7 100644 (file)
@@ -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) {
index 3caa2d25da7f832c5a714e43f07d3573904bb7d7..d8025698f026f772b825c8356bb36e5b9816b42d 100644 (file)
@@ -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();
index d9d58b188ea2d85fec2b84af874a15cfc6a9d6b5..7fb17071e717b67c533c49c9ace1b29e6ec60205 100644 (file)
@@ -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);
index 73329ac5aa34b0c6b0d62b232582e65c49c6a783..da4b752f37030ce66ec2756c686f1176579afb0e 100644 (file)
@@ -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");
index e1cc1f65c15415de35f11065c853d35560bd9c02..6664ac1187730eb14520fc54c1ff44bd73d2085d 100644 (file)
@@ -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);
index df21b2de0967b095a1ed3a2bbbf8c6c2cba5b256..f253612259f9f5b6ae4d922dc317ba5d493be3fc 100644 (file)
@@ -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"
 #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;
+       
 }
 
+
index a563e2af210acc29fc58b5f1a619cb663de43200..5b1ffdd35f2da8163d7e44569668f850d2825df6 100644 (file)
@@ -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;
        
index 40a67c3c67a33fe733fb6fc542a3b9b3ce71ddf8..c4cd6d655a3b3d8762c473aa6e46a4b7d318ae18 100644 (file)
@@ -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);
index 1533cc636db7566763b92e035d3da076c751ef2a..f76bfb511b389470f5c99065c2d6e985562b49cd 100644 (file)
@@ -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);
 }
 
index 046fbdefb646d804c626838bd0926fea0acae897..161ab66f3fdc31ff59c3035523818afa434817c2 100644 (file)
@@ -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)
 {
@@ -798,11 +818,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;
@@ -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);
                }
        }
 }
index 92a233d1067ed5ddaf017dd1ccc942f848f72610..a2eefad05a5687b70ef9bb873554e024042679ef 100644 (file)
@@ -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)
 {
index 1835a47532393464a6e3743a34c7d9038230bd04..c063226b96f8c1d6c5717f6520d3a36ab9066638 100644 (file)
 
 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 *);