/* specular.c A specular reflection Magic tool for Tux Paint by Bill Kendrick Last updated: March 2, 2024 */ /* Inclusion of header files */ /* ---------------------------------------------------------------------- */ #include #include #include #include "tp_magic_api.h" #include "SDL_image.h" #include "SDL_mixer.h" /* Our global variables: */ /* ---------------------------------------------------------------------- */ /* Sound effects: */ Mix_Chunk *snd_effect; /* The size the user has selected in Tux Paint: */ Uint8 specular_size = 32; void specular_drag(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int old_x, int old_y, int x, int y, SDL_Rect * update_rect); void specular_line_callback(void *pointer, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y); Uint32 specular_api_version(void) { return (TP_MAGIC_API_VERSION); } int specular_init(magic_api *api, Uint8 disabled_features, Uint8 complexity_level) { int i; char filename[1024]; snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory, "reflection.ogg"); // FIXME snd_effect = Mix_LoadWAV(filename); return (1); } int specular_get_tool_count(magic_api *api) { return (1); } SDL_Surface *specular_get_icon(magic_api *api, int which) { char filename[1024]; snprintf(filename, sizeof(filename), "%simages/magic/%s", api->data_directory, "reflection.png"); // FIXME return (IMG_Load(filename)); } char *specular_get_name(magic_api *api, int which) { return strdup(gettext("Specular Reflection")); } int specular_get_group(magic_api *api, int which) { return MAGIC_TYPE_PAINTING; } int specular_get_order(int which) { return 1710; } char *specular_get_description(magic_api *api, int which, int mode) { return strdup(gettext ("Click and drag on the bottom half of your picture to draw a specular reflection — like a puddle, pond, or lake — that mirrors the top half of your picture.")); } int specular_requires_colors(magic_api *api, int which) { return 0; } int specular_modes(magic_api *api, int which) { return MODE_PAINT; } Uint8 specular_accepted_sizes(magic_api *api, int which, int mode) { return 4; } Uint8 specular_default_size(magic_api *api, int which, int mode) { return 2; } void specular_shutdown(magic_api *api) { if (snd_effect != NULL) { Mix_FreeChunk(snd_effect); } } void specular_click(magic_api *api, int which, int mode, SDL_Surface *canvas, SDL_Surface *snapshot, int x, int y, SDL_Rect *update_rect) { specular_drag(api, which, canvas, snapshot, x, y, x, y, update_rect); } void specular_drag(magic_api *api, int which, SDL_Surface *canvas, SDL_Surface *snapshot, int old_x, int old_y, int x, int y, SDL_Rect *update_rect) { SDL_LockSurface(snapshot); SDL_LockSurface(canvas); api->line((void *)api, which, canvas, snapshot, old_x, old_y, x, y, 1, specular_line_callback); SDL_UnlockSurface(canvas); SDL_UnlockSurface(snapshot); if (old_x > x) { int temp = old_x; old_x = x; x = temp; } if (old_y > y) { int temp = old_y; old_y = y; y = temp; } update_rect->x = old_x - specular_size; update_rect->y = old_y - specular_size; update_rect->w = (x + specular_size) - update_rect->x + 1; update_rect->h = (y + specular_size) - update_rect->y + 1; api->playsound(snd_effect, (x * 255) / canvas->w, 255); } void specular_release(magic_api *api, int which, SDL_Surface *canvas, SDL_Surface *snapshot, int x, int y, SDL_Rect *update_rect) { } void specular_set_color(magic_api *api, int which, SDL_Surface *canvas, SDL_Surface *snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect *update_rect) { } void specular_set_size(magic_api *api, int which, int mode, SDL_Surface *canvas, SDL_Surface *snapshot, Uint8 size, SDL_Rect *update_rect) { specular_size = size * 16; } void specular_line_callback(void *pointer, int which, SDL_Surface *canvas, SDL_Surface *snapshot, int x, int y) { magic_api *api = (magic_api *) pointer; int xx, yy, ysrc; Uint8 r, g, b, r1, g1, b1, r2, g2, b2, fade; for (yy = -specular_size / 16; yy < specular_size / 16; yy++) { ysrc = (snapshot->h - y - yy) + sin(y - yy) * 4; for (xx = -specular_size; xx < specular_size; xx++) { if (api->in_circle(xx, yy * 16, specular_size)) { SDL_GetRGB(api->getpixel(snapshot, x + xx + sin((y + yy) / 4) * 4, ysrc), snapshot->format, &r1, &g1, &b1); SDL_GetRGB(api->getpixel(snapshot, x + xx + sin((y + yy) / 4) * 4 + 1, ysrc), snapshot->format, &r2, &g2, &b2); fade = (((y + yy) * 255) / canvas->h); r = (((r1 + r2) * 2) + fade) / 5; g = (((g1 + g2) * 2) + fade) / 5; b = (((b1 + b2) * 2) + fade) / 5; api->putpixel(canvas, x + xx, y + yy, SDL_MapRGB(canvas->format, r, g, b)); } } } } void specular_switchin(magic_api *api, int which, int mode, SDL_Surface *canvas) { } void specular_switchout(magic_api *api, int which, int mode, SDL_Surface *canvas) { }