Syncing tp_magic_example.c (indent & transliteration)

This commit is contained in:
Bill Kendrick 2024-05-10 01:29:05 -07:00
parent bd10e955a1
commit 51d47d554e
14 changed files with 2058 additions and 1988 deletions

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // Fyrir "strdup()"
#include <libintl.h> // Fyrir "gettext()"
#include <string.h> // Fyrir "strdup()"
#include <libintl.h> // Fyrir "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * skjamynd, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int x, int y);
SDL_Surface * skjamynd, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int hamur)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int hamur,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, skjamynd, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int hamur,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * skjamynd,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(skjamynd);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, skjamynd,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(skjamynd);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_staerd;
update_rect->y = old_y - example_staerd;
update_rect->w = (x + example_staerd) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* vinstri/hægri hliðrun */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* vinstri/hægri hliðrun */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * skjamynd, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * skjamynd, Uint8 staerd, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * skjamynd,
Uint8 staerd, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_staerd = staerd * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int x, int y)
SDL_Surface * skjamynd, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_staerd; yy < example_staerd; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
skjamynd->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // Fyrir "strdup()"
#include <libintl.h> // Fyrir "gettext()"
#include <string.h> // Fyrir "strdup()"
#include <libintl.h> // Fyrir "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * skjamynd, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int x, int y);
SDL_Surface * skjamynd, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int hamur)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int hamur,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, skjamynd, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int hamur,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * skjamynd,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(skjamynd);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, skjamynd,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(skjamynd);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_staerd;
update_rect->y = old_y - example_staerd;
update_rect->w = (x + example_staerd) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* vinstri/hægri hliðrun */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* vinstri/hægri hliðrun */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * skjamynd, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * skjamynd, Uint8 staerd, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * skjamynd,
Uint8 staerd, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_staerd = staerd * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * skjamynd, int x, int y)
SDL_Surface * skjamynd, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_staerd; yy < example_staerd; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
skjamynd->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}

View file

@ -9,12 +9,12 @@
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include <string.h> // For "strdup()"
#include <libintl.h> // For "gettext()"
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
#include "tp_magic_api.h" // Tux Paint "Magic" tool API header
#include "SDL_image.h" // For IMG_Load(), to load our PNG icon
#include "SDL_mixer.h" // For Mix_LoadWAV(), to load our sound effects
/* Tool Enumerations: */
@ -25,9 +25,9 @@
enum
{
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
TOOL_ONE, // Becomes '0'
TOOL_TWO, // Becomes '1'
NUM_TOOLS // Becomes '2'
};
@ -101,11 +101,11 @@ _before_ them.
*/
void example_drag(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
SDL_Surface * snapshot, int old_x, int old_y, int x, int y,
SDL_Rect * update_rect);
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y);
SDL_Surface * snapshot, int x, int y);
/* Setup Functions: */
@ -144,7 +144,8 @@ released, aka deallocated) when the user quits Tux Paint, when our
example_shutdown() function is called.
*/
int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_level)
int example_init(magic_api * api, Uint8 disabled_features,
Uint8 complexity_level)
{
int i;
char filename[1024];
@ -152,15 +153,15 @@ int example_init(magic_api * api, Uint8 disabled_features, Uint8 complexity_leve
for (i = 0; i < NUM_TOOLS; i++)
{
/*
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Assemble the filename from the "sound_filenames[]" array into a full path
to a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s", api->data_directory,
sound_filenames[i]);
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
*/
snprintf(filename, sizeof(filename), "%ssounds/magic/%s",
api->data_directory, sound_filenames[i]);
printf("Trying to load %s sound file\n", filename);
@ -200,16 +201,16 @@ SDL_Surface *example_get_icon(magic_api * api, int which)
char filename[1024];
/*
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Assemble the filename from the "icon_filenames[]" array into a full path to
a real file.
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
Use "api->data_directory" to figure out where our sounds should be. (The
"tp-magic-config --dataprefix" command would have told us when we installed
our plugin and its data.)
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use "which" (which of our tools Tux Paint is asking about) as an index
into the array.
*/
snprintf(filename, sizeof(filename), "%simages/magic/%s",
api->data_directory, icon_filenames[which]);
@ -229,31 +230,31 @@ names (labels) for the 'Magic' tool buttons.
*/
char *example_get_name(magic_api * api, int which)
{
const char *our_name_english;
const char *our_name_english;
const char *our_name_localized;
/*
Get our name from the "tool_names[]" array.
Get our name from the "tool_names[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_name_english = tool_names[which];
/*
Return a localized (aka translated) version of our name, if possible.
Return a localized (aka translated) version of our name, if possible.
We send "gettext()" the English version of the name from our array.
*/
We send "gettext()" the English version of the name from our array.
*/
our_name_localized = gettext(our_name_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_name_localized));
}
@ -267,11 +268,11 @@ where the tool should be grouped.
int example_get_group(magic_api * api, int which)
{
/*
Return our group, found in the "tool_groups[]" array.
Return our group, found in the "tool_groups[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
return (tool_groups[which]);
}
@ -302,28 +303,28 @@ char *example_get_description(magic_api * api, int which, int mode)
const char *our_desc_localized;
/*
Get our description from the "tool_descriptions[]" array.
Get our description from the "tool_descriptions[]" array.
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
We use 'which' (which of our tools Tux Paint is asking about) as an index
into the array.
*/
our_desc_english = tool_descriptions[which];
/*
Return a localized (aka translated) version of our description, if
possible.
Return a localized (aka translated) version of our description, if
possible.
We send "gettext" the English version of the description from our array.
*/
We send "gettext" the English version of the description from our array.
*/
our_desc_localized = gettext(our_desc_english);
/*
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
Finally, duplicate the string into a new section of memory, and send it to
Tux Paint. (Tux Paint keeps track of the string and will free it for us,
so we have one less thing to keep track of.)
*/
return (strdup(our_desc_localized));
}
@ -345,9 +346,9 @@ int example_requires_colors(magic_api * api, int which)
int example_modes(magic_api * api, int which)
{
/*
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
Both of our tools are painted (neither affect the full-screen), so we're
always returning 'MODE_PAINT'
*/
return MODE_PAINT;
}
@ -385,9 +386,9 @@ void example_shutdown(magic_api * api)
int i;
/*
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
Free (aka release, aka deallocate) the memory used to store the sound
effects that we loaded during example_init():
*/
for (i = 0; i < NUM_TOOLS; i++)
Mix_FreeChunk(sound_effects[i]);
}
@ -404,13 +405,13 @@ example_click(magic_api * api, int which, int mode,
SDL_Rect * update_rect)
{
/*
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
In our case, a single click (which is also the start of a drag!) is
identical to what dragging does, but just at one point, rather than across
a line.
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
So we 'cheat' here, by calling our "example_draw()" function with (x,y) for
both the beginning and end points of a line.
*/
example_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
}
@ -420,34 +421,32 @@ example_click(magic_api * api, int which, int mode,
void
example_drag(magic_api * api, int which,
SDL_Surface * canvas, SDL_Surface * snapshot,
int old_x, int old_y, int x, int y,
SDL_Rect * update_rect)
int old_x, int old_y, int x, int y, SDL_Rect * update_rect)
{
/*
Call Tux Paint's "line()" (line-traversing) function.
Call Tux Paint's "line()" (line-traversing) function.
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
It will calculate a straight line between (old_x,old_y) and (x,y). Every
N steps along that line (in this case, N is '1'), it will call _our_
function, "example_line_callback()", and send the current X,Y
coordinates along the line, as well as other useful things (which of our
'Magic' tools is being used and the current and snapshot canvases).
*/
SDL_LockSurface(snapshot);
SDL_LockSurface(canvas);
api->line((void *) api, which, canvas, snapshot,
old_x, old_y, x, y, 1,
example_line_callback);
old_x, old_y, x, y, 1, example_line_callback);
SDL_UnlockSurface(canvas);
SDL_UnlockSurface(snapshot);
/*
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
If we need to, swap the X and/or Y values, so that the coordinates
(old_x,old_y) is always the top left, and the coordinates (x,y) is
always the bottom right, so the values we put inside "update_rect" make
sense:
*/
if (old_x > x)
{
@ -466,17 +465,20 @@ example_drag(magic_api * api, int which,
/*
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
Fill in the elements of the "update_rect" SDL_Rect structure that Tux
Paint is sharing with us, therefore telling Tux Paint which part of the
canvas has been modified and should be updated.
*/
if (which == TOOL_ONE) {
if (which == TOOL_ONE)
{
update_rect->x = old_x;
update_rect->y = old_y;
update_rect->w = (x - old_x) + 1;
update_rect->h = (y - old_y) + 1;
} else {
}
else
{
update_rect->x = old_x - example_size;
update_rect->y = old_y - example_size;
update_rect->w = (x + example_size) - update_rect->x + 1;
@ -484,19 +486,18 @@ example_drag(magic_api * api, int which,
}
/*
Play the appropriate sound effect
Play the appropriate sound effect
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
We're calculating a value between 0-255 for where the mouse is
horizontally across the canvas (0 is the left, ~128 is the center, 255
is the right).
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which],
(x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */);
These are the exact values Tux Paint's "playsound()" wants, to determine
what speaker to play the sound in. (So the sound will pan from speaker
to speaker as you drag the mouse around the canvas!)
*/
api->playsound(sound_effects[which], (x * 255) / canvas->w, /* Left/right pan */
255 /* Near/far distance (loudness) */ );
}
@ -508,9 +509,9 @@ example_release(magic_api * api, int which,
SDL_Rect * update_rect)
{
/*
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
Neither of our effects do anything special when the mouse is released
from a click or click-and-drag, so there's no code here...
*/
}
@ -526,12 +527,14 @@ changes their chosen, we'll be informed of that as well.
The color comes in as RGB (red, green, and blue) values from 0 (darkest) to
255 (brightest).
*/
void example_set_color(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b, SDL_Rect * update_rect)
void example_set_color(magic_api * api, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, Uint8 r, Uint8 g, Uint8 b,
SDL_Rect * update_rect)
{
/*
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
We simply store the RGB values in the global variables we declared at
the top of this file.
*/
example_r = r;
example_g = g;
@ -551,12 +554,14 @@ that as well.
The size comes in as an unsigned integer (Uint8) between 1 and the value
returned by our example_accepted_sizes() function during setup.
*/
void example_set_size(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot, Uint8 size, SDL_Rect * update_rect)
void example_set_size(magic_api * api, int which, int mode,
SDL_Surface * canvas, SDL_Surface * snapshot,
Uint8 size, SDL_Rect * update_rect)
{
/*
Store the new size into the global variable we declared at the top of
this file.
*/
Store the new size into the global variable we declared at the top of
this file.
*/
example_size = size * 4;
}
@ -580,51 +585,51 @@ Our callback pays attention to 'which' to determine which of our plugin's
tools is currently selected.
*/
void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
SDL_Surface * snapshot, int x, int y)
SDL_Surface * snapshot, int x, int y)
{
/*
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
For technical reasons, we can't accept a pointer to the Tux Paint API's
"magic_api" struct, like the other functions do.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
Instead, we receive a 'generic' pointer (a "void *"). The line below
declares a local "magic_api" pointer variable called "api", and then
assigns it to the value of the 'generic' pointer we received.
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
The "(magic_api *)" seen below casts the generic "void *" pointer into
the 'type' of pointer we want, a pointer to a "magic_api" struct.)
*/
magic_api *api = (magic_api *) pointer;
int xx, yy;
/*
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
This function handles both of our tools, so we need to check which is
being used right now. We compare the 'which' argument that Tux Paint
sends to us with the values we enumerated above.
*/
if (which == TOOL_ONE)
{
/*
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
Tool number 1 simply draws a single pixel at the (x,y) location. It acts
as a 1x1 pixel brush.
*/
api->putpixel(canvas, x, y,
SDL_MapRGB(canvas->format,
example_r, example_g, example_b));
/*
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
We use "SDL_MapRGB()" to convert the RGB value we receive from Tux Paint
for the user's current color selection to a 'Uint32' pixel value we can
send to Tux Paint's "putpixel()" function.
*/
}
else if (which == TOOL_TWO)
{
/*
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
Tool number 2 copies a square of pixels (of the size chosen by the user)
from the opposite side of the canvas and puts it under the cursor.
*/
for (yy = -example_size; yy < example_size; yy++)
{
@ -636,14 +641,14 @@ void example_line_callback(void *pointer, int which, SDL_Surface * canvas,
snapshot->h - y - yy));
/*
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Here we have simply use Tux Paint's "getpixel()" routine to pull pixel
values from the 'snapshot', and then "putpixel()" to draw them right
into the 'canvas'.
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
Note: putpixel() and getpixel() are safe to use, even if your X,Y values
are outside of the SDL surface (e.g., negative, or greater than the
surface's width and/or height).
*/
}
}
}