Actually commiting new Magic tool source

...and CHANGES.txt update
This commit is contained in:
Bill Kendrick 2023-02-28 01:20:47 -08:00
parent d588c39d21
commit 06aa682667
2 changed files with 130 additions and 48 deletions

View file

@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt)
https://tuxpaint.org/
2023.February.26 (0.9.29)
2023.February.28 (0.9.29)
* Improvements to "Stamp" tool:
-----------------------------
* Stamps may now be rotated.
@ -58,6 +58,20 @@ https://tuxpaint.org/
Attribution 4.0 International (CC BY 4.0)
by https://freesound.org/people/juskiddink/)
* [WIP] "Saturate" & "Desaturate" - Increase or decrease color saturation.
Bill Kendrick <bill@newbreedsoftware.com>
- need icons
- need sound effects
* [WIP] "Keep Color" & "Remove Color" - Completely desaturate
parts of the picture, based on the chosen color.
"Keep" keeps the saturation intact if the colors match;
while "Remove" desaturates parts of the image that match the
chosen color.
Bill Kendrick <bill@newbreedsoftware.com>
- need icons
- need sound effects
* [WIP] "Rivulet"; apply rivulets of water to the canvas
- needs better icon
- needs sound effect

View file

@ -23,7 +23,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
Last updated: February 12, 2023
Last updated: February 28, 2023
*/
#include <stdio.h>
@ -36,10 +36,75 @@ enum
{
TOOL_FADE,
TOOL_DARKEN,
TOOL_DESATURATE,
TOOL_SATURATE,
TOOL_REMOVE,
TOOL_KEEP,
NUM_TOOLS
};
char * tool_names[NUM_TOOLS] = {
gettext_noop("Lighten"),
gettext_noop("Darken"),
gettext_noop("Desaturate"),
gettext_noop("Saturate"),
gettext_noop("Remove Color"),
gettext_noop("Keep Color"),
};
char * tool_descriptions[NUM_TOOLS][2] = {
{
gettext_noop("Click and drag the mouse to lighten parts of your picture."),
gettext_noop("Click to lighten your entire picture.")
},
{
gettext_noop("Click and drag the mouse to darken parts of your picture."),
gettext_noop("Click to darken your entire picture.")
},
{
gettext_noop("Click and drag the mouse to desaturate parts of your picture."),
gettext_noop("Click to desaturate your entire picture.")
},
{
gettext_noop("Click and drag the mouse to saturate parts of your picture."),
gettext_noop("Click to saturate your entire picture.")
},
{
gettext_noop("Click and drag the mouse to entirely desaturate parts of your picture that match the chosen color."),
gettext_noop("Click to entirely desaturate your the parts of your picture that match the chosen color."),
},
{
gettext_noop("Click and drag the mouse to entirely desaturate parts of your picture that don't match the chosen color."),
gettext_noop("Click to entirely desaturate your the parts of your picture that don't match the chosen color."),
},
};
char * sfx_filenames[NUM_TOOLS] = {
"fade.wav",
"darken.wav",
"fade.wav", // FIXME
"darken.wav", // FIXME
"darken.wav", // FIXME
"darken.wav", // FIXME
};
char * icon_filenames[NUM_TOOLS] = {
"fade.png",
"darken.png",
"fade.png", // FIXME
"darken.png", // FIXME
"darken.png", // FIXME
"darken.png", // FIXME
};
static Mix_Chunk *snd_effects[NUM_TOOLS];
float chosen_h, chosen_s;
#define KEEP_REMOVE_HUE_THRESH 15.0
#define KEEP_REMOVE_VALUE_THRESH 0.4
#define SAT_DESAT_RATIO_NUM 3
#define SAT_DESAT_RATIO_DENOM 4
/* Local function prototypes: */
@ -74,17 +139,17 @@ void fade_darken_switchout(magic_api * api, int which, int mode,
SDL_Surface * canvas);
int fade_darken_modes(magic_api * api, int which);
int fade_darken_init(magic_api * api)
{
int i;
char fname[1024];
snprintf(fname, sizeof(fname), "%ssounds/magic/fade.wav",
api->data_directory);
snd_effects[TOOL_FADE] = Mix_LoadWAV(fname);
snprintf(fname, sizeof(fname), "%ssounds/magic/darken.wav",
api->data_directory);
snd_effects[TOOL_DARKEN] = Mix_LoadWAV(fname);
for (i = 0; i < NUM_TOOLS; i++) {
snprintf(fname, sizeof(fname), "%ssounds/magic/%s",
api->data_directory, sfx_filenames[i]);
snd_effects[i] = Mix_LoadWAV(fname);
}
return (1);
}
@ -105,16 +170,8 @@ SDL_Surface *fade_darken_get_icon(magic_api * api, int which)
{
char fname[1024];
if (which == TOOL_FADE)
{
snprintf(fname, sizeof(fname), "%simages/magic/fade.png",
api->data_directory);
}
else if (which == TOOL_DARKEN)
{
snprintf(fname, sizeof(fname), "%simages/magic/darken.png",
api->data_directory);
}
snprintf(fname, sizeof(fname), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
return (IMG_Load(fname));
}
@ -122,12 +179,7 @@ SDL_Surface *fade_darken_get_icon(magic_api * api, int which)
// Return our name, localized:
char *fade_darken_get_name(magic_api * api ATTRIBUTE_UNUSED, int which)
{
if (which == TOOL_FADE)
return (strdup(gettext_noop("Lighten")));
else if (which == TOOL_DARKEN)
return (strdup(gettext_noop("Darken")));
return (NULL);
return strdup(gettext(tool_names[which]));
}
// Return our group (all the same):
@ -141,26 +193,7 @@ int fade_darken_get_group(magic_api * api ATTRIBUTE_UNUSED,
char *fade_darken_get_description(magic_api * api ATTRIBUTE_UNUSED, int which,
int mode)
{
if (which == TOOL_FADE)
{
if (mode == MODE_PAINT)
return (strdup
(gettext_noop
("Click and drag the mouse to lighten parts of your picture.")));
else if (mode == MODE_FULLSCREEN)
return (strdup(gettext_noop("Click to lighten your entire picture.")));
}
else if (which == TOOL_DARKEN)
{
if (mode == MODE_PAINT)
return (strdup
(gettext_noop
("Click and drag the mouse to darken parts of your picture.")));
else if (mode == MODE_FULLSCREEN)
return (strdup(gettext_noop("Click to darken your entire picture.")));
}
return (NULL);
return strdup(gettext(tool_descriptions[which][mode - 1]));
}
static void do_fade_darken(void *ptr, int which, SDL_Surface * canvas,
@ -183,10 +216,40 @@ static void do_fade_darken(void *ptr, int which, SDL_Surface * canvas,
g = max(g - 48, 0);
b = max(b - 48, 0);
}
else
{
float h, s, v;
api->rgbtohsv(r, g, b, &h, &s, &v);
if (which == TOOL_DESATURATE) {
s = (s * SAT_DESAT_RATIO_NUM) / SAT_DESAT_RATIO_DENOM;
} else if (which == TOOL_SATURATE) {
if (s > 0.1) { /* don't saturate things w/o undefined color! */
s = (s * SAT_DESAT_RATIO_DENOM) / SAT_DESAT_RATIO_NUM;
if (s > 1.0) {
s = 1.0;
}
}
} else if (which == TOOL_REMOVE) {
if (fabs(h - chosen_h) <= KEEP_REMOVE_HUE_THRESH &&
fabs(s - chosen_s) <= KEEP_REMOVE_VALUE_THRESH) {
s = 0.0;
}
} else if (which == TOOL_KEEP) {
if (fabs(h - chosen_h) > KEEP_REMOVE_HUE_THRESH ||
fabs(s - chosen_s) > KEEP_REMOVE_VALUE_THRESH) {
s = 0.0;
}
}
api->hsvtorgb(h, s, v, &r, &g, &b);
}
api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format, r, g, b));
}
// Callback that does the fade_darken color effect on a circle centered around x,y
static void do_fade_darken_paint(void *ptr, int which, SDL_Surface * canvas,
SDL_Surface * last, int x, int y)
@ -288,16 +351,21 @@ void fade_darken_shutdown(magic_api * api ATTRIBUTE_UNUSED)
Mix_FreeChunk(snd_effects[1]);
}
// We don't use colors
void fade_darken_set_color(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED,
SDL_Surface * last ATTRIBUTE_UNUSED, Uint8 r ATTRIBUTE_UNUSED, Uint8 g ATTRIBUTE_UNUSED, Uint8 b ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
void fade_darken_set_color(magic_api * api, 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)
{
float tmp;
api->rgbtohsv(r, g, b, &chosen_h, &chosen_s, &tmp);
}
// We don't use colors
int fade_darken_requires_colors(magic_api * api ATTRIBUTE_UNUSED,
int which ATTRIBUTE_UNUSED)
{
if (which == TOOL_REMOVE || which == TOOL_KEEP)
return 1;
return 0;
}