tuxpaint-pencil-sharpener/magic/src/grass.c
2007-07-08 07:53:39 +00:00

201 lines
4.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}
Uint32 grass_api_version(void) { return(TP_MAGIC_API_VERSION); }
// 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. Dont 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;
}