From e913709362bb0d3b97acfa781861830e052cb5f1 Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Mon, 6 Mar 2023 01:07:13 -0800 Subject: [PATCH] Shape tool improvements More sensible rotation when using the drag-from-corner mode (rotates around center of the shape, as you'd expect, rather than around one of the corners of the shape's bounding box, as it has been doing all this time). Stretching a shape from bottom to top causes an upside-down shape (e.g., before, a triangle would always start out up-pointing regardless as to whether you clicked and drag downwards or upwards; now, it will start out down-pointing if you drag upwards when initially placing & stretching the shape). --- docs/CHANGES.txt | 14 ++++- src/tuxpaint.c | 144 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 113 insertions(+), 45 deletions(-) diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 62500bbb4..6a2689216 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt) https://tuxpaint.org/ -2023.March.3 (0.9.29) +2023.March.6 (0.9.29) * Improvements to "Stamp" tool: ----------------------------- * Stamps may now be rotated. @@ -100,6 +100,18 @@ https://tuxpaint.org/ (Based on http://www.codersnotes.com/notes/signed-distance-fields/ by Richard Mitton) + * Improvements to Shape tool: + --------------------------- + * Rotation of corner-stretched shapes are around their center, + rather than orbiting a corner. + Bill Kendrick + + * Stretching a shape upwards rotates it 180-degrees + (e.g., stretching the triangle downwards makes an up-pointing + triangle (^), as before; but stretching it upwards now makes + a down-pointing triangle (v)) + Bill Kendrick + * Improvements to Color selection: -------------------------------- * The rainbow palette color picker allows you to switch to the diff --git a/src/tuxpaint.c b/src/tuxpaint.c index 05b0f2090..d8f356e5e 100644 --- a/src/tuxpaint.c +++ b/src/tuxpaint.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (See COPYING.txt) - June 14, 2002 - March 3, 2023 + June 14, 2002 - March 6, 2023 */ #include "platform.h" @@ -2592,7 +2592,7 @@ static void mainloop(void) { int done, val_x, val_y, valhat_x, valhat_y, new_x, new_y, shape_tool_mode, shape_start_x, shape_start_y, shape_current_x, - shape_current_y, old_stamp_group, which; + shape_current_y, shape_ctr_x, shape_ctr_y, old_stamp_group, which; int num_things; int *thing_scroll; int do_draw; @@ -2651,6 +2651,8 @@ static void mainloop(void) shape_start_y = 0; shape_current_x = 0; shape_current_y = 0; + shape_ctr_x = 0; + shape_ctr_y = 0; shape_tool_mode = SHAPE_TOOL_MODE_DONE; stamp_tool_mode = STAMP_TOOL_MODE_PLACE; button_down = 0; @@ -5216,7 +5218,7 @@ static void mainloop(void) { cur_shape = cur_thing; - /* Remove ghost previews an reset the tool */ + /* Remove ghost previews and reset the tool */ if (shape_tool_mode != SHAPE_TOOL_MODE_DONE) { shape_tool_mode = SHAPE_TOOL_MODE_DONE; @@ -5502,6 +5504,8 @@ static void mainloop(void) shape_start_x = old_x; shape_start_y = old_y; + shape_ctr_x = old_x; + shape_ctr_y = old_y; shape_tool_mode = SHAPE_TOOL_MODE_STRETCH; @@ -5525,8 +5529,8 @@ static void mainloop(void) playsound(screen, 1, SND_LINE_END, 1, event.button.x, SNDDIST_NEAR); do_shape(shape_start_x, shape_start_y, shape_current_x, - shape_current_y, shape_rotation(shape_start_x, - shape_start_y, + shape_current_y, shape_rotation(shape_ctr_x, + shape_ctr_y, event.button.x - r_canvas.x, event.button.y - @@ -6348,6 +6352,14 @@ static void mainloop(void) shape_current_x = event.button.x - r_canvas.x; shape_current_y = event.button.y - r_canvas.y; + if (shape_mode == SHAPEMODE_CENTER) { + shape_ctr_x = shape_start_x; + shape_ctr_y = shape_start_y; + } else { + shape_ctr_x = shape_start_x + (shape_current_x - shape_start_x) / 2; + shape_ctr_y = shape_start_y + (shape_current_y - shape_start_y) / 2; + } + if (!simple_shapes && !shape_no_rotate[cur_shape]) { shape_tool_mode = SHAPE_TOOL_MODE_ROTATE; @@ -6359,7 +6371,7 @@ static void mainloop(void) shape_current_y) * (shape_start_y - shape_current_y)); - SDL_WarpMouse(shape_current_x + r_ttools.w, shape_start_y); + SDL_WarpMouse(shape_ctr_x + (shape_current_x - shape_ctr_x) * 1.05 + r_canvas.x, shape_ctr_y + r_canvas.y); do_setcursor(cursor_rotate); @@ -6374,7 +6386,7 @@ static void mainloop(void) do_shape(shape_start_x, shape_start_y, shape_current_x, shape_current_y, - shape_rotation(shape_start_x, shape_start_y, + shape_rotation(shape_ctr_x, shape_ctr_y, shape_current_x, shape_current_y), 0); @@ -6413,8 +6425,8 @@ static void mainloop(void) playsound(screen, 1, SND_LINE_END, 1, event.button.x, SNDDIST_NEAR); do_shape(shape_start_x, shape_start_y, shape_current_x, - shape_current_y, shape_rotation(shape_start_x, - shape_start_y, + shape_current_y, shape_rotation(shape_ctr_x, + shape_ctr_y, event.button.x - r_canvas.x, event.button.y - @@ -7216,11 +7228,11 @@ static void mainloop(void) { int deg; - deg = shape_rotation(shape_start_x, shape_start_y, old_x, old_y); + deg = shape_rotation(shape_ctr_x, shape_ctr_y, old_x, old_y); do_shape(shape_start_x, shape_start_y, shape_current_x, shape_current_y, deg, 0); - deg = shape_rotation(shape_start_x, shape_start_y, new_x, new_y); + deg = shape_rotation(shape_ctr_x, shape_ctr_y, new_x, new_y); do_shape(shape_start_x, shape_start_y, shape_current_x, shape_current_y, deg, 0); @@ -16016,7 +16028,12 @@ static void do_shape(int sx, int sy, int nx, int ny, int rotn, int use_brush) int side, rx, ry, rmax, x1, y1, x2, y2, xp, yp, xv, yv, old_brush, step; float a1, a2, rotn_rad, init_ang, angle_skip; int xx, yy, offx, offy, max_x, max_y; + int upsidedown = 0; + if (ny < sy) { + upsidedown = 1; + rotn = (rotn + 180) % 360; + } /* Determine radius/shape of the shape to draw: */ @@ -16166,26 +16183,45 @@ static void do_shape(int sx, int sy, int nx, int ny, int rotn, int use_brush) { rotn_rad = rotn * M_PI / 180; - xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); - yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); + if (shape_mode == SHAPEMODE_CENTER) { + xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); + yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); + + x1 = xp - offx; + y1 = yp - offy; + + xp = (x2 + offx) * cos(rotn_rad) - (y2 + offy) * sin(rotn_rad); + yp = (x2 + offx) * sin(rotn_rad) + (y2 + offy) * cos(rotn_rad); + + x2 = xp - offx; + y2 = yp - offy; + + xp = (xv + offx) * cos(rotn_rad) - (yv + offy) * sin(rotn_rad); + yp = (xv + offx) * sin(rotn_rad) + (yv + offy) * cos(rotn_rad); + + xv = xp - offx; + yv = yp - offy; + } else { + xp = x1 * cos(rotn_rad) - y1 * sin(rotn_rad); + yp = x1 * sin(rotn_rad) + y1 * cos(rotn_rad); - x1 = xp - offx; - y1 = yp - offy; + x1 = xp; + y1 = yp; + + xp = x2 * cos(rotn_rad) - y2 * sin(rotn_rad); + yp = x2 * sin(rotn_rad) + y2 * cos(rotn_rad); + + x2 = xp; + y2 = yp; + + xp = xv * cos(rotn_rad) - yv * sin(rotn_rad); + yp = xv * sin(rotn_rad) + yv * cos(rotn_rad); - xp = (x2 + offx) * cos(rotn_rad) - (y2 + offy) * sin(rotn_rad); - yp = (x2 + offx) * sin(rotn_rad) + (y2 + offy) * cos(rotn_rad); - - x2 = xp - offx; - y2 = yp - offy; - - xp = (xv + offx) * cos(rotn_rad) - (yv + offy) * sin(rotn_rad); - yp = (xv + offx) * sin(rotn_rad) + (yv + offy) * cos(rotn_rad); - - xv = xp - offx; - yv = yp - offy; + xv = xp; + yv = yp; + } } - /* Center the line around the center of the shape: */ x1 = x1 + sx + offx; @@ -16271,23 +16307,43 @@ static void do_shape(int sx, int sy, int nx, int ny, int rotn, int use_brush) { rotn_rad = rotn * M_PI / 180; - xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); - yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); - - x1 = xp - offx; - y1 = yp - offy; - - xp = (x2 + offx) * cos(rotn_rad) - (y2 + offy) * sin(rotn_rad); - yp = (x2 + offx) * sin(rotn_rad) + (y2 + offy) * cos(rotn_rad); - - x2 = xp - offx; - y2 = yp - offy; - - xp = (xv + offx) * cos(rotn_rad) - (yv + offy) * sin(rotn_rad); - yp = (xv + offx) * sin(rotn_rad) + (yv + offy) * cos(rotn_rad); - - xv = xp - offx; - yv = yp - offy; + if (shape_mode == SHAPEMODE_CENTER) { + xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); + yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); + + x1 = xp - offx; + y1 = yp - offy; + + xp = (x2 + offx) * cos(rotn_rad) - (y2 + offy) * sin(rotn_rad); + yp = (x2 + offx) * sin(rotn_rad) + (y2 + offy) * cos(rotn_rad); + + x2 = xp - offx; + y2 = yp - offy; + + xp = (xv + offx) * cos(rotn_rad) - (yv + offy) * sin(rotn_rad); + yp = (xv + offx) * sin(rotn_rad) + (yv + offy) * cos(rotn_rad); + + xv = xp - offx; + yv = yp - offy; + } else { + xp = x1 * cos(rotn_rad) - y1 * sin(rotn_rad); + yp = x1 * sin(rotn_rad) + y1 * cos(rotn_rad); + + x1 = xp; + y1 = yp; + + xp = x2 * cos(rotn_rad) - y2 * sin(rotn_rad); + yp = x2 * sin(rotn_rad) + y2 * cos(rotn_rad); + + x2 = xp; + y2 = yp; + + xp = xv * cos(rotn_rad) - yv * sin(rotn_rad); + yp = xv * sin(rotn_rad) + yv * cos(rotn_rad); + + xv = xp; + yv = yp; + } }