WIP Specular Reflection magic tool

This commit is contained in:
Bill Kendrick 2024-02-28 23:51:28 -08:00
parent 9fa5c649d1
commit f21e5f136d
2 changed files with 239 additions and 0 deletions

View file

@ -7,6 +7,16 @@ Various contributors (see below, and AUTHORS.txt)
https://tuxpaint.org/
2024.February.28 (0.9.33)
* New Magic Tools:
----------------
* WIP Specular Reflection: Draws a slightly blurred, wavy, and
faded reflection of the opposite half of the drawing.
Bill Kendrick <bill@newbreedsoftware.com>
+ WIP Needs docs
+ WIP Add to new features lists
+ WIP Needs icon
+ WIP Needs sound effect
* Other Improvements:
-------------------
* Make screen refresh more snappy on macOS.

229
magic/src/specular.c Normal file
View file

@ -0,0 +1,229 @@
/* specular.c
A specular reflection Magic tool for Tux Paint
by Bill Kendrick <bill@newbreedsoftware.com>
Last updated: February 28, 2024
*/
/* Inclusion of header files */
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h>
#include <libintl.h>
#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;
Uint8 r, g, b, r1, g1, b1, r2, g2, b2, fade;
for (yy = -specular_size / 16; yy < specular_size / 16; yy++)
{
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, snapshot->h - y - yy), snapshot->format, &r1, &g1, &b1);
SDL_GetRGB(api->getpixel(snapshot, x + xx + sin((y + yy) / 4) * 4 + 1, snapshot->h - y - yy), 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)
{
}