diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_stroke.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_stroke.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 210cffcbcda..88e7a786a47 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -79,6 +79,8 @@ typedef struct PaintStroke { float last_mouse_position[2]; float last_world_space_position[3]; + float last_scene_spacing_delta[3]; + bool stroke_over_mesh; /* space distance covered so far */ float stroke_distance; @@ -120,6 +122,8 @@ typedef struct PaintStroke { StrokeUpdateStep update_step; StrokeRedraw redraw; StrokeDone done; + + bool original; /* Raycast original mesh at start of stroke */ } PaintStroke; /*** Cursors ***/ @@ -243,6 +247,11 @@ static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode) return false; } +static bool paint_tool_raycast_original(Brush *brush, ePaintMode UNUSED(mode)) +{ + return brush->flag & BRUSH_ANCHORED; +} + static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode) { if (brush->flag & BRUSH_ANCHORED) { @@ -392,7 +401,7 @@ static bool paint_brush_update(bContext *C, halfway[1] = dy * 0.5f + stroke->initial_mouse[1]; if (stroke->get_location) { - if (stroke->get_location(C, r_location, halfway)) { + if (stroke->get_location(C, r_location, halfway, stroke->original)) { hit = true; location_sampled = true; location_success = true; @@ -466,7 +475,7 @@ static bool paint_brush_update(bContext *C, if (!location_sampled) { if (stroke->get_location) { - if (stroke->get_location(C, r_location, mouse)) { + if (stroke->get_location(C, r_location, mouse, stroke->original)) { location_success = true; *r_location_is_set = true; } @@ -506,7 +515,7 @@ static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert) /* 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, PaintStroke *stroke, const float mouse_in[2], float pressure) + bContext *C, wmOperator *op, PaintStroke *stroke, const float mval[2], float pressure) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); @@ -546,12 +555,20 @@ static void paint_brush_stroke_add_step( /* copy last position -before- jittering, or space fill code * will create too many dabs */ - copy_v2_v2(stroke->last_mouse_position, mouse_in); + copy_v2_v2(stroke->last_mouse_position, mval); stroke->last_pressure = pressure; if (paint_stroke_use_scene_spacing(brush, mode)) { - SCULPT_stroke_get_location(C, stroke->last_world_space_position, stroke->last_mouse_position); - mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); + float world_space_position[3]; + + if (SCULPT_stroke_get_location( + C, world_space_position, stroke->last_mouse_position, stroke->original)) { + copy_v3_v3(stroke->last_world_space_position, world_space_position); + mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); + } + else { + add_v3_v3(stroke->last_world_space_position, stroke->last_scene_spacing_delta); + } } if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) { @@ -562,24 +579,24 @@ static void paint_brush_stroke_add_step( factor *= pressure; } - BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out); + BKE_brush_jitter_pos(scene, brush, mval, mouse_out); /* XXX: meh, this is round about because * BKE_brush_jitter_pos isn't written in the best way to * be reused here */ if (factor != 1.0f) { - sub_v2_v2v2(delta, mouse_out, mouse_in); + sub_v2_v2v2(delta, mouse_out, mval); mul_v2_fl(delta, factor); - add_v2_v2v2(mouse_out, mouse_in, delta); + add_v2_v2v2(mouse_out, mval, delta); } } else { - copy_v2_v2(mouse_out, mouse_in); + copy_v2_v2(mouse_out, mval); } bool is_location_is_set; ups->last_hit = paint_brush_update( - C, brush, mode, stroke, mouse_in, mouse_out, pressure, location, &is_location_is_set); + C, brush, mode, stroke, mval, mouse_out, pressure, location, &is_location_is_set); if (is_location_is_set) { copy_v3_v3(ups->last_location, location); } @@ -605,7 +622,7 @@ static void paint_brush_stroke_add_step( /* Mouse coordinates modified by the stroke type options. */ RNA_float_set_array(&itemptr, "mouse", mouse_out); /* Original mouse coordinates. */ - RNA_float_set_array(&itemptr, "mouse_event", mouse_in); + RNA_float_set_array(&itemptr, "mouse_event", mval); RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip); RNA_float_set(&itemptr, "pressure", pressure); RNA_float_set(&itemptr, "x_tilt", stroke->x_tilt); @@ -698,7 +715,7 @@ static float paint_space_stroke_spacing(bContext *C, spacing *= stroke->zoom_2d; if (paint_stroke_use_scene_spacing(brush, mode)) { - return max_ff(0.001f, size_clamp * spacing / 50.0f); + return size_clamp * spacing / 50.0f; } return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f); } @@ -807,7 +824,7 @@ static int paint_space_stroke(bContext *C, if (use_scene_spacing) { float world_space_position[3]; - bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse); + bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse, stroke->original); mul_m4_v3(stroke->vc.obact->obmat, world_space_position); if (hit && stroke->stroke_over_mesh) { sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position); @@ -838,6 +855,8 @@ static int paint_space_stroke(bContext *C, stroke->last_world_space_position, final_world_space_position); ED_view3d_project_v2(region, final_world_space_position, mouse); + + mul_v3_v3fl(stroke->last_scene_spacing_delta, d_world_space_position, spacing); } else { mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing; @@ -896,6 +915,8 @@ PaintStroke *paint_stroke_new(bContext *C, stroke->ups = ups; stroke->stroke_mode = RNA_enum_get(op->ptr, "mode"); + stroke->original = paint_tool_raycast_original(br, BKE_paintmode_get_active_from_context(C)); + get_imapaint_zoom(C, &zoomx, &zoomy); stroke->zoom_2d = max_ff(zoomx, zoomy); @@ -912,8 +933,13 @@ PaintStroke *paint_stroke_new(bContext *C, rv3d->rflag |= RV3D_PAINTING; } - zero_v3(ups->average_stroke_accum); - ups->average_stroke_counter = 0; + /* Preserve location from last stroke while applying and resetting + * ups->average_stroke_counter to 1. + */ + if (ups->average_stroke_counter) { + mul_v3_fl(ups->average_stroke_accum, 1.0f / (float)ups->average_stroke_counter); + ups->average_stroke_counter = 1; + } /* initialize here to avoid initialization conflict with threaded strokes */ BKE_curvemapping_init(br->curve); @@ -990,7 +1016,7 @@ static void stroke_done(bContext *C, wmOperator *op, PaintStroke *stroke) static bool curves_sculpt_brush_uses_spacing(const eBrushCurvesSculptTool tool) { - return ELEM(tool, CURVES_SCULPT_TOOL_ADD); + return ELEM(tool, CURVES_SCULPT_TOOL_ADD, CURVES_SCULPT_TOOL_DENSITY); } bool paint_space_stroke_enabled(Brush *br, ePaintMode mode) @@ -1186,8 +1212,10 @@ static void paint_line_strokes_spacing(bContext *C, copy_v2_v2(stroke->last_mouse_position, old_pos); if (use_scene_spacing) { - bool hit_old = SCULPT_stroke_get_location(C, world_space_position_old, old_pos); - bool hit_new = SCULPT_stroke_get_location(C, world_space_position_new, new_pos); + bool hit_old = SCULPT_stroke_get_location( + C, world_space_position_old, old_pos, stroke->original); + bool hit_new = SCULPT_stroke_get_location( + C, world_space_position_new, new_pos, stroke->original); mul_m4_v3(stroke->vc.obact->obmat, world_space_position_old); mul_m4_v3(stroke->vc.obact->obmat, world_space_position_new); if (hit_old && hit_new && stroke->stroke_over_mesh) { @@ -1331,7 +1359,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) { stroke->stroke_over_mesh = SCULPT_stroke_get_location( - C, stroke->last_world_space_position, data + 2 * j); + C, stroke->last_world_space_position, data + 2 * j, stroke->original); mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); } @@ -1463,7 +1491,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS copy_v2_v2(stroke->last_mouse_position, sample_average.mouse); if (paint_stroke_use_scene_spacing(br, mode)) { stroke->stroke_over_mesh = SCULPT_stroke_get_location( - C, stroke->last_world_space_position, sample_average.mouse); + C, stroke->last_world_space_position, sample_average.mouse, stroke->original); mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position); } stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse); |