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