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).
This commit is contained in:
Bill Kendrick 2023-03-06 01:07:13 -08:00
parent 36eb2ea70c
commit e913709362
2 changed files with 113 additions and 45 deletions

View file

@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt)
https://tuxpaint.org/ https://tuxpaint.org/
2023.March.3 (0.9.29) 2023.March.6 (0.9.29)
* Improvements to "Stamp" tool: * Improvements to "Stamp" tool:
----------------------------- -----------------------------
* Stamps may now be rotated. * Stamps may now be rotated.
@ -100,6 +100,18 @@ https://tuxpaint.org/
(Based on http://www.codersnotes.com/notes/signed-distance-fields/ (Based on http://www.codersnotes.com/notes/signed-distance-fields/
by Richard Mitton) by Richard Mitton)
* Improvements to Shape tool:
---------------------------
* Rotation of corner-stretched shapes are around their center,
rather than orbiting a corner.
Bill Kendrick <bill@newbreedsofware.com>
* 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 <bill@newbreedsofware.com>
* Improvements to Color selection: * Improvements to Color selection:
-------------------------------- --------------------------------
* The rainbow palette color picker allows you to switch to the * The rainbow palette color picker allows you to switch to the

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt) (See COPYING.txt)
June 14, 2002 - March 3, 2023 June 14, 2002 - March 6, 2023
*/ */
#include "platform.h" #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, 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_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 num_things;
int *thing_scroll; int *thing_scroll;
int do_draw; int do_draw;
@ -2651,6 +2651,8 @@ static void mainloop(void)
shape_start_y = 0; shape_start_y = 0;
shape_current_x = 0; shape_current_x = 0;
shape_current_y = 0; shape_current_y = 0;
shape_ctr_x = 0;
shape_ctr_y = 0;
shape_tool_mode = SHAPE_TOOL_MODE_DONE; shape_tool_mode = SHAPE_TOOL_MODE_DONE;
stamp_tool_mode = STAMP_TOOL_MODE_PLACE; stamp_tool_mode = STAMP_TOOL_MODE_PLACE;
button_down = 0; button_down = 0;
@ -5216,7 +5218,7 @@ static void mainloop(void)
{ {
cur_shape = cur_thing; 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) if (shape_tool_mode != SHAPE_TOOL_MODE_DONE)
{ {
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_x = old_x;
shape_start_y = old_y; shape_start_y = old_y;
shape_ctr_x = old_x;
shape_ctr_y = old_y;
shape_tool_mode = SHAPE_TOOL_MODE_STRETCH; 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, playsound(screen, 1, SND_LINE_END, 1, event.button.x,
SNDDIST_NEAR); SNDDIST_NEAR);
do_shape(shape_start_x, shape_start_y, shape_current_x, do_shape(shape_start_x, shape_start_y, shape_current_x,
shape_current_y, shape_rotation(shape_start_x, shape_current_y, shape_rotation(shape_ctr_x,
shape_start_y, shape_ctr_y,
event.button.x - event.button.x -
r_canvas.x, r_canvas.x,
event.button.y - event.button.y -
@ -6348,6 +6352,14 @@ static void mainloop(void)
shape_current_x = event.button.x - r_canvas.x; shape_current_x = event.button.x - r_canvas.x;
shape_current_y = event.button.y - r_canvas.y; 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]) if (!simple_shapes && !shape_no_rotate[cur_shape])
{ {
shape_tool_mode = SHAPE_TOOL_MODE_ROTATE; shape_tool_mode = SHAPE_TOOL_MODE_ROTATE;
@ -6359,7 +6371,7 @@ static void mainloop(void)
shape_current_y) * (shape_start_y - shape_current_y) * (shape_start_y -
shape_current_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); do_setcursor(cursor_rotate);
@ -6374,7 +6386,7 @@ static void mainloop(void)
do_shape(shape_start_x, shape_start_y, do_shape(shape_start_x, shape_start_y,
shape_current_x, shape_current_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), shape_current_x, shape_current_y),
0); 0);
@ -6413,8 +6425,8 @@ static void mainloop(void)
playsound(screen, 1, SND_LINE_END, 1, event.button.x, playsound(screen, 1, SND_LINE_END, 1, event.button.x,
SNDDIST_NEAR); SNDDIST_NEAR);
do_shape(shape_start_x, shape_start_y, shape_current_x, do_shape(shape_start_x, shape_start_y, shape_current_x,
shape_current_y, shape_rotation(shape_start_x, shape_current_y, shape_rotation(shape_ctr_x,
shape_start_y, shape_ctr_y,
event.button.x - event.button.x -
r_canvas.x, r_canvas.x,
event.button.y - event.button.y -
@ -7216,11 +7228,11 @@ static void mainloop(void)
{ {
int deg; 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, do_shape(shape_start_x, shape_start_y, shape_current_x,
shape_current_y, deg, 0); 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, do_shape(shape_start_x, shape_start_y, shape_current_x,
shape_current_y, deg, 0); 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; 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; float a1, a2, rotn_rad, init_ang, angle_skip;
int xx, yy, offx, offy, max_x, max_y; 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: */ /* 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; rotn_rad = rotn * M_PI / 180;
xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); if (shape_mode == SHAPEMODE_CENTER) {
yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); 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; x1 = xp;
y1 = yp - offy; 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); xv = xp;
yp = (x2 + offx) * sin(rotn_rad) + (y2 + offy) * cos(rotn_rad); yv = yp;
}
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;
} }
/* Center the line around the center of the shape: */ /* Center the line around the center of the shape: */
x1 = x1 + sx + offx; 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; rotn_rad = rotn * M_PI / 180;
xp = (x1 + offx) * cos(rotn_rad) - (y1 + offy) * sin(rotn_rad); if (shape_mode == SHAPEMODE_CENTER) {
yp = (x1 + offx) * sin(rotn_rad) + (y1 + offy) * cos(rotn_rad); 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; 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); 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; 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); 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 - 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;
}
} }