diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_stroke.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_stroke.c | 86 |
1 files changed, 71 insertions, 15 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bb875d2ef00..d9d0d8f5ef6 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -122,6 +122,10 @@ typedef struct PaintStroke { float zoom_2d; int pen_flip; + + /* line constraint */ + bool constrain_line; + float constrained_pos[2]; StrokeGetLocation get_location; StrokeTestStart test_start; @@ -161,13 +165,25 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata) glColor4ub(0, 0, 0, paint->paint_cursor_col[3]); glLineWidth(3.0); - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - x, y); + if (stroke->constrain_line) { + sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], + stroke->constrained_pos[0], stroke->constrained_pos[1]); + } + else { + sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], + x, y); + } glColor4ub(255, 255, 255, paint->paint_cursor_col[3]); glLineWidth(1.0); - sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], - x, y); + if (stroke->constrain_line) { + sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], + stroke->constrained_pos[0], stroke->constrained_pos[1]); + } + else { + sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1], + x, y); + } glDisable(GL_LINE_STIPPLE); @@ -288,7 +304,7 @@ static bool paint_brush_update(bContext *C, ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy); - ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + M_PI; + ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI; if (brush->flag & BRUSH_EDGE_TO_EDGE) { halfway[0] = dx * 0.5f + stroke->initial_mouse[0]; @@ -654,10 +670,11 @@ PaintStroke *paint_stroke_new(bContext *C, get_imapaint_zoom(C, &zoomx, &zoomy); stroke->zoom_2d = max_ff(zoomx, zoomy); - if ((br->flag & BRUSH_CURVE) && - RNA_struct_property_is_set(op->ptr, "mode")) + if (stroke->stroke_mode == BRUSH_STROKE_INVERT) { - RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL); + if (br->flag & (BRUSH_CURVE | BRUSH_LINE)) { + RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL); + } } /* initialize here */ ups->overlap_factor = 1.0; @@ -996,6 +1013,34 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str return false; } +static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2]) +{ + if (stroke->constrain_line) { + float line[2]; + float angle, len, res; + + sub_v2_v2v2(line, mouse, stroke->last_mouse_position); + angle = atan2(line[1], line[0]); + len = len_v2(line); + + /* divide angle by PI/4 */ + angle = 4.0f * angle / (float)M_PI; + + /* now take residue */ + res = angle - floorf(angle); + + /* residue decides how close we are at a certain angle */ + if (res <= 0.5f) { + angle = floorf(angle) * (float)M_PI_4; + } + else { + angle = (floorf(angle) + 1.0f) * (float)M_PI_4; + } + + mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0]; + mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1]; + } +} int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -1069,7 +1114,9 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->type == stroke->event_type && !first_modal) { if (event->val == KM_RELEASE) { - paint_stroke_line_end (C, op, stroke, sample_average.mouse); + copy_v2_fl2(mouse, event->mval[0], event->mval[1]); + paint_stroke_line_constrain(stroke, mouse); + paint_stroke_line_end (C, op, stroke, mouse); stroke_done(C, op); return OPERATOR_FINISHED; } @@ -1079,13 +1126,22 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) stroke_done(C, op); return OPERATOR_FINISHED; } - else if ((br->flag & BRUSH_LINE) && stroke->stroke_started && - (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) - { - if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) { - copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position); + else if (br->flag & BRUSH_LINE) { + if (event->ctrl) + stroke->constrain_line = true; + else + stroke->constrain_line = false; + + copy_v2_fl2(mouse, event->mval[0], event->mval[1]); + paint_stroke_line_constrain(stroke, mouse); + + if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) + { + if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) { + copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position); + } + paint_calculate_rake_rotation(stroke->ups, br, mouse); } - paint_calculate_rake_rotation(stroke->ups, br, sample_average.mouse); } else if (first_modal || /* regular dabs */ |