soc-2008-mxcurioni: merged changes to revision 23516
[blender.git] / source / blender / editors / sculpt_paint / paint_stroke.c
index 634b82674b5272612ea756d50016bf16e9d90271..b83352ae70cc1155230ca21221a5a0962539492b 100644 (file)
@@ -43,6 +43,9 @@
 
 #include "BLI_arithb.h"
 
+#include "PIL_time.h"
+
+#include "BIF_gl.h"
 #include "BIF_glutil.h"
 
 #include "ED_screen.h"
 #include <math.h>
 
 typedef struct PaintStroke {
+       void *mode_data;
+       void *smooth_stroke_cursor;
+       wmTimer *timer;
+
        /* Cached values */
        ViewContext vc;
        bglMats mats;
@@ -71,6 +78,42 @@ typedef struct PaintStroke {
        StrokeDone done;
 } PaintStroke;
 
+/*** Cursor ***/
+static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata) 
+{
+       Brush *brush = paint_brush(paint_get_active(CTX_data_scene(C)));
+       PaintStroke *stroke = customdata;
+
+       glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
+       glEnable(GL_LINE_SMOOTH);
+       glEnable(GL_BLEND);
+
+       if(stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
+               ARegion *ar = CTX_wm_region(C);
+               sdrawline(x, y, (int)stroke->last_mouse_position[0] - ar->winrct.xmin,
+                         (int)stroke->last_mouse_position[1] - ar->winrct.ymin);
+       }
+
+       glDisable(GL_BLEND);
+       glDisable(GL_LINE_SMOOTH);
+}
+
+static void paint_draw_cursor(bContext *C, int x, int y, void *customdata)
+{
+       Brush *brush = paint_brush(paint_get_active(CTX_data_scene(C)));
+
+       glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
+       glEnable(GL_LINE_SMOOTH);
+       glEnable(GL_BLEND);
+
+       glTranslatef((float)x, (float)y, 0.0f);
+       glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+       glTranslatef((float)-x, (float)-y, 0.0f);
+
+       glDisable(GL_BLEND);
+       glDisable(GL_LINE_SMOOTH);
+}
+
 /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
 static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse[2])
 {
@@ -187,10 +230,22 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
        PaintStroke *stroke = op->customdata;
        float mouse[2];
 
+       if(event->type == TIMER && (event->customdata != stroke->timer))
+               return OPERATOR_RUNNING_MODAL;
+
        if(!stroke->stroke_started) {
                stroke->last_mouse_position[0] = event->x;
                stroke->last_mouse_position[1] = event->y;
                stroke->stroke_started = stroke->test_start(C, op, event);
+
+               if(stroke->stroke_started) {
+                       stroke->smooth_stroke_cursor =
+                               WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
+
+                       if(stroke->brush->flag & BRUSH_AIRBRUSH)
+                               stroke->timer = WM_event_add_window_timer(CTX_wm_window(C), TIMER, stroke->brush->rate);
+               }
+
                ED_region_tag_redraw(ar);
        }
 
@@ -208,7 +263,15 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
        }
 
        /* TODO: fix hardcoded event here */
-       if(event->type == LEFTMOUSE && event->val == 0) {
+       if(event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+               /* Exit stroke, free data */
+
+               if(stroke->smooth_stroke_cursor)
+                       WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
+
+               if(stroke->timer)
+                       WM_event_remove_window_timer(CTX_wm_window(C), stroke->timer);
+
                stroke->done(C, stroke);
                MEM_freeN(stroke);
                return OPERATOR_FINISHED;
@@ -217,8 +280,51 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
                return OPERATOR_RUNNING_MODAL;
 }
 
+int paint_stroke_exec(bContext *C, wmOperator *op)
+{
+       PaintStroke *stroke = op->customdata;
+
+       RNA_BEGIN(op->ptr, itemptr, "stroke") {
+               stroke->update_step(C, stroke, &itemptr);
+       }
+       RNA_END;
+
+       MEM_freeN(stroke);
+       op->customdata = NULL;
+
+       return OPERATOR_FINISHED;
+}
+
 ViewContext *paint_stroke_view_context(PaintStroke *stroke)
 {
        return &stroke->vc;
 }
 
+void *paint_stroke_mode_data(struct PaintStroke *stroke)
+{
+       return stroke->mode_data;
+}
+
+void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
+{
+       stroke->mode_data = mode_data;
+}
+
+int paint_poll(bContext *C)
+{
+       Paint *p = paint_get_active(CTX_data_scene(C));
+       Object *ob = CTX_data_active_object(C);
+
+       return p && ob && paint_brush(p) &&
+               CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
+               CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
+}
+
+void paint_cursor_start(bContext *C, int (*poll)(bContext *C))
+{
+       Paint *p = paint_get_active(CTX_data_scene(C));
+
+       if(p && !p->paint_cursor)
+               p->paint_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), poll, paint_draw_cursor, NULL);
+}
+