diff --git a/Makefile b/Makefile index 1fb5335b4..f066703c3 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # Various contributors (see AUTHORS.txt) # http://www.tuxpaint.org/ -# June 14, 2002 - October 3, 2022 +# June 14, 2002 - October 18, 2022 # The version number, for release: @@ -244,7 +244,6 @@ MAGIC_PREFIX:=$(DESTDIR)$(LIBDIR)/lib$(LIBDIRSUFFIX)/tuxpaint/plugins # Docs and man page: DOC_PREFIX:=$(DESTDIR)$(PREFIX)/share/doc/tuxpaint-$(VER_VERSION) -DEVDOC_PREFIX:=$(DESTDIR)$(PREFIX)/share/doc/tuxpaint-$(VER_VERSION)/tuxpaint-dev MAN_PREFIX:=$(DESTDIR)$(PREFIX)/share/man DEVMAN_PREFIX:=$(DESTDIR)$(PREFIX)/share/man @@ -649,9 +648,6 @@ install-magic-plugin-dev: src/tp_magic_api.h @install -d $(INCLUDE_PREFIX)/tuxpaint @cp src/tp_magic_api.h $(INCLUDE_PREFIX)/tuxpaint @chmod a+r,g-w,o-w $(INCLUDE_PREFIX)/tuxpaint/tp_magic_api.h - @install -d $(DEVDOC_PREFIX) - @cp -R magic/docs/* $(DEVDOC_PREFIX) - @chmod a=rX,g=rX,u=rwX $(DEVDOC_PREFIX) # Installs the various parts for the MinGW/MSYS development/testing environment. @@ -748,7 +744,6 @@ uninstall: uninstall-i18n -rm -r $(MAGIC_PREFIX) -rm -r $(INCLUDE_PREFIX)/tuxpaint -rm $(BIN_PREFIX)/tp-magic-config - -rm -r $(DEVDOC_PREFIX) -if [ "x$(BUNDLE)" != "x" ]; then \ rm -rf $(BUNDLE); \ fi diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 317e0075e..4c6598cff 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -7,7 +7,7 @@ Various contributors (see below, and AUTHORS.txt) http://www.tuxpaint.org/ -2022.October.14 (0.9.29) +2022.October.18 (0.9.29) * Improvements to "Stamp" tool: ----------------------------- * Stamps may now be rotated. @@ -162,7 +162,11 @@ http://www.tuxpaint.org/ Mark Kim * Magic tool API documentation updated to match other docs, - and allow for localization. + and allow for localization. (Maintained in "tuxpaint-docs" repo.) + Bill Kendrick + + * WIP - Example Magic tool source file ("tp_magic_example.c") + now allows for localization. (Maintained in "tuxpaint-docs" repo.) Bill Kendrick * "--verbose-version" now shows whether SDL2_Pango is being used. diff --git a/docs/Makefile b/docs/Makefile index 951dc6610..3c91620fb 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -7,7 +7,7 @@ # Bill Kendrick # bill@newbreedsoftware.com # -# Sept. 4, 2005 - September 18, 2021 +# Sept. 4, 2005 - October 18, 2022 LINKS_OPTIONS:=-dump -codepage utf8 LINKS:=links $(LINKS_OPTIONS) diff --git a/docs/en/MAGIC-API.txt b/docs/en/MAGIC-API.txt index 4673cb03d..bb3ffefe2 100644 --- a/docs/en/MAGIC-API.txt +++ b/docs/en/MAGIC-API.txt @@ -6,7 +6,7 @@ Magic Tool Plugin API Documentation Copyright © 2007-2022 by various contributors; see AUTHORS.txt. https://tuxpaint.org/ - October 3, 2022 + October 18, 2022 +----------------------------------------------------+ |Table of Contents | diff --git a/docs/en/html/MAGIC-API.html b/docs/en/html/MAGIC-API.html index c278a91bd..a2b797339 100644 --- a/docs/en/html/MAGIC-API.html +++ b/docs/en/html/MAGIC-API.html @@ -100,7 +100,7 @@

- October 3, 2022

+ October 18, 2022

@@ -1063,9 +1063,8 @@ Example Code -

- The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects. + The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects.

diff --git a/magic/docs/tp_magic_example.c b/docs/en/html/tp_magic_example.c similarity index 70% rename from magic/docs/tp_magic_example.c rename to docs/en/html/tp_magic_example.c index 3642c848a..3043d3df4 100644 --- a/magic/docs/tp_magic_example.c +++ b/docs/en/html/tp_magic_example.c @@ -1,65 +1,67 @@ /* tp_magic_example.c An example of a "Magic" tool plugin for Tux Paint - Last modified: 2021.09.21 + October 18, 2022 */ -/* Inclusion of header files: */ -/* -------------------------- */ +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ #include -#include // For "strdup()" -#include // For "gettext()" +#include // For "strdup()" +#include // 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: */ -/* ------------------ */ +/* ---------------------------------------------------------------------- */ /* What tools we contain: */ + enum { - TOOL_ONE, // Becomes '0' - TOOL_TWO, // Becomes '1' - NUM_TOOLS // Becomes '2' + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' }; /* A list of filenames for sounds and icons to load at startup: */ -const char *snd_filenames[NUM_TOOLS] = { - "one.wav", - "two.wav" +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" }; const char *icon_filenames[NUM_TOOLS] = { - "one.png", - "two.png" + "tool_one.png", + "tool_two.png" }; -// NOTE: We use a macro called "gettext_noop()" below in some arrays of -// strings (char *'s) that hold the names and descriptions of our "Magic" -// tools. This allows the strings to be localized into other languages. +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ /* A list of names for the tools */ -const char *names[NUM_TOOLS] = { +const char *tool_names[NUM_TOOLS] = { gettext_noop("A tool"), gettext_noop("Another tool") }; -/* How to group the tools with other similar tools, - within the 'Magic' selector: */ +/* How to group the tools with other similar tools, within the 'Magic' selector: */ -const int groups[NUM_TOOLS] = { +const int tool_groups[$NUM_TOOLS] = { MAGIC_TYPE_PAINTING, MAGIC_TYPE_DISTORTS }; @@ -67,7 +69,7 @@ const int groups[NUM_TOOLS] = { /* A list of descriptions of the tools */ -const char *descs[NUM_TOOLS] = { +const char *tool_descriptions[NUM_TOOLS] = { gettext_noop("This is example tool number 1."), gettext_noop("This is example tool number 2.") }; @@ -75,42 +77,46 @@ const char *descs[NUM_TOOLS] = { /* Our global variables: */ -/* --------------------- */ +/* ---------------------------------------------------------------------- */ /* Sound effects: */ -Mix_Chunk *snd_effect[NUM_TOOLS]; +Mix_Chunk *sound_effects[NUM_TOOLS]; -/* The current color (an "RGB" value) the user has selected in Tux Paint: */ -Uint8 example_r, example_g, example_b; +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; /* Our local function prototypes: */ -/* ------------------------------ */ +/* ---------------------------------------------------------------------- */ -// These functions are called by other functions within our plugin, -// so we provide a 'prototype' of them, so the compiler knows what -// they accept and return. This lets us use them in other functions -// that are declared _before_ them. +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ void example_drag(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect); -void example_line_callback(void *ptr, int which, SDL_Surface * canvas, +void example_line_callback(void *pointer, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y); /* Setup Functions: */ -/* ---------------- */ +/* ---------------------------------------------------------------------- */ -// API Version check -// -// The running copy of Tux Paint that has loaded us first asks us what -// version of the Tux Paint "Magic" tool plugin API we were built against. -// If it deems us compatible, we'll be used! -// -// All we need to do here is return "TP_MAGIC_API_VERSION", -// which is #define'd in tp_magic_api.h. +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ Uint32 example_api_version(void) { @@ -118,42 +124,44 @@ Uint32 example_api_version(void) } -// Initialization -// -// This happens once, when Tux Paint starts up and is loading all of the -// "Magic" tool plugins. (Assuming what we returned from api_version() was -// acceptable!) -// -// All we're doing in this example is loading our sound effects, -// which we'll use later (in click(), drag() and release()) -// when the user is using our Magic tools. -// -// The memory we allocate here to store the sounds will be -// freed (aka released, aka deallocated) when the user quits Tux Paint, -// when our shutdown() function is called. +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ int example_init(magic_api * api) { int i; - char fname[1024]; + char filename[1024]; for (i = 0; i < NUM_TOOLS; i++) { - // Assemble the filename from the "snd_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.) + /* + Assemble the filename from the "sound_filenames[]" array into a full path + to a real file. - snprintf(fname, sizeof(fname), "%s/sounds/magic/%s", api->data_directory, - snd_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.) - printf("Trying to load %s sound file\n", fname); + snprintf(filename, sizeof(filename), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); // Try to load the file! - - snd_effect[i] = Mix_LoadWAV(fname); + sound_effects[i] = Mix_LoadWAV(filename); } return (1); @@ -238,51 +246,58 @@ char *example_get_name(magic_api * api, int which) } -// Report our "Magic" tool groups -// -// When Tux Paint is starting up and loading plugins, it asks us to -// specify where the tool should be grouped. +/* +Report our 'Magic' tool groups +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ int example_get_group(magic_api * api, int which) { - // Return our group from the "groups[]" array. - // - // We use 'which' (which of our tools Tux Paint is asking about) - // as an index into the array. + /* + Return our group, found in the "tool_groups[]" array. - return (groups[which]); + We use 'which' (which of our tools Tux Paint is asking about) as an index + into the array. + */ + return (tool_groups[which]); } -// Report our "Magic" tool descriptions -// -// When Tux Paint is starting up and loading plugins, it asks us to -// provide names (labels) for the "Magic" tool buttons. +/* +Report our 'Magic' tool descriptions +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ char *example_get_description(magic_api * api, int which, int mode) { const char *our_desc_english; const char *our_desc_localized; - // Get our desc from the "descs[]" array. - // - // We use 'which' (which of our tools Tux Paint is asking about) - // as an index into the array. + /* + Get our description from the "tool_descriptions[]" array. - our_desc_english = descs[which]; + 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. - // - // We send "gettext()" the English version of the description from our array. + /* + Return a localized (aka translated) version of our description, if + possible. + 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)); } @@ -291,7 +306,7 @@ char *example_get_description(magic_api * api, int which, int mode) int example_requires_colors(magic_api * api, int which) { - // Both of our tools accept colors, so we're always returning '1' (for "true") + // Both of our tools accept colors, so we're always returning '1' (for 'true') return 1; } @@ -301,34 +316,36 @@ 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; } -// Shut down -// -// Tux Paint is quitting. When it quits, it asks all of the plugins -// to 'clean up' after themselves. We, for example, loaded some sound -// effects at startup (in our init() function), so we should free the -// memory used by them now. +/* +Shut down +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ 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 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(snd_effect[i]); + Mix_FreeChunk(sound_effects[i]); } /* Functions that respond to events in Tux Paint: */ -/* ---------------------------------------------- */ +/* ---------------------------------------------------------------------- */ // Affect the canvas on click: @@ -446,7 +463,7 @@ void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) /* The Magic Effect Routines! */ -/* -------------------------- */ +/* ---------------------------------------------------------------------- */ // Our "callback" function // diff --git a/docs/en/tp_magic_example.c b/docs/en/tp_magic_example.c new file mode 100644 index 000000000..3043d3df4 --- /dev/null +++ b/docs/en/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + October 18, 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/es_ES.UTF-8/MAGIC-API.txt b/docs/es_ES.UTF-8/MAGIC-API.txt index 60e94a280..b2cfcf836 100644 --- a/docs/es_ES.UTF-8/MAGIC-API.txt +++ b/docs/es_ES.UTF-8/MAGIC-API.txt @@ -6,7 +6,7 @@ Magic Tool Plugin API Documentation Copyright © 2007-2022 by various contributors; see AUTHORS.txt. https://tuxpaint.org/ - octubre 3, 2022 + octubre 18, 2022 +----------------------------------------------------+ |Table of Contents | diff --git a/docs/es_ES.UTF-8/html/MAGIC-API.html b/docs/es_ES.UTF-8/html/MAGIC-API.html index 9c6e73dfd..241ed2787 100644 --- a/docs/es_ES.UTF-8/html/MAGIC-API.html +++ b/docs/es_ES.UTF-8/html/MAGIC-API.html @@ -100,7 +100,7 @@

- octubre 3, 2022

+ octubre 18, 2022

@@ -1063,9 +1063,8 @@ Example Code -

- The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects. + The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects.

diff --git a/docs/es_ES.UTF-8/html/tp_magic_example.c b/docs/es_ES.UTF-8/html/tp_magic_example.c new file mode 100644 index 000000000..a354aeb24 --- /dev/null +++ b/docs/es_ES.UTF-8/html/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + octubre 18, 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/es_ES.UTF-8/tp_magic_example.c b/docs/es_ES.UTF-8/tp_magic_example.c new file mode 100644 index 000000000..a354aeb24 --- /dev/null +++ b/docs/es_ES.UTF-8/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + octubre 18, 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/fr_FR.UTF-8/MAGIC-API.txt b/docs/fr_FR.UTF-8/MAGIC-API.txt index f9f38473e..343e41230 100644 --- a/docs/fr_FR.UTF-8/MAGIC-API.txt +++ b/docs/fr_FR.UTF-8/MAGIC-API.txt @@ -6,7 +6,7 @@ Magic Tool Plugin API Documentation Copyright © 2007-2022 by various contributors; see AUTHORS.txt. https://tuxpaint.org/ - octobre 3, 2022 + octobre 18, 2022 +----------------------------------------------------+ |Table of Contents | diff --git a/docs/fr_FR.UTF-8/html/MAGIC-API.html b/docs/fr_FR.UTF-8/html/MAGIC-API.html index e178378fc..57676fc40 100644 --- a/docs/fr_FR.UTF-8/html/MAGIC-API.html +++ b/docs/fr_FR.UTF-8/html/MAGIC-API.html @@ -100,7 +100,7 @@

- octobre 3, 2022

+ octobre 18, 2022

@@ -1063,9 +1063,8 @@ Example Code -

- The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects. + The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects.

diff --git a/docs/fr_FR.UTF-8/html/tp_magic_example.c b/docs/fr_FR.UTF-8/html/tp_magic_example.c new file mode 100644 index 000000000..ecb147f16 --- /dev/null +++ b/docs/fr_FR.UTF-8/html/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + octobre 18, 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/fr_FR.UTF-8/tp_magic_example.c b/docs/fr_FR.UTF-8/tp_magic_example.c new file mode 100644 index 000000000..ecb147f16 --- /dev/null +++ b/docs/fr_FR.UTF-8/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + octobre 18, 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/gl_ES.UTF-8/MAGIC-API.txt b/docs/gl_ES.UTF-8/MAGIC-API.txt index b76f89a3d..01dfd28d0 100644 --- a/docs/gl_ES.UTF-8/MAGIC-API.txt +++ b/docs/gl_ES.UTF-8/MAGIC-API.txt @@ -6,7 +6,7 @@ Magic Tool Plugin API Documentation Copyright © 2007-2022 by various contributors; see AUTHORS.txt. https://tuxpaint.org/ - Outubro 3, 2022 + Outubro 18, 2022 +----------------------------------------------------+ |Table of Contents | diff --git a/docs/gl_ES.UTF-8/html/MAGIC-API.html b/docs/gl_ES.UTF-8/html/MAGIC-API.html index 36ea97d9a..a6bb4d13c 100644 --- a/docs/gl_ES.UTF-8/html/MAGIC-API.html +++ b/docs/gl_ES.UTF-8/html/MAGIC-API.html @@ -100,7 +100,7 @@

- Outubro 3, 2022

+ Outubro 18, 2022

@@ -1063,9 +1063,8 @@ Example Code -

- The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects. + The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects.

diff --git a/docs/gl_ES.UTF-8/html/tp_magic_example.c b/docs/gl_ES.UTF-8/html/tp_magic_example.c new file mode 100644 index 000000000..9f8a5be07 --- /dev/null +++ b/docs/gl_ES.UTF-8/html/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + 18 de Outubro de 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/gl_ES.UTF-8/tp_magic_example.c b/docs/gl_ES.UTF-8/tp_magic_example.c new file mode 100644 index 000000000..9f8a5be07 --- /dev/null +++ b/docs/gl_ES.UTF-8/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + 18 de Outubro de 2022 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/ja_JP.UTF-8/MAGIC-API.txt b/docs/ja_JP.UTF-8/MAGIC-API.txt index 721a9a989..b74292e2d 100644 --- a/docs/ja_JP.UTF-8/MAGIC-API.txt +++ b/docs/ja_JP.UTF-8/MAGIC-API.txt @@ -6,7 +6,7 @@ Magic Tool Plugin API Documentation Copyright © 2007-2022 by various contributors; see AUTHORS.txt. https://tuxpaint.org/ - 10月 3, 2022 + 10月 18, 2022 +----------------------------------------------------+ |Table of Contents | diff --git a/docs/ja_JP.UTF-8/html/MAGIC-API.html b/docs/ja_JP.UTF-8/html/MAGIC-API.html index 1e60cdd99..968a9b4c8 100644 --- a/docs/ja_JP.UTF-8/html/MAGIC-API.html +++ b/docs/ja_JP.UTF-8/html/MAGIC-API.html @@ -100,7 +100,7 @@

- 10月 3, 2022

+ 10月 18, 2022

@@ -1063,9 +1063,8 @@ Example Code -

- The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects. + The C source file "tp_magic_example.c" contains a complete example of a plugin with multiple simple effects.

diff --git a/docs/ja_JP.UTF-8/html/tp_magic_example.c b/docs/ja_JP.UTF-8/html/tp_magic_example.c new file mode 100644 index 000000000..fa16f3128 --- /dev/null +++ b/docs/ja_JP.UTF-8/html/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + 2022年10月18日 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/docs/ja_JP.UTF-8/tp_magic_example.c b/docs/ja_JP.UTF-8/tp_magic_example.c new file mode 100644 index 000000000..fa16f3128 --- /dev/null +++ b/docs/ja_JP.UTF-8/tp_magic_example.c @@ -0,0 +1,579 @@ +/* tp_magic_example.c + + An example of a "Magic" tool plugin for Tux Paint + 2022年10月18日 +*/ + + +/* Inclusion of header files */ +/* ---------------------------------------------------------------------- */ + +#include +#include // For "strdup()" +#include // 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 + + +/* Tool Enumerations: */ +/* ---------------------------------------------------------------------- */ + +/* What tools we contain: */ + + +enum +{ + TOOL_ONE, // Becomes '0' + TOOL_ONE, // Becomes '1' + NUM_TOOLS // Becomes '2' +}; + + +/* A list of filenames for sounds and icons to load at startup: */ + +const char *sound_filenames[NUM_TOOLS] = { + "tool_one.wav", + "tool_two.wav" +}; + +const char *icon_filenames[NUM_TOOLS] = { + "tool_one.png", + "tool_two.png" +}; + + +/* +NOTE: We use a macro called "gettext_noop()" below in some arrays of +strings (char *'s) that hold the names and descriptions of our "Magic" +tools. This allows the strings to be localized into other languages. +*/ + + +/* A list of names for the tools */ + +const char *tool_names[NUM_TOOLS] = { + gettext_noop("A tool"), + gettext_noop("Another tool") +}; + + +/* How to group the tools with other similar tools, within the 'Magic' selector: */ + +const int tool_groups[$NUM_TOOLS] = { + MAGIC_TYPE_PAINTING, + MAGIC_TYPE_DISTORTS +}; + + +/* A list of descriptions of the tools */ + +const char *tool_descriptions[NUM_TOOLS] = { + gettext_noop("This is example tool number 1."), + gettext_noop("This is example tool number 2.") +}; + + + +/* Our global variables: */ +/* ---------------------------------------------------------------------- */ + +/* Sound effects: */ +Mix_Chunk *sound_effects[NUM_TOOLS]; + +/* The current color (an "RGB" -- red, green, blue -- value) the user has selected in Tux Paint: */ +Uint8 example_r, $example_g, $example_b; + + +/* Our local function prototypes: */ +/* ---------------------------------------------------------------------- */ + +/* +These functions are called by other functions within our plugin, so we +provide a 'prototype' of them, so the compiler knows what they accept and +return. This lets us use them in other functions that are declared +_before_ them. +*/ + +void example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, 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); + + +/* Setup Functions: */ +/* ---------------------------------------------------------------------- */ + +/* +API Version check + +The running copy of Tux Paint that has loaded us first asks us what version +of the Tux Paint 'Magic' tool plugin API we were built against. If it +deems us compatible, we'll be used! + +All we need to do here is return "TP_MAGIC_API_VERSION", which is defined +(#define) in the header file "tp_magic_api.h". +*/ + +Uint32 example_api_version(void) +{ + return (TP_MAGIC_API_VERSION); +} + + +/* +Initialization + +This happens once, when Tux Paint starts up and is loading all of the +'Magic' tool plugins. (Assuming what we returned from api_version was +acceptable!) + +All we're doing in this example is loading our sound effects, which we'll +use later (in example_click(), example_drag(), and example_release()) when +the user is using our Magic tools. + +The memory we allocate here to store the sounds will be freed (aka +released, aka deallocated) when the user quits Tux Paint, when our +example_shutdown() function is called. +*/ + +int example_init(magic_api * api) +{ + int i; + char filename[1024]; + + for (i = 0; i < NUM_TOOLS; i++) + { + /* + 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), "%s/sounds/magic/%s", api->data_directory, + sound_filenames[i]); + + printf("Trying to load %s sound file\n", filename); + + // Try to load the file! + sound_effects[i] = Mix_LoadWAV(filename); + } + + return (1); +} + + +// Report our tool count +// +// Tux Paint needs to know how many "Magic" tools we'll be providing. +// Return that number here. (We simply grab the value of "NUM_TOOLS" +// from our 'enum' above!) +// +// When Tux Paint is starting up and loading plugins, it will call +// some of the following setup functions once for each tool we report. + +int example_get_tool_count(magic_api * api) +{ + return (NUM_TOOLS); +} + + +// Load icons +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide icons for the "Magic" tool buttons. + +SDL_Surface *example_get_icon(magic_api * api, int which) +{ + char fname[1024]; + + // 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.) + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + snprintf(fname, sizeof(fname), "%s/images/magic/%s.png", + api->data_directory, icon_filenames[which]); + + + // Try to load the image, and return the results to Tux Paint: + + return (IMG_Load(fname)); +} + + +// Report our "Magic" tool names +// +// When Tux Paint is starting up and loading plugins, it asks us to +// provide 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_localized; + + // Get our name from the "names[]" array. + // + // We use 'which' (which of our tools Tux Paint is asking about) + // as an index into the array. + + our_name_english = names[which]; + + + // Return a localized (aka translated) version of our name, + // if possible. + // + // 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.) + + return (strdup(our_name_localized)); +} + + +/* +Report our 'Magic' tool groups + +When Tux Paint is starting up and loading plugins, it asks us to specify +where the tool should be grouped. +*/ +int example_get_group(magic_api * api, int which) +{ + /* + 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. + */ + return (tool_groups[which]); +} + + +/* +Report our 'Magic' tool descriptions + +When Tux Paint is starting up and loading plugins, it asks us to provide +descriptions of each 'Magic' tool. +*/ +char *example_get_description(magic_api * api, int which, int mode) +{ + const char *our_desc_english; + const char *our_desc_localized; + + /* + 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. + */ + our_desc_english = tool_descriptions[which]; + + + /* + Return a localized (aka translated) version of our description, if + possible. + + 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.) + */ + + return (strdup(our_desc_localized)); +} + +// Report whether we accept colors + +int example_requires_colors(magic_api * api, int which) +{ + // Both of our tools accept colors, so we're always returning '1' (for 'true') + + return 1; +} + + +// Report what modes we work in + +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' + + return MODE_PAINT; +} + + +/* +Shut down + +Tux Paint is quitting. When it quits, it asks all of the plugins to 'clean +up' after themselves. We, for example, loaded some sound effects at +startup (in our example_init() function), so we should free the memory used +by them now. +*/ +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(): + */ + for (i = 0; i < NUM_TOOLS; i++) + Mix_FreeChunk(sound_effects[i]); +} + + +/* Functions that respond to events in Tux Paint: */ +/* ---------------------------------------------------------------------- */ + +// Affect the canvas on click: + +void +example_click(magic_api * api, int which, int mode, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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. + // + // So we 'cheat' here, by calling our 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); +} + + +// Affect the canvas on drag: + +void +example_drag(magic_api * api, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int ox, int oy, int x, int y, + SDL_Rect * update_rect) +{ + // Call Tux Paint's "line()" function. + // + // It will calculate a straight line between (ox,ox) 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). + + api->line((void *) api, which, canvas, snapshot, ox, oy, x, y, 1, + example_line_callback); + + + // If we need to, swap the X and/or Y values, so that + // (ox,oy) is always the top left, and (x,y) is always the bottom right, + // so the values we put inside "update_rect" make sense: + + if (ox > x) + { + int tmp = ox; + + ox = x; + x = tmp; + } + if (oy > y) + { + int tmp = oy; + + oy = y; + y = tmp; + } + + + // Fill in the elements of the "update_rect" SDL_Rect structure + // that Tux Paint is sharing with us. + + update_rect->x = ox - 4; + update_rect->y = oy - 4; + update_rect->w = (x + 4) - update_rect->x; + update_rect->h = (y + 4) - update_rect->h; + + + // Play the appropriate sound effect + // + // We're calculating a value between 0-255 for where the mouse is + // 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(snd_effect[which], (x * 255) / canvas->w, // pan + 255); // distance +} + + +// Affect the canvas on release: + +void +example_release(magic_api * api, int which, + SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, + 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... +} + + +// Accept colors +// +// When any of our "Magic" tools are activated by the user, +// if that tool accepts colors, the current color selection is sent to us. +// +// Additionally, if one of our color-accepting tools is active when the +// user changes colors, we'll be informed of that, as well. +// +// The color comes in as RGB values. + +void example_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b) +{ + // We simply store the RGB values in the global variables we + // declared at the top of this file. + + example_r = r; + example_g = g; + example_b = b; +} + + +/* The Magic Effect Routines! */ +/* ---------------------------------------------------------------------- */ + +// Our "callback" function +// +// We do the 'work' in this callback. Our plugin file has just one. +// Some "Magic" tool plugins may have more, depending on the tools they're +// providing. Some have none (since they're not click-and-drag +// painting-style tools). +// +// Our callback function gets called once for every point along a line between +// the mouse's previous and current position, as it's being dragged. +// +// It pays attention to 'which' to determine which of our plugin's tools +// is currently selected. + +void example_line_callback(void *ptr, int which, SDL_Surface * canvas, + SDL_Surface * snapshot, int x, int y) +{ + // For technical reasons, we can't accept a pointer to the "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. + // + // (The "(magic_api *)" casts the generic pointer into the 'type' of + // pointer we want, a pointer to a "magic_api".) + magic_api *api = (magic_api *) ptr; + 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. + + if (which == TOOL_ONE) + { + // Tool number 1 simply draws a single pixel at the (x,y) location. + // It's 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. + } + else if (which == TOOL_TWO) + { + // Tool number 2 copies an 8x8 square of pixels from the opposite side + // of the canvas and puts it under the cursor + + for (yy = -4; yy < 4; yy++) + { + for (xx = -4; xx < 4; xx++) + { + api->putpixel(canvas, x + xx, y + yy, + api->getpixel(snapshot, canvas->w - x - xx, + canvas->h - y - yy)); + + // We 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 or height). + } + } + } +} + +// Switch-In event +// +// This happens whenever a Magic tool is enabled, either because the +// user just selected it, or they just came back to "Magic" after using +// another tool (e.g., Brush or Text), and this was the most-recently +// selected Magic tool. +// +// (This also applies to momentary tools, like +// Undo and Redo, and image-changing tools such as New and Open.) +// +// It also happens when a Magic tool's mode changes (it first +// receives a 'switchout()', below, for the old mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchin(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} + +// Switch-Out event +// +// This happens whenever a Magic tool is disabled, either because the +// user selected a different Magic tool, or they selected a completely +// different tool (e.g., Brush or Text). +// +// (This also applies to momentary tools, like Undo and Redo, and +// image-changing tools such as New and Open, in which case the +// switchin() function will be called moments later.) +// +// It also happens when a Magic tool's mode changes (it then +// receives a 'switchin()', above, for the new mode). +// +// Our example doesn't do anything when we switch to, or away from, our +// Magic tools, so we just do nothing here. + +void example_switchout(magic_api * api, int which, int mode, + SDL_Surface * canvas) +{ +} diff --git a/magic/docs/.indent.pro b/magic/docs/.indent.pro deleted file mode 120000 index bd43730f5..000000000 --- a/magic/docs/.indent.pro +++ /dev/null @@ -1 +0,0 @@ -../../src/.indent.pro \ No newline at end of file