From 881ea9a3c1b5f57d8e0613422e1cc474cad45236 Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Tue, 8 Oct 2024 01:17:56 -0700 Subject: [PATCH] WIP "Tessellation" magic tool --- docs/AUTHORS.txt | 5 +- docs/CHANGES.txt | 9 +- magic/src/tessell.c | 235 +++++++++++++++++++++++ src/org.tuxpaint.Tuxpaint.appdata.xml.in | 4 +- 4 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 magic/src/tessell.c diff --git a/docs/AUTHORS.txt b/docs/AUTHORS.txt index 0da74f955..d1fe5f273 100644 --- a/docs/AUTHORS.txt +++ b/docs/AUTHORS.txt @@ -6,7 +6,7 @@ Copyright (c) 2002-2024 Various contributors (see below, and CHANGES.txt) https://tuxpaint.org/ -June 17, 2002 - October 7, 2024 +June 17, 2002 - October 8, 2024 * Design and Coding: @@ -268,6 +268,9 @@ June 17, 2002 - October 7, 2024 Creative Commons Attribution 3.0 (CC BY 3.0) by "THE_bizniss" + "Tessellation" magic tool + by Bill Kendrick + Bloom magic tool by Bill Kendrick diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index b0476ba73..282c33ded 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -6,7 +6,7 @@ Copyright (c) 2002-2024 Various contributors (see below, and AUTHORS.txt) https://tuxpaint.org/ -2024.October.7 (0.9.34) +2024.October.8 (0.9.34) * New Magic Tools: ---------------- * "Comic Dots", draws repeating dots (using a multiply blend) @@ -96,6 +96,13 @@ https://tuxpaint.org/ Creative Commons Attribution 3.0 (CC BY 3.0) by "THE_bizniss" + * WIP "Tessellation": Draw a repeating tessellation pattern + + Code by Bill Kendrick + + TODO Move to proper section + + TODO Add icon + + TODO Add sound effect + + TODO Documentation + * Magic Tool Improvements: ------------------------ * Sound pause/resume functions added to API diff --git a/magic/src/tessell.c b/magic/src/tessell.c new file mode 100644 index 000000000..e4d3614bd --- /dev/null +++ b/magic/src/tessell.c @@ -0,0 +1,235 @@ +/* + tessell.c + + Repeats what you draw in a tessellating pattern around + the canvas. + + Tux Paint - A simple drawing program for children. + + Copyright (c) 2024 by Bill Kendrick + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + (See COPYING.txt) + + Last updated: October 8, 2024 +*/ + +#include +#include +#include "tp_magic_api.h" +#include "SDL_image.h" +#include "SDL_mixer.h" + +#define REPEAT_CNT 3 +#define SIN_60DEG 0.866025403784439 + +static Mix_Chunk *tessell_snd; +static int tessell_radius = 16, tessell_width, tessell_height; +static Uint32 tessell_color; + +Uint32 tessell_api_version(void); +int tessell_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level); +int tessell_get_tool_count(magic_api * api); +SDL_Surface *tessell_get_icon(magic_api * api, int which); +char *tessell_get_name(magic_api * api, int which); +int tessell_get_group(magic_api * api, int which); +int tessell_get_order(int which); +char *tessell_get_description(magic_api * api, int which, int mode); + +void tessell_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect); + +void tessell_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect); + +void tessell_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect); + +void tessell_shutdown(magic_api * api); +void tessell_set_color(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * last, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect); +int tessell_requires_colors(magic_api * api, int which); +void tessell_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas); +void tessell_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas); +int tessell_modes(magic_api * api, int which); +Uint8 tessell_accepted_sizes(magic_api * api, int which, int mode); +Uint8 tessell_default_size(magic_api * api, int which, int mode); +void tessell_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * last, Uint8 size, + SDL_Rect * update_rect); + + +Uint32 tessell_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + +int tessell_init(magic_api * api, Uint8 disabled_features ATTRIBUTE_UNUSED, Uint8 complexity_level ATTRIBUTE_UNUSED) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%ssounds/magic/xor.ogg", api->data_directory); // FIXME + tessell_snd = Mix_LoadWAV(fname); + + return (1); +} + +int tessell_get_tool_count(magic_api * api ATTRIBUTE_UNUSED) +{ + return (1); +} + +SDL_Surface *tessell_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED) +{ + char fname[1024]; + + snprintf(fname, sizeof(fname), "%simages/magic/xor.png", api->data_directory); // FIXME + + return (IMG_Load(fname)); +} + +char *tessell_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED) +{ + return (strdup(gettext("Tessellation"))); +} + +int tessell_get_group(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED) +{ + return MAGIC_TYPE_PAINTING; +} + +int tessell_get_order(int which ATTRIBUTE_UNUSED) +{ + return 800; +} + +char *tessell_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode) +{ + return (strdup(gettext("Click and drag to draw a repeating tessellating pattern."))); +} + +static void do_tessell_circle(void *ptr, int which ATTRIBUTE_UNUSED, + SDL_Surface * canvas, SDL_Surface * last ATTRIBUTE_UNUSED, int x, int y) +{ + int xx, yy, rx, ry, sx, sy; + magic_api *api = (magic_api *) ptr; + + for (yy = -tessell_radius; yy <= tessell_radius; yy++) + { + for (xx = -tessell_radius; xx <= tessell_radius; xx++) + { + if (api->in_circle(xx, yy, tessell_radius)) + { + for (ry = -REPEAT_CNT; ry <= REPEAT_CNT; ry++) + { + for (rx = -REPEAT_CNT; rx <= REPEAT_CNT; rx++) + { + sx = rx * tessell_width; + if (abs(ry) % 2 == 1) + sx += tessell_width / 2; + sy = ry * tessell_height; + + api->putpixel(canvas, x + xx + sx, y + yy + sy, tessell_color); + } + } + } + } + } +} + +void tessell_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * last ATTRIBUTE_UNUSED, int ox, int oy, int x, int y, SDL_Rect * update_rect) +{ + api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, do_tessell_circle); + + update_rect->x = 0; + update_rect->y = 0; + update_rect->w = canvas->w; + update_rect->h = canvas->h; + + api->playsound(tessell_snd, (x * 255) / canvas->w, 255); +} + +void tessell_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * last ATTRIBUTE_UNUSED, int x, int y, SDL_Rect * update_rect) +{ + tessell_drag(api, which, canvas, last, x, y, x, y, update_rect); +} + +void tessell_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED, + SDL_Surface * last ATTRIBUTE_UNUSED, int x ATTRIBUTE_UNUSED, + int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) +{ +} + +void tessell_shutdown(magic_api * api ATTRIBUTE_UNUSED) +{ + if (tessell_snd != NULL) + Mix_FreeChunk(tessell_snd); +} + +void tessell_set_color(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED, + SDL_Surface * last ATTRIBUTE_UNUSED, Uint8 r, Uint8 g, + Uint8 b, SDL_Rect * update_rect ATTRIBUTE_UNUSED) +{ + tessell_color = SDL_MapRGB(canvas->format, r, g, b); +} + +int tessell_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED) +{ + return 1; +} + +void tessell_switchin(magic_api * api ATTRIBUTE_UNUSED, + int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED) +{ + int tessell_mult; + + if (canvas->w > canvas->h) + tessell_mult = canvas->w / (REPEAT_CNT + 1); + else + tessell_mult = canvas->h / (REPEAT_CNT + 1); + + tessell_width = tessell_mult; + tessell_height = tessell_mult * SIN_60DEG; +} + +void tessell_switchout(magic_api * api ATTRIBUTE_UNUSED, + int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED) +{ +} + +int tessell_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED) +{ + return MODE_PAINT; +} + + +Uint8 tessell_accepted_sizes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode) +{ + return 8; +} + +Uint8 tessell_default_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) +{ + return 2; +} + +void tessell_set_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, + SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * last ATTRIBUTE_UNUSED, + Uint8 size ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED) +{ + tessell_radius = size; +} diff --git a/src/org.tuxpaint.Tuxpaint.appdata.xml.in b/src/org.tuxpaint.Tuxpaint.appdata.xml.in index 92d9586b3..dc29fd3ff 100644 --- a/src/org.tuxpaint.Tuxpaint.appdata.xml.in +++ b/src/org.tuxpaint.Tuxpaint.appdata.xml.in @@ -47,10 +47,10 @@ - +

New Fill mode: "Eraser" flood fill.

-

New Magic tools: "Comic dots", "Rotate", various "ASCII" art, various "Fractals", "Crescent", "Spray Paint", "Spiral", "Square Spiral", "Concentric Circle", and "Concentric Square".

+

New Magic tools: "Comic dots", "Rotate", various "ASCII" art, various "Fractals", "Crescent", "Spray Paint", "Spiral", "Square Spiral", "Concentric Circle", "Concentric Square", and "Tessellation".

New brush: Fluff (gradient).