Stroke code:
authorAntony Riakiotakis <kalast@gmail.com>
Sat, 18 May 2013 09:44:30 +0000 (09:44 +0000)
committerAntony Riakiotakis <kalast@gmail.com>
Sat, 18 May 2013 09:44:30 +0000 (09:44 +0000)
* Fix crash on 2d painting when no active object is present (NULL
pointer dereference in cursor drawing)
* Skip conditional on space_stroke function, since this is already
checked for on higher level.
* Interpolate pressure on spaced strokes.

source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_stroke.c

index 8574d6b8a8f8eff05b4ac3d117b8fdbfee3a8436..107ff9668f0125ee0ec1b55df96b3dcc2827e3c9 100644 (file)
@@ -809,7 +809,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
 
        /* TODO: as sculpt and other paint modes are unified, this
         * special mode of drawing will go away */
-       if (vc.obact->sculpt) {
+       if (vc.obact && vc.obact->sculpt) {
                float location[3];
                int pixel_radius, hit;
 
index d3cb53c94fc0332d842735d6f08065a667da3d54..0ff09ddbb8f25590f4c6f1afd63529509cef3a03 100644 (file)
@@ -94,9 +94,14 @@ typedef struct PaintStroke {
        
        bool brush_init;
        float initial_mouse[2];
+       /* cached_pressure stores initial pressure for size pressure influence mainly */
        float cached_pressure;
+       /* last pressure will store last pressure value for use in interpolation for space strokes */
+       float last_pressure;
+
 
        float zoom_2d;
+       int pen_flip;
 
        StrokeGetLocation get_location;
        StrokeTestStart test_start;
@@ -253,7 +258,7 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
 
 
 /* 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, const wmEvent *event, const float mouse_in[2])
+static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
 {
        Scene *scene = CTX_data_scene(C);
        wmWindow *window = CTX_wm_window(C);
@@ -265,11 +270,6 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const wmEve
        float mouse_out[2];
        PointerRNA itemptr;
        float location[3];
-       float pressure;
-       int pen_flip;
-
-       /* see if tablet affects event */
-       pressure = event_tablet_data(event, &pen_flip);
 
 /* the following code is adapted from texture paint. It may not be needed but leaving here
  * just in case for reference (code in texpaint removed as part of refactoring).
@@ -323,7 +323,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const wmEve
 
        RNA_float_set_array(&itemptr, "location", location);
        RNA_float_set_array(&itemptr, "mouse", mouse_out);
-       RNA_boolean_set(&itemptr, "pen_flip", pen_flip);
+       RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
        RNA_float_set(&itemptr, "pressure", pressure);
 
        stroke->update_step(C, stroke, &itemptr);
@@ -364,63 +364,64 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
 
 /* For brushes with stroke spacing enabled, moves mouse in steps
  * towards the final mouse location. */
-static int paint_space_stroke(bContext *C, wmOperator *op, const wmEvent *event, const float final_mouse[2])
+static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mouse[2], float pressure)
 {
        PaintStroke *stroke = op->customdata;
-       PaintMode mode = BKE_paintmode_get_active_from_context(C);
 
        int cnt = 0;
 
-       if (paint_space_stroke_enabled(stroke->brush, mode)) {
-               float mouse[2];
-               float vec[2];
-               float length, scale;
-
-               copy_v2_v2(mouse, stroke->last_mouse_position);
-               sub_v2_v2v2(vec, final_mouse, mouse);
-
-               length = len_v2(vec);
-
-               if (length > FLT_EPSILON) {
-                       const Scene *scene = CTX_data_scene(C);
-                       int steps;
-                       int i;
-                       float size_pressure = 1.0f;
-                       float pressure = event_tablet_data(event, NULL);
-
-                       /* XXX mysterious :) what has 'use size' do with this here... if you don't check for it, pressure fails */
-                       if (BKE_brush_use_size_pressure(scene, stroke->brush))
-                               size_pressure = pressure;
-                       
-                       if (size_pressure > FLT_EPSILON) {
-                               /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
-                                * causing very high step sizes, hanging blender [#32381] */
-                               const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
-                               float spacing = stroke->brush->spacing;
-
-                               /* stroke system is used for 2d paint too, so we need to account for
+       float mouse[2];
+       float vec[2];
+       float length, scale;
+
+       copy_v2_v2(mouse, stroke->last_mouse_position);
+       sub_v2_v2v2(vec, final_mouse, mouse);
+
+       length = len_v2(vec);
+
+       if (length > FLT_EPSILON) {
+               const Scene *scene = CTX_data_scene(C);
+               int steps;
+               int i;
+               float size_pressure = 1.0f;
+
+               /* XXX mysterious :) what has 'use size' do with this here... if you don't check for it, pressure fails */
+               if (BKE_brush_use_size_pressure(scene, stroke->brush))
+                       size_pressure = pressure;
+
+               if (size_pressure > FLT_EPSILON) {
+                       /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
+                        * causing very high step sizes, hanging blender [#32381] */
+                       const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
+                       float spacing = stroke->brush->spacing;
+
+                       /* stroke system is used for 2d paint too, so we need to account for
                                 * the fact that brush can be scaled there. */
 
-                               if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
-                                       spacing = max_ff(1.0f, spacing * (1.5f - pressure));
+                       if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
+                               spacing = max_ff(1.0f, spacing * (1.5f - pressure));
 
-                               spacing *= stroke->zoom_2d;
+                       spacing *= stroke->zoom_2d;
 
-                               scale = (size_clamp * spacing / 50.0f) / length;
-                               if (scale > FLT_EPSILON) {
-                                       mul_v2_fl(vec, scale);
+                       scale = (size_clamp * spacing / 50.0f) / length;
+                       if (scale > FLT_EPSILON) {
+                               float pressure_diff = (pressure - stroke->last_pressure)*scale;
+                               float final_pressure = stroke->last_pressure;
+                               mul_v2_fl(vec, scale);
 
-                                       steps = (int)(1.0f / scale);
+                               steps = (int)(1.0f / scale);
 
-                                       for (i = 0; i < steps; ++i, ++cnt) {
-                                               add_v2_v2(mouse, vec);
-                                               paint_brush_stroke_add_step(C, op, event, mouse);
-                                       }
+                               for (i = 0; i < steps; ++i, ++cnt) {
+                                       final_pressure += pressure_diff;
+                                       add_v2_v2(mouse, vec);
+                                       paint_brush_stroke_add_step(C, op, mouse, final_pressure);
                                }
                        }
                }
        }
 
+       stroke->last_pressure = pressure;
+
        return cnt;
 }
 
@@ -624,6 +625,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
        int first = 0;
        float zoomx, zoomy;
        bool redraw = false;
+       float pressure;
 
        paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1]);
        paint_stroke_sample_average(stroke, &sample_average);
@@ -631,6 +633,9 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
        get_imapaint_zoom(C, &zoomx, &zoomy);
        stroke->zoom_2d = max_ff(zoomx, zoomy);
 
+       /* see if tablet affects event */
+       pressure = event_tablet_data(event, &stroke->pen_flip);
+
        /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
         * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
         * since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -642,6 +647,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
                copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
                stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
                BLI_assert((stroke->stroke_started & ~1) == 0);  /* 0/1 */
+               stroke->last_pressure = pressure;
 
                if (stroke->stroke_started) {
                        stroke->smooth_stroke_cursor =
@@ -674,11 +680,11 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
                if (stroke->stroke_started) {
                        if (paint_smooth_stroke(stroke, mouse, &sample_average, mode)) {
                                if (paint_space_stroke_enabled(stroke->brush, mode)) {
-                                       if (paint_space_stroke(C, op, event, mouse))
+                                       if (paint_space_stroke(C, op, mouse, pressure))
                                                redraw = true;
                                }
                                else {
-                                       paint_brush_stroke_add_step(C, op, event, mouse);
+                                       paint_brush_stroke_add_step(C, op, mouse, pressure);
                                        redraw = true;
                                }
                        }
@@ -693,7 +699,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
            !(stroke->brush->flag & BRUSH_ANCHORED) &&
            !(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
        {
-               paint_brush_stroke_add_step(C, op, event, mouse);
+               paint_brush_stroke_add_step(C, op, mouse, pressure);
                redraw = true;
        }