From 0783b36fce40b8848ab1eda83bf95f0e258308b5 Mon Sep 17 00:00:00 2001 From: Bill Kendrick Date: Tue, 23 May 2023 00:29:37 -0700 Subject: [PATCH] Ribbon Magic tool sound effect CC-BY 3.0 by https://freesound.org/people/CosmicEmbers/ --- docs/AUTHORS.txt | 9 ++++++++- docs/CHANGES.txt | 5 +++-- magic/sounds/ribbon.ogg | Bin 0 -> 11129 bytes magic/src/ribbon.c | 26 ++++++++++++++++++-------- 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 magic/sounds/ribbon.ogg diff --git a/docs/AUTHORS.txt b/docs/AUTHORS.txt index 30d7e2f6a..3a95a2b82 100644 --- a/docs/AUTHORS.txt +++ b/docs/AUTHORS.txt @@ -6,7 +6,7 @@ Copyright (c) 2002-2023 Various contributors (see below, and CHANGES.txt) https://tuxpaint.org/ -June 17, 2002 - May 22, 2023 +June 17, 2002 - May 23, 2023 * Design and Coding: @@ -202,6 +202,13 @@ June 17, 2002 - May 22, 2023 Creative Commons Attribution 4.0 International (CC BY 4.0) by https://freesound.org/people/PercyFrench/ + "Ribbon" Magic tool + by Bill Kendrick + Sound effect "cape-swoosh" + (https://freesound.org/people/CosmicEmbers/sounds/161415/) + Creative Commons Attribution 3.0 Unported (CC BY 3.0) + by https://freesound.org/people/CosmicEmbers/ + Mouse accessibility code and keyboard access Ankit Choudary , as part of GSOC 2010, with integration and fixes by Pere Pujal i Carabantes diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index c0bdffd5f..89d2556f3 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -6,7 +6,7 @@ Copyright (c) 2002-2023 Various contributors (see below, and AUTHORS.txt) https://tuxpaint.org/ -2023.May.22 (0.9.31) +2023.May.23 (0.9.31) * New Magic Tools: ---------------- * WIP Loops - Draw loop-the-loops. @@ -17,7 +17,8 @@ https://tuxpaint.org/ * WIP Ribbon - Paints a flowing, fixed-length ribbon. Bill Kendrick - - WIP needs sfx + Sound effect CC-BY 3.0 by + https://freesound.org/people/CosmicEmbers/ - WIP needs icon * WIP Smooth - Freehand paintbrush with a smoothing effect (Bezier curve) diff --git a/magic/sounds/ribbon.ogg b/magic/sounds/ribbon.ogg new file mode 100644 index 0000000000000000000000000000000000000000..286b49fef5bf12644a3cdc5abe7cd4bcc1bfd907 GIT binary patch literal 11129 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 @@ -44,6 +44,7 @@ static Uint8 ribbon_r, ribbon_g, ribbon_b; static Uint32 ribbon_segment_color; static int ribbon_x[MAX_LENGTH], ribbon_y[MAX_LENGTH]; static int ribbon_tail = 0, ribbon_head = 0; +static double ribbon_old_angle; static Mix_Chunk *ribbon_snd; int ribbon_init(magic_api * api, Uint32 disabled_features); @@ -88,7 +89,7 @@ int ribbon_init(magic_api * api, Uint32 disabled_features ATTRIBUTE_UNUSED) { char fname[1024]; - snprintf(fname, sizeof(fname), "%ssounds/magic/rainbow.wav", api->data_directory); // FIXME + snprintf(fname, sizeof(fname), "%ssounds/magic/ribbon.ogg", api->data_directory); ribbon_snd = Mix_LoadWAV(fname); return (1); @@ -164,11 +165,23 @@ void ribbon_drag(magic_api * api, int which, SDL_Surface * canvas, if (ribbon_head == ribbon_tail) ribbon_tail = (ribbon_tail + 1) % ribbon_max_length; + + angle = 0.0; + if (!first_click) { + double x_angle; + + if (sqrt((x - ox) * (x - ox) + (y - oy) * (y - oy)) > 16) + { + /* Play swooshing sfx if we're moving quickly and making a big angle */ + x_angle = (fabs(atan2((double)(y - oy), (double)(x - ox))) * 2.0); + if (fabs(x_angle - ribbon_old_angle) > (M_PI / 4.0)) + api->playsound(ribbon_snd, (x * 255) / canvas->w, 255); + ribbon_old_angle = x_angle; + } + pt = ribbon_tail; - angle = 0.0; do { - double x_angle; int brt; pt2 = ((pt + 1) % ribbon_max_length); @@ -188,7 +201,6 @@ void ribbon_drag(magic_api * api, int which, SDL_Surface * canvas, r = max(min(ribbon_r + brt, 255), 0); g = max(min(ribbon_g + brt, 255), 0); b = max(min(ribbon_b + brt, 255), 0); -// b = (Uint8) (((double) ribbon_b * angle) / M_PI); ribbon_segment_color = SDL_MapRGB(canvas->format, r, g, b); api->line((void *)api, which, canvas, last, ox, oy, x, y, 1, ribbon_linecb); @@ -200,15 +212,13 @@ void ribbon_drag(magic_api * api, int which, SDL_Surface * canvas, update_rect->y = 0; update_rect->w = canvas->w; update_rect->h = canvas->h; - - api->playsound(ribbon_snd, (x * 255) / canvas->w, 255); } // Affect the canvas on click: void ribbon_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect) { - ribbon_head = ribbon_tail = 0; + ribbon_head = ribbon_tail = ribbon_old_angle = 0; ribbon_drag(api, which, canvas, last, x, y, x, y, update_rect); }