Converted Blocks, Chalk, Drip, Blur, Bricks, Cartoon, Drip, Fill, Grass,
Rainbow, Smudge and Tint Magic tools to plugins.
This commit is contained in:
parent
535220e921
commit
2d4eee798f
10 changed files with 1793 additions and 0 deletions
246
magic/src/blocks_chalk_drip.c
Normal file
246
magic/src/blocks_chalk_drip.c
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
|
||||||
|
/* What tools we contain: */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOOL_BLOCKS,
|
||||||
|
TOOL_CHALK,
|
||||||
|
TOOL_DRIP,
|
||||||
|
NUM_TOOLS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * snd_effect[NUM_TOOLS];
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int blocks_chalk_drip_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/blocks.wav",
|
||||||
|
api->data_directory);
|
||||||
|
snd_effect[0] = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/chalk.wav",
|
||||||
|
api->data_directory);
|
||||||
|
snd_effect[1] = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/drip.wav",
|
||||||
|
api->data_directory);
|
||||||
|
snd_effect[2] = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int blocks_chalk_drip_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(NUM_TOOLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * blocks_chalk_drip_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
if (which == TOOL_BLOCKS)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/blocks.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
else if (which == TOOL_CHALK)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/chalk.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
else if (which == TOOL_DRIP)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/drip.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * blocks_chalk_drip_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
if (which == TOOL_BLOCKS)
|
||||||
|
return(strdup(gettext("Blocks")));
|
||||||
|
else if (which == TOOL_CHALK)
|
||||||
|
return(strdup(gettext("Chalk")));
|
||||||
|
else if (which == TOOL_DRIP)
|
||||||
|
return(strdup(gettext("Drip")));
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * blocks_chalk_drip_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
if (which == TOOL_BLOCKS)
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to turn the picture into a chalk drawing.")));
|
||||||
|
else if (which == TOOL_CHALK)
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to make the picture blocky.")));
|
||||||
|
else if (which == TOOL_DRIP)
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to make the picture drip.")));
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
int h;
|
||||||
|
SDL_Rect src, dest;
|
||||||
|
Uint8 r, g, b;
|
||||||
|
Uint32 colr;
|
||||||
|
|
||||||
|
if (which == TOOL_BLOCKS)
|
||||||
|
{
|
||||||
|
/* Put x/y on exact grid points: */
|
||||||
|
|
||||||
|
x = (x / 4) * 4;
|
||||||
|
y = (y / 4) * 4;
|
||||||
|
|
||||||
|
for (yy = y - 8; yy < y + 8; yy = yy + 4)
|
||||||
|
{
|
||||||
|
for (xx = x - 8; xx < x + 8; xx = xx + 4)
|
||||||
|
{
|
||||||
|
Uint32 pix[16];
|
||||||
|
Uint32 p_or = 0;
|
||||||
|
Uint32 p_and = ~0;
|
||||||
|
unsigned i = 16;
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
Uint32 p_tmp;
|
||||||
|
p_tmp = api->getpixel(last, xx + (i >> 2), yy + (i & 3));
|
||||||
|
p_or |= p_tmp;
|
||||||
|
p_and &= p_tmp;
|
||||||
|
pix[i] = p_tmp;
|
||||||
|
}
|
||||||
|
if (p_or == p_and) // if all pixels the same already
|
||||||
|
{
|
||||||
|
SDL_GetRGB(p_or, last->format, &r, &g, &b);
|
||||||
|
}
|
||||||
|
else // nope, must average them
|
||||||
|
{
|
||||||
|
double r_sum = 0.0;
|
||||||
|
double g_sum = 0.0;
|
||||||
|
double b_sum = 0.0;
|
||||||
|
i = 16;
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
SDL_GetRGB(pix[i], last->format, &r, &g, &b);
|
||||||
|
r_sum += api->sRGB_to_linear(r);
|
||||||
|
g_sum += api->sRGB_to_linear(g);
|
||||||
|
b_sum += api->sRGB_to_linear(b);
|
||||||
|
}
|
||||||
|
r = api->linear_to_sRGB(r_sum / 16.0);
|
||||||
|
g = api->linear_to_sRGB(g_sum / 16.0);
|
||||||
|
b = api->linear_to_sRGB(b_sum / 16.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw block: */
|
||||||
|
|
||||||
|
dest.x = xx;
|
||||||
|
dest.y = yy;
|
||||||
|
dest.w = 4;
|
||||||
|
dest.h = 4;
|
||||||
|
|
||||||
|
SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (which == TOOL_CHALK)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (yy = y - 8; yy <= y + 8; yy = yy + 4)
|
||||||
|
{
|
||||||
|
for (xx = x - 8; xx <= x + 8; xx = xx + 4)
|
||||||
|
{
|
||||||
|
dest.x = xx + ((rand() % 5) - 2);
|
||||||
|
dest.y = yy + ((rand() % 5) - 2);
|
||||||
|
dest.w = (rand() % 4) + 2;
|
||||||
|
dest.h = (rand() % 4) + 2;
|
||||||
|
|
||||||
|
colr = api->getpixel(last, clamp(0, xx, canvas->w - 1),
|
||||||
|
clamp(0, yy, canvas->h - 1));
|
||||||
|
SDL_FillRect(canvas, &dest, colr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (which == TOOL_DRIP)
|
||||||
|
{
|
||||||
|
for (xx = x - 8; xx <= x + 8; xx++)
|
||||||
|
{
|
||||||
|
h = (rand() % 8) + 8;
|
||||||
|
|
||||||
|
for (yy = y; yy <= y + h; yy++)
|
||||||
|
{
|
||||||
|
src.x = xx;
|
||||||
|
src.y = y;
|
||||||
|
src.w = 1;
|
||||||
|
src.h = 16;
|
||||||
|
|
||||||
|
dest.x = xx;
|
||||||
|
dest.y = yy;
|
||||||
|
|
||||||
|
SDL_BlitSurface(last, &src, canvas, &dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void blocks_chalk_drip_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
|
||||||
|
|
||||||
|
api->playsound(snd_effect[which], (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void blocks_chalk_drip_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
blocks_chalk_drip_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void blocks_chalk_drip_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (snd_effect[0] != NULL)
|
||||||
|
Mix_FreeChunk(snd_effect[0]);
|
||||||
|
|
||||||
|
if (snd_effect[1] != NULL)
|
||||||
|
Mix_FreeChunk(snd_effect[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void blocks_chalk_drip_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int blocks_chalk_drip_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
159
magic/src/blur.c
Normal file
159
magic/src/blur.c
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * blur_snd;
|
||||||
|
|
||||||
|
|
||||||
|
int blur_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/blur.wav",
|
||||||
|
api->data_directory);
|
||||||
|
blur_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int blur_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * blur_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/blur.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * blur_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Blur")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * blur_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to blur the picture.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_blur(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
double state[32][32][3];
|
||||||
|
unsigned i;
|
||||||
|
Uint8 r, g, b;
|
||||||
|
|
||||||
|
i = 32 * 32;
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
int iy = i >> 5;
|
||||||
|
int ix = i & 0x1f;
|
||||||
|
// is it not on the circle of radius sqrt(220) at location 16,16?
|
||||||
|
if ((ix - 16) * (ix - 16) + (iy - 16) * (iy - 16) > 220)
|
||||||
|
continue;
|
||||||
|
// it is on the circle, so grab it
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(canvas, x + ix - 16, y + iy - 16),
|
||||||
|
last->format, &r, &g, &b);
|
||||||
|
state[ix][iy][0] = api->sRGB_to_linear(r);
|
||||||
|
state[ix][iy][1] = api->sRGB_to_linear(g);
|
||||||
|
state[ix][iy][2] = api->sRGB_to_linear(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 32 * 32;
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
double lr, lg, lb; // linear red,green,blue
|
||||||
|
double weight;
|
||||||
|
int iy = i >> 5;
|
||||||
|
int ix = i & 0x1f;
|
||||||
|
int r2 = (ix - 16) * (ix - 16) + (iy - 16) * (iy - 16); // radius squared
|
||||||
|
|
||||||
|
// is it not on the circle of radius sqrt(140) at location 16,16?
|
||||||
|
if (r2 > 140)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// It is on the circle, but how strongly will it be affected?
|
||||||
|
// This is lame; we should use something like a gaussian or cosine
|
||||||
|
// via a lookup table. (inverted, because this is the center weight)
|
||||||
|
weight = r2 / 16.0 + 3.0;
|
||||||
|
|
||||||
|
// Sampling more points would be good too, though it'd be slower.
|
||||||
|
|
||||||
|
lr = state[ix][iy - 1][0]
|
||||||
|
+ state[ix - 1][iy][0] + state[ix][iy][0] * weight + state[ix +
|
||||||
|
1][iy][0]
|
||||||
|
+ state[ix][iy + 1][0];
|
||||||
|
|
||||||
|
lg = state[ix][iy - 1][1]
|
||||||
|
+ state[ix - 1][iy][1] + state[ix][iy][1] * weight + state[ix +
|
||||||
|
1][iy][1]
|
||||||
|
+ state[ix][iy + 1][1];
|
||||||
|
|
||||||
|
lb = state[ix][iy - 1][2]
|
||||||
|
+ state[ix - 1][iy][2] + state[ix][iy][2] * weight + state[ix +
|
||||||
|
1][iy][2]
|
||||||
|
+ state[ix][iy + 1][2];
|
||||||
|
|
||||||
|
lr /= weight + 4.0;
|
||||||
|
lg /= weight + 4.0;
|
||||||
|
lb /= weight + 4.0;
|
||||||
|
api->putpixel(canvas, x + ix - 16, y + iy - 16,
|
||||||
|
SDL_MapRGB(canvas->format, api->linear_to_sRGB(lr),
|
||||||
|
api->linear_to_sRGB(lg), api->linear_to_sRGB(lb)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void blur_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_blur);
|
||||||
|
|
||||||
|
api->playsound(blur_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void blur_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
blur_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blur_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (blur_snd != NULL)
|
||||||
|
Mix_FreeChunk(blur_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void blur_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int blur_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
247
magic/src/bricks.c
Normal file
247
magic/src/bricks.c
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
/* What tools we contain: */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOOL_LARGEBRICKS,
|
||||||
|
TOOL_SMALLBRICKS,
|
||||||
|
NUM_TOOLS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * brick_snd;
|
||||||
|
Uint8 bricks_r, bricks_g, bricks_b;
|
||||||
|
|
||||||
|
|
||||||
|
/* Local function prototype: */
|
||||||
|
|
||||||
|
void do_brick(magic_api * api, SDL_Surface * canvas,
|
||||||
|
int x, int y, int w, int h);
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int bricks_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/brick.wav",
|
||||||
|
api->data_directory);
|
||||||
|
brick_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int bricks_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(NUM_TOOLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * bricks_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
if (which == TOOL_LARGEBRICKS)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/largebrick.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
else if (which == TOOL_SMALLBRICKS)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/smallbrick.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * bricks_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
/* Both are named "Bricks", at the moment: */
|
||||||
|
|
||||||
|
return(strdup(gettext("Bricks")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * bricks_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
if (which == TOOL_LARGEBRICKS)
|
||||||
|
return(strdup(gettext("Click and move to draw large bricks.")));
|
||||||
|
else if (which == TOOL_SMALLBRICKS)
|
||||||
|
return(strdup(gettext("Click and move to draw small bricks.")));
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_bricks(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
|
||||||
|
// "specified" means the brick itself, w/o morter
|
||||||
|
// "nominal" means brick-to-brick (includes morter)
|
||||||
|
int specified_width, specified_height, specified_length;
|
||||||
|
int nominal_length;
|
||||||
|
int brick_x, brick_y;
|
||||||
|
|
||||||
|
int vertical_joint = 2; // between a brick and the one above/below
|
||||||
|
int horizontal_joint = 2; // between a brick and the one to the side
|
||||||
|
int nominal_width = 18;
|
||||||
|
int nominal_height = 12; // 11 to 14, for joints of 2
|
||||||
|
static unsigned char *map;
|
||||||
|
static int x_count;
|
||||||
|
static int y_count;
|
||||||
|
unsigned char *mybrick;
|
||||||
|
|
||||||
|
if (which == TOOL_LARGEBRICKS)
|
||||||
|
{
|
||||||
|
vertical_joint = 4; // between a brick and the one above/below
|
||||||
|
horizontal_joint = 4; // between a brick and the one to the side
|
||||||
|
nominal_width = 36;
|
||||||
|
nominal_height = 24; // 11 to 14, for joints of 2
|
||||||
|
}
|
||||||
|
|
||||||
|
nominal_length = 2 * nominal_width;
|
||||||
|
specified_width = nominal_width - horizontal_joint;
|
||||||
|
specified_height = nominal_height - vertical_joint;
|
||||||
|
specified_length = nominal_length - horizontal_joint;
|
||||||
|
|
||||||
|
if (!api->button_down())
|
||||||
|
{
|
||||||
|
if (map)
|
||||||
|
free(map);
|
||||||
|
// the "+ 3" allows for both ends and misalignment
|
||||||
|
x_count = (canvas->w + nominal_width - 1) / nominal_width + 3;
|
||||||
|
y_count = (canvas->h + nominal_height - 1) / nominal_height + 3;
|
||||||
|
map = calloc(x_count, y_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
brick_x = x / nominal_width;
|
||||||
|
brick_y = y / nominal_height;
|
||||||
|
|
||||||
|
mybrick = map + brick_x + 1 + (brick_y + 1) * x_count;
|
||||||
|
|
||||||
|
if ((unsigned) x < (unsigned) canvas->w
|
||||||
|
&& (unsigned) y < (unsigned) canvas->h && !*mybrick)
|
||||||
|
{
|
||||||
|
int my_x = brick_x * nominal_width;
|
||||||
|
int my_w = specified_width;
|
||||||
|
*mybrick = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
//SDL_LockSurface(canvas);
|
||||||
|
|
||||||
|
if ((brick_y ^ brick_x) & 1)
|
||||||
|
{
|
||||||
|
if (mybrick[1])
|
||||||
|
my_w = specified_length;
|
||||||
|
}
|
||||||
|
else if (mybrick[-1])
|
||||||
|
{
|
||||||
|
my_x -= nominal_width;
|
||||||
|
my_w = specified_length;
|
||||||
|
}
|
||||||
|
do_brick(api, canvas, my_x, brick_y * nominal_height,
|
||||||
|
my_w, specified_height);
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// SDL_UnlockSurface(canvas);
|
||||||
|
|
||||||
|
// upper left corner and lower right corner
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
/*
|
||||||
|
update_canvas(brick_x * nominal_width - nominal_width,
|
||||||
|
brick_y * nominal_height - vertical_joint,
|
||||||
|
brick_x * nominal_width + specified_length,
|
||||||
|
(brick_y + 1) * nominal_height);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void bricks_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_bricks);
|
||||||
|
|
||||||
|
api->playsound(brick_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void bricks_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
bricks_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void bricks_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (brick_snd != NULL)
|
||||||
|
Mix_FreeChunk(brick_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void bricks_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
bricks_r = r;
|
||||||
|
bricks_g = g;
|
||||||
|
bricks_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int bricks_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_brick(magic_api * api, SDL_Surface * canvas,
|
||||||
|
int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
SDL_Rect dest;
|
||||||
|
|
||||||
|
// brick color: 127,76,73
|
||||||
|
double ran_r = rand() / (double) RAND_MAX;
|
||||||
|
double ran_g = rand() / (double) RAND_MAX;
|
||||||
|
double base_r =
|
||||||
|
api->sRGB_to_linear(bricks_r) * 1.5 +
|
||||||
|
api->sRGB_to_linear(127) * 5.0 + ran_r;
|
||||||
|
double base_g =
|
||||||
|
api->sRGB_to_linear(bricks_g) * 1.5 +
|
||||||
|
api->sRGB_to_linear(76) * 5.0 + ran_g;
|
||||||
|
double base_b =
|
||||||
|
api->sRGB_to_linear(bricks_b) * 1.5 +
|
||||||
|
api->sRGB_to_linear(73) * 5.0 + (ran_r + ran_g * 2.0) / 3.0;
|
||||||
|
|
||||||
|
Uint8 r = api->linear_to_sRGB(base_r / 7.5);
|
||||||
|
Uint8 g = api->linear_to_sRGB(base_g / 7.5);
|
||||||
|
Uint8 b = api->linear_to_sRGB(base_b / 7.5);
|
||||||
|
|
||||||
|
dest.x = x;
|
||||||
|
dest.y = y;
|
||||||
|
dest.w = w;
|
||||||
|
dest.h = h;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, r, g, b));
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: We only play the brick sound when we actually DRAW a brick: */
|
||||||
|
|
||||||
|
api->playsound(brick_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
178
magic/src/cartoon.c
Normal file
178
magic/src/cartoon.c
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * cartoon_snd;
|
||||||
|
|
||||||
|
#define OUTLINE_THRESH 48
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int cartoon_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/cartoon.wav",
|
||||||
|
api->data_directory);
|
||||||
|
cartoon_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int cartoon_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * cartoon_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/cartoon.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * cartoon_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Cartoon")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * cartoon_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to turn the picture into a cartoon.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_cartoon(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
Uint8 r1, g1, b1, r2, g2, b2;
|
||||||
|
Uint8 r, g, b;
|
||||||
|
float hue, sat, val;
|
||||||
|
|
||||||
|
/* First, convert colors to more cartoony ones: */
|
||||||
|
|
||||||
|
for (yy = y - 16; yy < y + 16; yy = yy + 1)
|
||||||
|
{
|
||||||
|
for (xx = x - 16; xx < x + 16; xx = xx + 1)
|
||||||
|
{
|
||||||
|
if (api->in_circle(xx - x, yy - y, 16))
|
||||||
|
{
|
||||||
|
/* Get original color: */
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
|
||||||
|
|
||||||
|
api->rgbtohsv(r, g, b, &hue, &sat, &val);
|
||||||
|
|
||||||
|
val = val - 0.5;
|
||||||
|
val = val * 4;
|
||||||
|
val = val + 0.5;
|
||||||
|
|
||||||
|
if (val < 0)
|
||||||
|
val = 0;
|
||||||
|
else if (val > 1.0)
|
||||||
|
val = 1.0;
|
||||||
|
|
||||||
|
val = floor(val * 4) / 4;
|
||||||
|
hue = floor(hue * 4) / 4;
|
||||||
|
|
||||||
|
sat = floor(sat * 4) / 4;
|
||||||
|
|
||||||
|
api->hsvtorgb(hue, sat, val, &r, &g, &b);
|
||||||
|
|
||||||
|
api->putpixel(canvas, xx, yy, SDL_MapRGB(canvas->format, r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then, draw dark outlines where there's a large contrast change */
|
||||||
|
|
||||||
|
for (yy = y - 16; yy < y + 16; yy++)
|
||||||
|
{
|
||||||
|
for (xx = x - 16; xx < x + 16; xx++)
|
||||||
|
{
|
||||||
|
if (api->in_circle(xx - x, yy - y, 16))
|
||||||
|
{
|
||||||
|
/* Get original color: */
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(last, xx + 1, yy),
|
||||||
|
last->format, &r1, &g1, &b1);
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(last, xx + 1, yy + 1),
|
||||||
|
last->format, &r2, &g2, &b2);
|
||||||
|
|
||||||
|
if (abs(((r + g + b) / 3) - (r1 + g1 + b1) / 3) > OUTLINE_THRESH
|
||||||
|
|| abs(((r + g + b) / 3) - (r2 + g2 + b2) / 3) >
|
||||||
|
OUTLINE_THRESH || abs(r - r1) > OUTLINE_THRESH
|
||||||
|
|| abs(g - g1) > OUTLINE_THRESH
|
||||||
|
|| abs(b - b1) > OUTLINE_THRESH
|
||||||
|
|| abs(r - r2) > OUTLINE_THRESH
|
||||||
|
|| abs(g - g2) > OUTLINE_THRESH
|
||||||
|
|| abs(b - b2) > OUTLINE_THRESH)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, xx - 1, yy,
|
||||||
|
SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||||
|
api->putpixel(canvas, xx, yy - 1,
|
||||||
|
SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||||
|
api->putpixel(canvas, xx - 1, yy - 1,
|
||||||
|
SDL_MapRGB(canvas->format, 0, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void cartoon_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_cartoon);
|
||||||
|
|
||||||
|
api->playsound(cartoon_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void cartoon_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
cartoon_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void cartoon_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (cartoon_snd != NULL)
|
||||||
|
Mix_FreeChunk(cartoon_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void cartoon_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int cartoon_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
156
magic/src/drip.c
Normal file
156
magic/src/drip.c
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
/* What tools we contain: */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TOOL_ONE,
|
||||||
|
TOOL_TWO,
|
||||||
|
NUM_TOOLS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * snd_effect[NUM_TOOLS];
|
||||||
|
Uint8 example_r, example_g, example_b;
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int example_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/one.wav",
|
||||||
|
api->data_directory);
|
||||||
|
snd_effect[0] = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/two.wav",
|
||||||
|
api->data_directory);
|
||||||
|
snd_effect[1] = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int example_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(NUM_TOOLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * example_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
if (which == TOOL_ONE)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/one.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
else if (which == TOOL_TWO)
|
||||||
|
{
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/two.png",
|
||||||
|
api->data_directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * example_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
if (which == TOOL_ONE)
|
||||||
|
return(strdup(gettext("One")));
|
||||||
|
else if (which == TOOL_TWO)
|
||||||
|
return(strdup(gettext("Two")));
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * example_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
if (which == TOOL_ONE)
|
||||||
|
return(strdup(gettext("Tool one.")));
|
||||||
|
else
|
||||||
|
return(strdup(gettext("Tool two.")));
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
|
||||||
|
if (which == TOOL_ONE)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, x, y, SDL_MapRGB(canvas->format,
|
||||||
|
example_r,
|
||||||
|
example_g,
|
||||||
|
example_b));
|
||||||
|
}
|
||||||
|
else if (which == TOOL_TWO)
|
||||||
|
{
|
||||||
|
for (yy = -4; yy < 4; yy++)
|
||||||
|
{
|
||||||
|
for (xx = -4; xx < 4; xx++)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, x + xx, y + yy,
|
||||||
|
api->getpixel(last,
|
||||||
|
canvas->w - x - xx,
|
||||||
|
canvas->h - y - yy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
|
||||||
|
|
||||||
|
api->playsound(snd_effect[which], (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void example_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
example_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void example_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (snd_effect[0] != NULL)
|
||||||
|
Mix_FreeChunk(snd_effect[0]);
|
||||||
|
|
||||||
|
if (snd_effect[1] != NULL)
|
||||||
|
Mix_FreeChunk(snd_effect[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
example_r = r;
|
||||||
|
example_g = g;
|
||||||
|
example_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int example_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
203
magic/src/fill.c
Normal file
203
magic/src/fill.c
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * fill_snd;
|
||||||
|
Uint8 fill_r, fill_g, fill_b;
|
||||||
|
|
||||||
|
/* Local function prototypes: */
|
||||||
|
|
||||||
|
static int colors_close(magic_api * api, SDL_Surface * canvas,
|
||||||
|
Uint32 c1, Uint32 c2);
|
||||||
|
void do_flood_fill(magic_api * api, SDL_Surface * canvas, int x, int y,
|
||||||
|
Uint32 cur_colr, Uint32 old_colr);
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int fill_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/fill.wav",
|
||||||
|
api->data_directory);
|
||||||
|
fill_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int fill_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * fill_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/fill.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * fill_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Fill")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * fill_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click in the picture to fill that area with color.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void fill_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void fill_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
do_flood_fill(api, canvas, x, y, SDL_MapRGB(canvas->format,
|
||||||
|
fill_r, fill_g, fill_b),
|
||||||
|
api->getpixel(canvas, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void fill_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
Mix_FreeChunk(fill_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void fill_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
fill_r = r;
|
||||||
|
fill_g = g;
|
||||||
|
fill_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int fill_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int colors_close(magic_api * api, SDL_Surface * canvas,
|
||||||
|
Uint32 c1, Uint32 c2)
|
||||||
|
{
|
||||||
|
Uint8 r1, g1, b1, r2, g2, b2;
|
||||||
|
|
||||||
|
if (c1 == c2)
|
||||||
|
{
|
||||||
|
/* Get it over with quick, if possible! */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double r, g, b;
|
||||||
|
SDL_GetRGB(c1, canvas->format, &r1, &g1, &b1);
|
||||||
|
SDL_GetRGB(c2, canvas->format, &r2, &g2, &b2);
|
||||||
|
|
||||||
|
// use distance in linear RGB space
|
||||||
|
r = api->sRGB_to_linear(r1) - api->sRGB_to_linear(r2);
|
||||||
|
r *= r;
|
||||||
|
g = api->sRGB_to_linear(g1) - api->sRGB_to_linear(g2);
|
||||||
|
g *= g;
|
||||||
|
b = api->sRGB_to_linear(b1) - api->sRGB_to_linear(b2);
|
||||||
|
b *= b;
|
||||||
|
|
||||||
|
// easy to confuse:
|
||||||
|
// dark grey, brown, purple
|
||||||
|
// light grey, tan
|
||||||
|
// red, orange
|
||||||
|
return r + g + b < 0.04;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void do_flood_fill(magic_api * api, SDL_Surface * canvas, int x, int y,
|
||||||
|
Uint32 cur_colr, Uint32 old_colr)
|
||||||
|
{
|
||||||
|
int fillL, fillR, i, in_line;
|
||||||
|
static unsigned char prog_anim;
|
||||||
|
|
||||||
|
|
||||||
|
if (cur_colr == old_colr || colors_close(api, canvas, cur_colr, old_colr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
fillL = x;
|
||||||
|
fillR = x;
|
||||||
|
|
||||||
|
prog_anim++;
|
||||||
|
if ((prog_anim % 4) == 0)
|
||||||
|
{
|
||||||
|
api->update_progress_bar();
|
||||||
|
api->playsound(fill_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Find left side, filling along the way */
|
||||||
|
|
||||||
|
in_line = 1;
|
||||||
|
|
||||||
|
while (in_line)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, fillL, y, cur_colr);
|
||||||
|
fillL--;
|
||||||
|
|
||||||
|
in_line =
|
||||||
|
(fillL < 0) ? 0 : colors_close(api, canvas,
|
||||||
|
api->getpixel(canvas, fillL, y),
|
||||||
|
old_colr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillL++;
|
||||||
|
|
||||||
|
/* Find right side, filling along the way */
|
||||||
|
|
||||||
|
in_line = 1;
|
||||||
|
while (in_line)
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, fillR, y, cur_colr);
|
||||||
|
fillR++;
|
||||||
|
|
||||||
|
in_line = (fillR >= canvas->w) ? 0 : colors_close(api, canvas,
|
||||||
|
api->getpixel(canvas, fillR, y),
|
||||||
|
old_colr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillR--;
|
||||||
|
|
||||||
|
|
||||||
|
/* Search top and bottom */
|
||||||
|
|
||||||
|
for (i = fillL; i <= fillR; i++)
|
||||||
|
{
|
||||||
|
if (y > 0 && colors_close(api, canvas, api->getpixel(canvas, i, y - 1),
|
||||||
|
old_colr))
|
||||||
|
do_flood_fill(api, canvas, i, y - 1, cur_colr, old_colr);
|
||||||
|
|
||||||
|
if (y < canvas->h
|
||||||
|
&& colors_close(api, canvas, api->getpixel(canvas, i, y + 1), old_colr))
|
||||||
|
do_flood_fill(api, canvas, i, y + 1, cur_colr, old_colr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
199
magic/src/grass.c
Normal file
199
magic/src/grass.c
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * grass_snd;
|
||||||
|
Uint8 grass_r, grass_g, grass_b;
|
||||||
|
SDL_Surface * img_grass;
|
||||||
|
|
||||||
|
|
||||||
|
/* Local prototypes: */
|
||||||
|
|
||||||
|
void do_grass(void * ptr, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y);
|
||||||
|
|
||||||
|
static int log2int(int x);
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int grass_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/grass.wav",
|
||||||
|
api->data_directory);
|
||||||
|
grass_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/grass_data.png",
|
||||||
|
api->data_directory);
|
||||||
|
img_grass = IMG_Load(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int grass_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * grass_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/grass.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * grass_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Grass")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * grass_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Click and move to draw grass. Don’t forget the dirt!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void grass_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 4, do_grass);
|
||||||
|
|
||||||
|
api->playsound(grass_snd,
|
||||||
|
(x * 255) / canvas->w, (y * 255) / canvas->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void grass_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
grass_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void grass_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (grass_snd != NULL)
|
||||||
|
Mix_FreeChunk(grass_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void grass_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
grass_r = r;
|
||||||
|
grass_g = g;
|
||||||
|
grass_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int grass_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_grass(void * ptr, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
// grass color: 82,180,17
|
||||||
|
static int bucket;
|
||||||
|
double tmp_red, tmp_green, tmp_blue;
|
||||||
|
Uint8 r, g, b, a;
|
||||||
|
SDL_Rect src, dest;
|
||||||
|
|
||||||
|
if (!api->button_down())
|
||||||
|
bucket = 0;
|
||||||
|
bucket += (3.5 + (rand() / (double) RAND_MAX)) * 7.0;
|
||||||
|
while (bucket >= 0)
|
||||||
|
{
|
||||||
|
int rank =
|
||||||
|
log2int(((double) y / canvas->h) *
|
||||||
|
(0.99 + (rand() / (double) RAND_MAX)) * 64);
|
||||||
|
int ah = 1 << rank;
|
||||||
|
bucket -= ah;
|
||||||
|
src.x = (rand() % 4) * 64;
|
||||||
|
src.y = ah;
|
||||||
|
src.w = 64;
|
||||||
|
src.h = ah;
|
||||||
|
|
||||||
|
dest.x = x - 32;
|
||||||
|
dest.y = y - 30 + (int) ((rand() / (double) RAND_MAX) * 30);
|
||||||
|
|
||||||
|
tmp_red =
|
||||||
|
api->sRGB_to_linear(grass_r) * 2.0 +
|
||||||
|
(rand() / (double) RAND_MAX);
|
||||||
|
tmp_green =
|
||||||
|
api->sRGB_to_linear(grass_g) * 2.0 +
|
||||||
|
(rand() / (double) RAND_MAX);
|
||||||
|
tmp_blue =
|
||||||
|
api->sRGB_to_linear(grass_b) * 2.0 +
|
||||||
|
api->sRGB_to_linear(17);
|
||||||
|
|
||||||
|
for (yy = 0; yy < ah; yy++)
|
||||||
|
{
|
||||||
|
for (xx = 0; xx < 64; xx++)
|
||||||
|
{
|
||||||
|
double rd, gd, bd;
|
||||||
|
|
||||||
|
SDL_GetRGBA(api->getpixel(img_grass, xx + src.x, yy + src.y),
|
||||||
|
img_grass->format, &r, &g, &b, &a);
|
||||||
|
|
||||||
|
rd = api->sRGB_to_linear(r) * 8.0 + tmp_red;
|
||||||
|
rd = rd * (a / 255.0) / 11.0;
|
||||||
|
gd = api->sRGB_to_linear(g) * 8.0 + tmp_green;
|
||||||
|
gd = gd * (a / 255.0) / 11.0;
|
||||||
|
bd = api->sRGB_to_linear(b) * 8.0 + tmp_blue;
|
||||||
|
bd = bd * (a / 255.0) / 11.0;
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(canvas, xx + dest.x, yy + dest.y),
|
||||||
|
canvas->format, &r, &g, &b);
|
||||||
|
|
||||||
|
r =
|
||||||
|
api->linear_to_sRGB(api->sRGB_to_linear(r) * (1.0 - a / 255.0) +
|
||||||
|
rd);
|
||||||
|
g =
|
||||||
|
api->linear_to_sRGB(api->sRGB_to_linear(g) * (1.0 - a / 255.0) +
|
||||||
|
gd);
|
||||||
|
b =
|
||||||
|
api->linear_to_sRGB(api->sRGB_to_linear(b) * (1.0 - a / 255.0) +
|
||||||
|
bd);
|
||||||
|
|
||||||
|
api->putpixel(canvas, xx + dest.x, yy + dest.y,
|
||||||
|
SDL_MapRGB(canvas->format, r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this one rounds down
|
||||||
|
static int log2int(int x)
|
||||||
|
{
|
||||||
|
int y = 0;
|
||||||
|
if (x <= 1)
|
||||||
|
return 0;
|
||||||
|
x >>= 1;
|
||||||
|
while (x)
|
||||||
|
{
|
||||||
|
x >>= 1;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
147
magic/src/rainbow.c
Normal file
147
magic/src/rainbow.c
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
#define NUM_RAINBOW_COLORS 23
|
||||||
|
|
||||||
|
const int rainbow_hexes[NUM_RAINBOW_COLORS][3] = {
|
||||||
|
{255, 0, 0},
|
||||||
|
{255, 64, 0},
|
||||||
|
{255, 128, 0},
|
||||||
|
{255, 192, 0},
|
||||||
|
{255, 255, 0},
|
||||||
|
{192, 255, 0},
|
||||||
|
{128, 255, 0},
|
||||||
|
{64, 255, 0},
|
||||||
|
{0, 255, 0},
|
||||||
|
{0, 255, 64},
|
||||||
|
{0, 255, 128},
|
||||||
|
{0, 255, 192},
|
||||||
|
{0, 255, 255},
|
||||||
|
{0, 192, 255},
|
||||||
|
{0, 128, 255},
|
||||||
|
{0, 64, 255},
|
||||||
|
{64, 0, 255},
|
||||||
|
{128, 0, 255},
|
||||||
|
{192, 0, 255},
|
||||||
|
{255, 0, 255},
|
||||||
|
{255, 0, 192},
|
||||||
|
{255, 0, 128},
|
||||||
|
{255, 0, 64}
|
||||||
|
};
|
||||||
|
|
||||||
|
int rainbow_color;
|
||||||
|
Uint32 rainbow_rgb;
|
||||||
|
Mix_Chunk * rainbow_snd;
|
||||||
|
|
||||||
|
// Load our sfx:
|
||||||
|
int rainbow_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
|
||||||
|
rainbow_color = 0;
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/rainbow.wav",
|
||||||
|
api->data_directory);
|
||||||
|
rainbow_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int rainbow_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * rainbow_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/rainbow.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * rainbow_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Rainbow")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * rainbow_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(
|
||||||
|
gettext("You can draw in rainbow colors!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_example(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
int xx, yy;
|
||||||
|
|
||||||
|
for (yy = y - 16; yy < y + 16; yy++)
|
||||||
|
{
|
||||||
|
for (xx = x - 16; xx < x + 16; xx++)
|
||||||
|
{
|
||||||
|
if (api->in_circle(xx - x, yy - y, 16))
|
||||||
|
{
|
||||||
|
api->putpixel(canvas, xx, yy, rainbow_rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void rainbow_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
rainbow_color = (rainbow_color + 1) % NUM_RAINBOW_COLORS;
|
||||||
|
rainbow_rgb = SDL_MapRGB(canvas->format,
|
||||||
|
rainbow_hexes[rainbow_color][0],
|
||||||
|
rainbow_hexes[rainbow_color][1],
|
||||||
|
rainbow_hexes[rainbow_color][2]);
|
||||||
|
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_example);
|
||||||
|
|
||||||
|
api->playsound(rainbow_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void rainbow_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
rainbow_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
void rainbow_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (rainbow_snd != NULL)
|
||||||
|
Mix_FreeChunk(rainbow_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void rainbow_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int rainbow_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
127
magic/src/smudge.c
Normal file
127
magic/src/smudge.c
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * smudge_snd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int smudge_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/smudge.wav",
|
||||||
|
api->data_directory);
|
||||||
|
smudge_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int smudge_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * smudge_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/smudge.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * smudge_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Smudge")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * smudge_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to smudge the picture.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_smudge(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
static double state[32][32][3];
|
||||||
|
unsigned i = 32 * 32;
|
||||||
|
double rate = api->button_down() ? 0.5 : 0.0;
|
||||||
|
Uint8 r, g, b;
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
int iy = i >> 5;
|
||||||
|
int ix = i & 0x1f;
|
||||||
|
// is it not on the circle of radius sqrt(120) at location 16,16?
|
||||||
|
if ((ix - 16) * (ix - 16) + (iy - 16) * (iy - 16) > 120)
|
||||||
|
continue;
|
||||||
|
// it is on the circle, so grab it
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(canvas, x + ix - 16, y + iy - 16),
|
||||||
|
last->format, &r, &g, &b);
|
||||||
|
state[ix][iy][0] =
|
||||||
|
rate * state[ix][iy][0] + (1.0 - rate) * api->sRGB_to_linear(r);
|
||||||
|
state[ix][iy][1] =
|
||||||
|
rate * state[ix][iy][1] + (1.0 - rate) * api->sRGB_to_linear(g);
|
||||||
|
state[ix][iy][2] =
|
||||||
|
rate * state[ix][iy][2] + (1.0 - rate) * api->sRGB_to_linear(b);
|
||||||
|
|
||||||
|
// opacity 100% --> new data not blended w/ existing data
|
||||||
|
api->putpixel(canvas, x + ix - 16, y + iy - 16,
|
||||||
|
SDL_MapRGB(canvas->format, api->linear_to_sRGB(state[ix][iy][0]),
|
||||||
|
api->linear_to_sRGB(state[ix][iy][1]),
|
||||||
|
api->linear_to_sRGB(state[ix][iy][2])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void smudge_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_smudge);
|
||||||
|
|
||||||
|
api->playsound(smudge_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void smudge_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
smudge_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void smudge_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (smudge_snd != NULL)
|
||||||
|
Mix_FreeChunk(smudge_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void smudge_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int smudge_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
131
magic/src/tint.c
Normal file
131
magic/src/tint.c
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include "tp_magic_api.h"
|
||||||
|
#include "SDL_image.h"
|
||||||
|
#include "SDL_mixer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Our globals: */
|
||||||
|
|
||||||
|
Mix_Chunk * tint_snd;
|
||||||
|
Uint8 tint_r, tint_g, tint_b;
|
||||||
|
|
||||||
|
|
||||||
|
// No setup required:
|
||||||
|
int tint_init(magic_api * api)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/sounds/magic/tint.wav",
|
||||||
|
api->data_directory);
|
||||||
|
tint_snd = Mix_LoadWAV(fname);
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have multiple tools:
|
||||||
|
int tint_get_tool_count(magic_api * api)
|
||||||
|
{
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load our icons:
|
||||||
|
SDL_Surface * tint_get_icon(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
char fname[1024];
|
||||||
|
|
||||||
|
snprintf(fname, sizeof(fname), "%s/images/magic/tint.png",
|
||||||
|
api->data_directory);
|
||||||
|
|
||||||
|
return(IMG_Load(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our names, localized:
|
||||||
|
char * tint_get_name(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext("Tint")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our descriptions, localized:
|
||||||
|
char * tint_get_description(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return(strdup(gettext(
|
||||||
|
"Click and move the mouse around to change the picture’s color.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the effect:
|
||||||
|
|
||||||
|
void do_tint(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
magic_api * api = (magic_api *) ptr;
|
||||||
|
double rd = api->sRGB_to_linear(tint_r);
|
||||||
|
double gd = api->sRGB_to_linear(tint_g);
|
||||||
|
double bd = api->sRGB_to_linear(tint_b);
|
||||||
|
double old;
|
||||||
|
int xx, yy;
|
||||||
|
Uint8 r, g, b;
|
||||||
|
|
||||||
|
for (yy = y - 16; yy < y + 16; yy++)
|
||||||
|
{
|
||||||
|
for (xx = x - 16; xx < x + 16; xx++)
|
||||||
|
{
|
||||||
|
if (api->in_circle(xx - x, yy - y, 16))
|
||||||
|
{
|
||||||
|
/* Get original pixel: */
|
||||||
|
|
||||||
|
SDL_GetRGB(api->getpixel(last, xx, yy), last->format, &r, &g, &b);
|
||||||
|
|
||||||
|
old = api->sRGB_to_linear(r) * 0.2126 +
|
||||||
|
api->sRGB_to_linear(g) * 0.7152 +
|
||||||
|
api->sRGB_to_linear(b) * 0.0722;
|
||||||
|
|
||||||
|
api->putpixel(canvas, xx, yy,
|
||||||
|
SDL_MapRGB(canvas->format,
|
||||||
|
api->linear_to_sRGB(rd * old),
|
||||||
|
api->linear_to_sRGB(gd * old),
|
||||||
|
api->linear_to_sRGB(bd * old)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on drag:
|
||||||
|
void tint_drag(magic_api * api, int which, SDL_Surface * canvas,
|
||||||
|
SDL_Surface * last, int ox, int oy, int x, int y)
|
||||||
|
{
|
||||||
|
api->line(which, canvas, last, ox, oy, x, y, 1, do_tint);
|
||||||
|
|
||||||
|
api->playsound(tint_snd, (x * 255) / canvas->w, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Affect the canvas on click:
|
||||||
|
void tint_click(magic_api * api, int which,
|
||||||
|
SDL_Surface * canvas, SDL_Surface * last,
|
||||||
|
int x, int y)
|
||||||
|
{
|
||||||
|
tint_drag(api, which, canvas, last, x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No setup happened:
|
||||||
|
void tint_shutdown(magic_api * api)
|
||||||
|
{
|
||||||
|
if (tint_snd != NULL)
|
||||||
|
Mix_FreeChunk(tint_snd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the color from Tux Paint:
|
||||||
|
void tint_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
|
||||||
|
{
|
||||||
|
tint_r = r;
|
||||||
|
tint_g = g;
|
||||||
|
tint_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use colors:
|
||||||
|
int tint_requires_colors(magic_api * api, int which)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue