api->retract_undo() added to Magic API; used by Filled Polygon

New API function which rolls back the Undo buffer (which is snapshotted
upon a mousedown event ahead of calling the Magic tool's `_click()`
function.)  Dangerous; use sparingly!

Filled Polygon uses this to prevent partially-created (aka unfinished
aka incomplete) polygons -- the preview lines and control points -- from
being recorded and wasting space in the Undo history, or reappearing
upon Redo.

TODO - Other tools (e.g., Clone) would certainly benefit from this.
TODO - Needs more testing to help identify any bugs/issues introduced
by this!
TODO - Magic API docs need updating.

This is probably a sufficient solution that will make
https://sourceforge.net/p/tuxpaint/feature-requests/246/,
'"Overlay" surface in Magic API', unnecessary.
This commit is contained in:
Bill Kendrick 2024-06-01 01:35:50 -07:00
parent 2e9f4b7f42
commit 01afb5846c
5 changed files with 63 additions and 20 deletions

View file

@ -4,7 +4,7 @@
# Various contributors (see AUTHORS.txt)
# https://tuxpaint.org/
# June 14, 2002 - February 29, 2024
# June 14, 2002 - June 1, 2024
# The version number, for release:
@ -24,7 +24,7 @@ else
VER_DATE=$(shell date "+%Y-%m-%d")
endif
MAGIC_API_VERSION:=0x00000009
MAGIC_API_VERSION:=0x0000000A
# Need to know the OS
SYSNAME:=$(shell uname -s)

View file

@ -6,7 +6,7 @@ Copyright (c) 2002-2024
Various contributors (see below, and AUTHORS.txt)
https://tuxpaint.org/
2024.May.30 (0.9.33)
2024.June.1 (0.9.33)
* New Magic Tools:
----------------
* Dither & Dither (Keep Color): Replaces all or part of a drawing
@ -42,6 +42,12 @@ https://tuxpaint.org/
+ Idea from O'Hare The Rabbit
+ Coding by Bill Kendrick <bill@newbreedsoftware.com>
* Ability for Magic tools to retract an undo buffer snapshot
(`api->retract_undo()`).
+ Used by new Filled Polygon magic tool.
+ Note: `TP_MAGIC_API_VERSION` bumped to 0x0000000A.
+ Bill Kendrick <bill@newbreedsoftware.com>
* Improvements to Eraser tool:
----------------------------
* Transparent erasers

View file

@ -7,7 +7,7 @@
Scanline polygon fill routine based on public-domain code
by Darel Rex Finley, 2007 <https://alienryderflex.com/polygon_fill/>
Last updated: May 30, 2024
Last updated: June 1, 2024
*/
@ -19,6 +19,9 @@
#include "SDL_image.h"
#include "SDL_mixer.h"
// #define DEBUG
enum
{
TOOL_POLYFILL,
@ -222,7 +225,7 @@ polyfill_click(magic_api * api, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_U
polyfill_dragged = 0;
#ifdef DEBUG
printf("Click. num_pts = %d\n", polyfill_num_pts);
printf("\nClick. num_pts = %d\n", polyfill_num_pts);
#endif
/* See if we're clicking a pre-existing point, to edit it? */
@ -242,6 +245,7 @@ polyfill_click(magic_api * api, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_U
#endif
polyfill_draw_preview(api, canvas, 1);
return;
}
@ -407,7 +411,7 @@ polyfill_release(magic_api * api, int which ATTRIBUTE_UNUSED,
}
/* Moved (or placed) the final spot at the beginning? */
if (polyfill_num_pts > 2 &&
if (polyfill_num_pts > 3 &&
((polyfill_editing == polyfill_num_pts - 1 &&
abs(x - polyfill_pt_x[0]) <= SNAP_SIZE &&
abs(y - polyfill_pt_y[0]) <= SNAP_SIZE) ||
@ -442,6 +446,12 @@ polyfill_release(magic_api * api, int which ATTRIBUTE_UNUSED,
/* Play "finish" sound effect */
api->playsound(snd_effects[SND_FINISH], 128 /* TODO could be clever and determine midpoint of polygon */, 255);
#ifdef DEBUG
printf("Retract the undo we just took (ahead of finishing polygon)!\n");
#endif
api->retract_undo();
SDL_BlitSurface(canvas, NULL, snapshot, NULL);
}
else
{
@ -493,6 +503,16 @@ polyfill_release(magic_api * api, int which ATTRIBUTE_UNUSED,
update_rect->y = 0;
update_rect->w = canvas->w;
update_rect->h = canvas->h;
/* Unless we just started a new polygon, don't let
Tux Paint take more undo snapshots */
if (polyfill_num_pts > 1)
{
#ifdef DEBUG
printf("Retract the undo we just took!\n");
#endif
api->retract_undo();
}
}
void polyfill_set_color(magic_api * api, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas,
@ -555,6 +575,14 @@ void polyfill_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNU
void polyfill_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
SDL_Surface * canvas)
{
if (polyfill_num_pts > 0)
{
#ifdef DEBUG
printf("Retract the undo we just took (on our way out)!\n");
#endif
api->retract_undo();
}
polyfill_num_pts = 0;
polyfill_editing = MAX_PTS;
polyfill_active = 0;

View file

@ -1,7 +1,7 @@
#ifndef TP_MAGIC_API_H
#define TP_MAGIC_API_H
/* src/tp_magic_api.h.in last modified 2023-12-29 */
/* src/tp_magic_api.h.in last modified 2024-06-01 */
#include "SDL.h"
#include "SDL_mixer.h"
@ -161,6 +161,11 @@ typedef struct magic_api_t {
clicked; useful for not applying the same effect from 'last' to 'canvas'
more than once per click-and-drag sequence */
Uint8 (*touched)(int, int);
/* Retracts the last undo buffer record; useful if a Magic tool has
drawn something "temporary" (such as guides) onto the canvas during
a previous click event. */
void (*retract_undo)(void);
} magic_api;

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
June 14, 2002 - May 25, 2024
June 14, 2002 - June 1, 2024
*/
#include "platform.h"
@ -1573,6 +1573,7 @@ typedef struct magic_funcs_s
void (*release)(magic_api *, int, SDL_Surface *, SDL_Surface *, int, int, SDL_Rect *);
void (*switchin)(magic_api *, int, int, SDL_Surface *, SDL_Surface *);
void (*switchout)(magic_api *, int, int, SDL_Surface *, SDL_Surface *);
void (*retract_undo)(void);
} magic_funcs_t;
@ -2304,6 +2305,7 @@ static SDL_Surface *magic_scale(SDL_Surface * surf, int w, int h, int aspect);
static SDL_Surface *magic_rotate_scale(SDL_Surface * surf, int r, int w);
static void reset_touched(void);
static Uint8 magic_touched(int x, int y);
static void magic_retract_undo(void);
static void magic_switchin(SDL_Surface * last);
static void magic_switchout(SDL_Surface * last);
@ -5442,18 +5444,7 @@ static void mainloop(void)
/* Start doing magic! */
/* These switchout/in are here for Magic tools that abuse the canvas
by drawing widgets on them; you don't want the widgets recorded as part
of the canvas in the undo buffer!
HOWEVER, as Pere noted in 2010.March, this causes many 'normal' Magic
tools to not work right, because they lose their record of the 'original'
canvas, before the user started using the tool (e.g., Rails, Perspective, Zoom).
FIXME: Some in-between solution is needed (a 'clean up the canvas'/'dirty the canvas'
pair of functions for the widgety abusers?) -bjk 2010.03.22 */
/* magic_switchout(canvas); *//* <-- FIXME: I dislike this -bjk 2009.10.13 */
rec_undo_buffer();
/* magic_switchin(canvas); *//* <-- FIXME: I dislike this -bjk 2009.10.13 */
if (cur_undo > 0)
undo_ctr = cur_undo - 1;
@ -21600,7 +21591,7 @@ static void load_magic_plugins(void)
magic_api_struct->scale = magic_scale;
magic_api_struct->rotate_scale = magic_rotate_scale;
magic_api_struct->touched = magic_touched;
magic_api_struct->retract_undo = magic_retract_undo;
do
{
@ -23775,6 +23766,19 @@ static Uint8 magic_touched(int x, int y)
return (res);
}
/**
* Removes the latest undo recorded
*/
void magic_retract_undo(void) {
if (cur_undo > 0)
cur_undo--;
else
cur_undo = NUM_UNDO_BUFS - 1;
newest_undo = cur_undo;
}
/**
* Allow the user to select a color from one of the
* pixels within their picture.