diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 0fd006c43..893f26146 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -37,6 +37,7 @@ https://tuxpaint.org/ * Various Magic tools now support sizing options: + Kaleidoscope + Blur + + Googly Eyes + WIP... more! * Other Improvements: diff --git a/magic/src/googlyeyes.c b/magic/src/googlyeyes.c index ebd4d302b..b20965bc2 100644 --- a/magic/src/googlyeyes.c +++ b/magic/src/googlyeyes.c @@ -3,7 +3,7 @@ Draws a googly eye at the click position, and looks towards where you drag+release. - Last updated: February 27, 2023 + Last updated: April 12, 2023 */ #include @@ -15,25 +15,32 @@ #include "SDL_image.h" #include "SDL_mixer.h" +/* For when Tux Paint is run with "--nomagicsizes", we'll present two tools */ + #define NUM_SIZES 2 int sizes[NUM_SIZES] = { 100, 50 }; char * googlyeyes_descr[NUM_SIZES] = { - "Click to place a large googly eye, then drag and release to make it look that direction.", - "Click to place a small googly eye, then drag and release to make it look that direction." + gettext_noop("Click to place a large googly eye, then drag and release to make it look that direction."), + gettext_noop("Click to place a small googly eye, then drag and release to make it look that direction."), }; char * img_filenames[NUM_SIZES] = { - "googlyeyes.png", + "googlyeyes.png", // Also used with magic sizes "googlyeyes-sm.png" }; +#define NUM_SCALEABLE_SIZES 4 + +int googlyeyes_limited = 0; +int googlyeyes_sizes; +int googlyeyes_size; Mix_Chunk *snd_effect = NULL; -SDL_Surface * googlyeyes_img_bkgd[NUM_SIZES]; -SDL_Surface * googlyeyes_img_pupil[NUM_SIZES]; -SDL_Surface * googlyeyes_img_reflection[NUM_SIZES]; +SDL_Surface * * googlyeyes_img_bkgd = NULL; +SDL_Surface * * googlyeyes_img_pupil = NULL; +SDL_Surface * * googlyeyes_img_reflection = NULL; int eye_x, eye_y; Uint32 googlyeyes_api_version(void); -int googlyeyes_init(magic_api * api); +int googlyeyes_init(magic_api * api, Uint32 disabled_features); int googlyeyes_get_tool_count(magic_api * api); SDL_Surface *googlyeyes_get_icon(magic_api * api, int which); char *googlyeyes_get_name(magic_api * api, int which); @@ -41,12 +48,17 @@ int googlyeyes_get_group(magic_api * api, int which); char *googlyeyes_get_description(magic_api * api, int which, int mode); int googlyeyes_requires_colors(magic_api * api, int which); int googlyeyes_modes(magic_api * api, int which); +Uint8 googlyeyes_accepted_sizes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED); +Uint8 googlyeyes_default_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED); void googlyeyes_shutdown(magic_api * api); void googlyeyes_click(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect); void googlyeyes_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * last, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect); +void googlyeyes_set_size(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * last, + Uint8 sz, SDL_Rect * update_rect); void googlyeyes_drag(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect); @@ -64,16 +76,30 @@ Uint32 googlyeyes_api_version(void) return (TP_MAGIC_API_VERSION); } -int googlyeyes_init(magic_api * api) +int googlyeyes_init(magic_api * api, Uint32 disabled_features) { char fname[1024]; int i; + googlyeyes_limited = (disabled_features & MAGIC_FEATURE_SIZE); + + /* Load sound effect */ snprintf(fname, sizeof(fname), "%ssounds/magic/googlyeyes.ogg", api->data_directory); snd_effect = Mix_LoadWAV(fname); - for (i = 0; i < NUM_SIZES; i++) { + /* Init the images */ + if (googlyeyes_limited) { + googlyeyes_sizes = NUM_SIZES; + } else { + googlyeyes_sizes = NUM_SCALEABLE_SIZES; + } + + googlyeyes_img_bkgd = (SDL_Surface * *) malloc(sizeof(SDL_Surface *) * googlyeyes_sizes); + googlyeyes_img_pupil = (SDL_Surface * *) malloc(sizeof(SDL_Surface *) * googlyeyes_sizes); + googlyeyes_img_reflection = (SDL_Surface * *) malloc(sizeof(SDL_Surface *) * googlyeyes_sizes); + + for (i = 0; i < googlyeyes_sizes; i++) { googlyeyes_img_bkgd[i] = NULL; googlyeyes_img_pupil[i] = NULL; googlyeyes_img_reflection[i] = NULL; @@ -108,34 +134,44 @@ int googlyeyes_init(magic_api * api) } /* Create the scaled versions */ - for (i = 1; i < NUM_SIZES; i++) { + for (i = 1; i < googlyeyes_sizes; i++) { + int size; + + if (googlyeyes_limited) { + size = sizes[i]; + } else { + size = (100 * (googlyeyes_sizes - i)) / googlyeyes_sizes; + } + + printf("%d -> %d%%\n", i, size); + googlyeyes_img_bkgd[i] = api->scale(googlyeyes_img_bkgd[0], - (googlyeyes_img_bkgd[0]->w * sizes[i]) / 100, - (googlyeyes_img_bkgd[0]->h * sizes[i]) / 100, + (googlyeyes_img_bkgd[0]->w * size) / 100, + (googlyeyes_img_bkgd[0]->h * size) / 100, 1); if (googlyeyes_img_bkgd[i] == NULL) { - fprintf(stderr, "Cannot scale bkgd to %d%%", sizes[i]); + fprintf(stderr, "Cannot scale bkgd to %d%%", size); return(1); } googlyeyes_img_pupil[i] = api->scale(googlyeyes_img_pupil[0], - (googlyeyes_img_pupil[0]->w * sizes[i]) / 100, - (googlyeyes_img_pupil[0]->h * sizes[i]) / 100, + (googlyeyes_img_pupil[0]->w * size) / 100, + (googlyeyes_img_pupil[0]->h * size) / 100, 1); if (googlyeyes_img_pupil[i] == NULL) { - fprintf(stderr, "Cannot scale pupil to %d%%", sizes[i]); + fprintf(stderr, "Cannot scale pupil to %d%%", size); return(1); } googlyeyes_img_reflection[i] = api->scale(googlyeyes_img_reflection[0], - (googlyeyes_img_reflection[0]->w * sizes[i]) / 100, - (googlyeyes_img_reflection[0]->h * sizes[i]) / 100, + (googlyeyes_img_reflection[0]->w * size) / 100, + (googlyeyes_img_reflection[0]->h * size) / 100, 1); if (googlyeyes_img_reflection[i] == NULL) { - fprintf(stderr, "Cannot scale reflection to %d%%", sizes[i]); + fprintf(stderr, "Cannot scale reflection to %d%%", size); return(1); } } @@ -145,7 +181,11 @@ int googlyeyes_init(magic_api * api) int googlyeyes_get_tool_count(magic_api * api ATTRIBUTE_UNUSED) { - return (NUM_SIZES); + if (googlyeyes_limited) { + return (NUM_SIZES); + } else { + return 1; + } } @@ -175,7 +215,11 @@ char *googlyeyes_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) { - return strdup(gettext(googlyeyes_descr[which])); + if (googlyeyes_limited) { + return strdup(gettext(googlyeyes_descr[which])); + } else { + return strdup(gettext_noop("Click to place a googly eye, then drag and release to make it look that direction.")); + } } int googlyeyes_requires_colors(magic_api * api ATTRIBUTE_UNUSED, @@ -190,6 +234,20 @@ int googlyeyes_modes(magic_api * api ATTRIBUTE_UNUSED, return MODE_PAINT; } +Uint8 googlyeyes_accepted_sizes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) +{ + if (googlyeyes_limited) { + return 1; + } else { + return NUM_SCALEABLE_SIZES; + } +} + +Uint8 googlyeyes_default_size(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) +{ + return NUM_SCALEABLE_SIZES; +} + void googlyeyes_shutdown(magic_api * api ATTRIBUTE_UNUSED) { int i; @@ -197,7 +255,7 @@ void googlyeyes_shutdown(magic_api * api ATTRIBUTE_UNUSED) if (snd_effect != NULL) Mix_FreeChunk(snd_effect); - for (i = 0; i < NUM_SIZES; i++) { + for (i = 0; i < googlyeyes_sizes; i++) { if (googlyeyes_img_bkgd[i] != NULL) SDL_FreeSurface(googlyeyes_img_bkgd[i]); @@ -207,6 +265,10 @@ void googlyeyes_shutdown(magic_api * api ATTRIBUTE_UNUSED) if (googlyeyes_img_reflection[i] != NULL) SDL_FreeSurface(googlyeyes_img_reflection[i]); } + + free(googlyeyes_img_bkgd); + free(googlyeyes_img_pupil); + free(googlyeyes_img_reflection); } @@ -215,13 +277,21 @@ googlyeyes_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect) { + int img; + eye_x = x; eye_y = y; - if (eye_x < googlyeyes_img_bkgd[which]->w / 2) - eye_x = googlyeyes_img_bkgd[which]->w / 2; - if (eye_y < googlyeyes_img_bkgd[which]->h / 2) - eye_y = googlyeyes_img_bkgd[which]->h / 2; + if (googlyeyes_limited) { + img = which; + } else { + img = googlyeyes_size - 1; + } + + if (eye_x < googlyeyes_img_bkgd[img]->w / 2) + eye_x = googlyeyes_img_bkgd[img]->w / 2; + if (eye_y < googlyeyes_img_bkgd[img]->h / 2) + eye_y = googlyeyes_img_bkgd[img]->h / 2; api->stopsound(); api->playsound(snd_effect, (x * 255) / canvas->w, 255); @@ -237,21 +307,28 @@ googlyeyes_drag(magic_api * api ATTRIBUTE_UNUSED, int which, SDL_Surface * canva { SDL_Rect dest; int max_radius; + int img; + + if (googlyeyes_limited) { + img = which; + } else { + img = googlyeyes_size - 1; + } /* Set the destination for the main background */ - update_rect->x = eye_x - googlyeyes_img_bkgd[which]->w / 2; - update_rect->y = eye_y - googlyeyes_img_bkgd[which]->h / 2; - update_rect->w = googlyeyes_img_bkgd[which]->w; - update_rect->h = googlyeyes_img_bkgd[which]->h; + update_rect->x = eye_x - googlyeyes_img_bkgd[img]->w / 2; + update_rect->y = eye_y - googlyeyes_img_bkgd[img]->h / 2; + update_rect->w = googlyeyes_img_bkgd[img]->w; + update_rect->h = googlyeyes_img_bkgd[img]->h; /* Erase the eye (drop snapshot pixels back into canvas) */ SDL_BlitSurface(snapshot, update_rect, canvas, update_rect); /* 1. Draw the background */ - SDL_BlitSurface(googlyeyes_img_bkgd[which], NULL, canvas, update_rect); + SDL_BlitSurface(googlyeyes_img_bkgd[img], NULL, canvas, update_rect); /* 2. Draw the pupil */ - max_radius = ((googlyeyes_img_bkgd[which]->w - googlyeyes_img_pupil[which]->w) / 2); + max_radius = ((googlyeyes_img_bkgd[img]->w - googlyeyes_img_pupil[img]->w) / 2); if (sqrt(((x - eye_x) * (x - eye_x)) + ((y - eye_y) * (y - eye_y))) > max_radius) { /* If drag position would place pupil outside the circular bounds * of the background, put it on the edge, "looking towards" (pointing at) @@ -268,18 +345,18 @@ googlyeyes_drag(magic_api * api ATTRIBUTE_UNUSED, int which, SDL_Surface * canva y = eye_y + (sin(angle) * max_radius); } - dest.x = x - googlyeyes_img_pupil[which]->w / 2; - dest.y = y - googlyeyes_img_pupil[which]->h / 2; - dest.w = googlyeyes_img_pupil[which]->w; - dest.h = googlyeyes_img_pupil[which]->h; - SDL_BlitSurface(googlyeyes_img_pupil[which], NULL, canvas, &dest); + dest.x = x - googlyeyes_img_pupil[img]->w / 2; + dest.y = y - googlyeyes_img_pupil[img]->h / 2; + dest.w = googlyeyes_img_pupil[img]->w; + dest.h = googlyeyes_img_pupil[img]->h; + SDL_BlitSurface(googlyeyes_img_pupil[img], NULL, canvas, &dest); /* 3. Draw the reflection */ - dest.x = eye_x - googlyeyes_img_reflection[which]->w / 2; - dest.y = eye_y - googlyeyes_img_reflection[which]->h / 2; - dest.w = googlyeyes_img_reflection[which]->w; - dest.h = googlyeyes_img_reflection[which]->h; - SDL_BlitSurface(googlyeyes_img_reflection[which], NULL, canvas, &dest); + dest.x = eye_x - googlyeyes_img_reflection[img]->w / 2; + dest.y = eye_y - googlyeyes_img_reflection[img]->h / 2; + dest.w = googlyeyes_img_reflection[img]->w; + dest.h = googlyeyes_img_reflection[img]->h; + SDL_BlitSurface(googlyeyes_img_reflection[img], NULL, canvas, &dest); } @@ -298,6 +375,13 @@ void googlyeyes_set_color(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_ } +void googlyeyes_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 sz, SDL_Rect * update_rect ATTRIBUTE_UNUSED) +{ + googlyeyes_size = (NUM_SCALEABLE_SIZES - sz) + 1; +} + void googlyeyes_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED, SDL_Surface * canvas ATTRIBUTE_UNUSED)