Added support for animated brushes.

This commit is contained in:
William Kendrick 2006-09-04 06:26:12 +00:00
parent 44f0d728ed
commit 609a8d5104
5 changed files with 139 additions and 32 deletions

View file

@ -1 +1 @@
frames=7
frames=6

View file

@ -9,7 +9,7 @@ http://www.newbreedsoftware.com/tuxpaint/
$Id$
2006.September.2 (0.9.16)
2006.September.3 (0.9.16)
* Interface improvements:
-----------------------
* New slideshow tool! ("Slides", available in "Open" dialog.)
@ -68,6 +68,14 @@ $Id$
* Round erasers added.
* Brushes may be animated.
(Create an image (W*N) x H in size (where N is number of frames),
then create a ".dat" file for the brush containing "frames=N".
* New Brushes:
------------
* Vines (animated)
* New Starter Images:
-------------------
* Shipwreck

View file

@ -8,7 +8,7 @@
bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
June 14, 2002 - March 12, 2006
June 14, 2002 - September 3, 2006
--------------------------------------------------------------------------
@ -119,16 +119,43 @@ Where Files Go
Brushes
The brushes used for drawing with the 'Brush' and 'Lines' tools in
Tux Paint are simply greyscale PNG images.
Tux Paint are simply PNG image files.
The alpha (transparency) of the PNG image is used to determine the shape
of the brush, which means that the shape can be 'anti-aliased' and even
partially-transparent!
Greyscale pixels in the brush PNG will be drawn using the
currently-selected color in Tux Paint. Color pixels will be tinted.
Brush images should be no wider than 40 pixels across and no taller than
40 pixels high. (i.e., the maximum size can be 40 x 40.)
Just place them in the "brushes" directory.
Brush Options
Aside from a graphical shape, brushes can also be given other
attributes. To do this, you need to create a 'data file' for the
brush.
A brush data file is simply a text file containing the options.
The file has the same name as the PNG image, but a ".dat" extension.
(e.g., "brush.png"'s data file is the text file "brush.dat" in the
same directory.)
Animated Brushes
As of Tux Paint version 0.9.16, you may now create animated brushes.
As the brush is drawn, each frame of the animation is displayed.
Lay each frame out across a wide PNG image. For example, if your
brush is 30x30 and you have 5 frames, the image should be 150x30.
Add a line containing the line "frames=N" to the brush's data file,
where N is the number of frames in the brush.
Place the brush image PNGs (and any data text files) in the "brushes"
directory.
Note: If your new brushes all come out as solid squares or rectangles,
it's because you forgot to use alpha transparency! See the documentation

View file

@ -23,7 +23,7 @@ New Breed Software</p>
<p><a href="mailto:bill@newbreedsoftware.com">bill@newbreedsoftware.com</a><br>
<a href="http://www.newbreedsoftware.com/tuxpaint/">http://www.newbreedsoftware.com/tuxpaint/</a></p>
<p>June 14, 2002 - March 12, 2006</p>
<p>June 14, 2002 - September 3, 2006</p>
</center>
<hr size=2 noshade>
@ -187,7 +187,7 @@ effect.</p>
<h2>Brushes</h2>
<blockquote>
<p>The brushes used for drawing with the 'Brush' and 'Lines' tools in
Tux&nbsp;Paint are simply greyscale PNG images.</p>
Tux&nbsp;Paint are simply PNG image files.</p>
<img src="images/brush_edit.png" width=123 height=147 alt="" align=right>
@ -195,11 +195,45 @@ effect.</p>
of the brush, which means that the shape can be 'anti-aliased' and even
partially-transparent!</p>
<p>Greyscale pixels in the brush PNG will be drawn using the
currently-selected color in Tux&nbsp;Paint. Color pixels will be
tinted.</p>
<p>Brush images should be no wider than 40&nbsp;pixels across and
no taller than 40&nbsp;pixels high. (i.e., the maximum size
can be 40&nbsp;x&nbsp;40.)</p>
<p>Just place them in the "<code><b>brushes</b></code>" directory.</p>
<h3>Brush Options</h3>
<blockquote>
<p>Aside from a graphical shape, brushes can also be given other
attributes. To do this, you need to create a 'data&nbsp;file'
for the brush.</p>
<p>A brush data file is simply a text file containing the options.</p>
<p>The file has the same name as the PNG image, but a "<code>.dat</code>"
extension. (e.g., "<code>brush.png</code>"'s data file is the text
file "<code>brush.dat</code>" in the same directory.)</p>
<h4>Animated Brushes</h4>
<blockquote>
<p>As of Tux&nbsp;Paint version 0.9.16, you may now create animated
brushes. As the brush is drawn, each frame of the animation is
displayed.</p>
<p>Lay each frame out across a wide PNG image. For example,
if your brush is 30x30 and you have 5 frames, the image should
be 150x30.</p>
<p>Add a line containing the line "<code><b>frames=<i>N</i></b></code>"
to the brush's data file, where <i>N</i> is the number of frames
in the brush.</p>
</blockquote>
</blockquote>
<p>Place the brush image PNGs (and any data text files) in the
"<code><b>brushes</b></code>" directory.</p>
<p>Note: If your new brushes all come out as solid squares or rectangles,
it's because you forgot to use alpha transparency! See the documentation

View file

@ -22,7 +22,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(See COPYING.txt)
June 14, 2002 - August 28, 2006
June 14, 2002 - September 3, 2006
$Id$
*/
@ -972,7 +972,8 @@ static SDL_Surface *img_color_btn_off;
static int colors_are_selectable;
static SDL_Surface *img_cur_brush;
static int brush_counter, rainbow_color;
int img_cur_brush_w, img_cur_brush_h, img_cur_brush_frames;
static int brush_counter, rainbow_color, brush_frame;
#define NUM_ERASERS 12 /* How many sizes of erasers
(from ERASER_MIN to _MAX as squares, then again
@ -1070,6 +1071,9 @@ static void rect_xor(int x1, int y1, int x2, int y2);
static void draw_blinking_cursor(void);
static void hide_blinking_cursor(void);
void reset_brush_counter_and_frame(void);
void reset_brush_counter(void);
#ifdef LOW_QUALITY_STAMP_OUTLINE
#define stamp_xor(x,y) rect_xor( \
(x) - (CUR_STAMP_W+1)/2, \
@ -2635,10 +2639,10 @@ static void mainloop(void)
rec_undo_buffer();
/* (Arbitrarily large, so we draw once now) */
brush_counter = 999;
reset_brush_counter();
brush_draw(old_x, old_y, old_x, old_y, 1);
playsound(screen, 0, SND_PAINT1 + (img_cur_brush->w) / 12, 1,
playsound(screen, 0, SND_PAINT1 + (img_cur_brush_w) / 12, 1,
event.button.x, SNDDIST_NEAR);
}
else if (cur_tool == TOOL_STAMP)
@ -2667,7 +2671,7 @@ static void mainloop(void)
line_start_y = old_y;
/* (Arbitrarily large, so we draw once now) */
brush_counter = 999;
reset_brush_counter();
brush_draw(old_x, old_y, old_x, old_y, 1);
@ -2697,7 +2701,7 @@ static void mainloop(void)
/* Draw the shape with the brush! */
/* (Arbitrarily large...) */
brush_counter = 999;
reset_brush_counter();
playsound(screen, 1, SND_LINE_END, 1, event.button.x,
SNDDIST_NEAR);
@ -2728,7 +2732,7 @@ static void mainloop(void)
/* (Arbitrarily large, so we draw once now) */
brush_counter = 999;
reset_brush_counter();
if (cur_magic != MAGIC_FILL)
{
@ -2975,7 +2979,7 @@ static void mainloop(void)
if (cur_tool == TOOL_LINES)
{
/* (Arbitrarily large, so we draw once now) */
brush_counter = 999;
reset_brush_counter();
brush_draw(line_start_x, line_start_y,
event.button.x - r_canvas.x,
@ -3028,7 +3032,7 @@ static void mainloop(void)
}
else
{
brush_counter = 999; /* arbitrarily large... */
reset_brush_counter();
playsound(screen, 1, SND_LINE_END, 1, event.button.x,
@ -3191,7 +3195,7 @@ static void mainloop(void)
brush_draw(old_x, old_y, new_x, new_y, 1);
playsound(screen, 0, SND_PAINT1 + (img_cur_brush->w) / 12, 0,
playsound(screen, 0, SND_PAINT1 + (img_cur_brush_w) / 12, 0,
event.button.x, SNDDIST_NEAR);
}
else if (cur_tool == TOOL_LINES)
@ -3483,23 +3487,43 @@ static void brush_draw(int x1, int y1, int x2, int y2, int update)
}
}
void reset_brush_counter_and_frame(void)
{
brush_counter = 999;
brush_frame = 0;
}
void reset_brush_counter(void)
{
brush_counter = 999;
}
/* Draw the current brush in the current color: */
static void blit_brush(int x, int y)
{
SDL_Rect dest;
SDL_Rect src, dest;
brush_counter++;
if (brush_counter >= (img_cur_brush->h / 4))
if (brush_counter >= (img_cur_brush_h / 4))
{
brush_counter = 0;
brush_frame++;
if (brush_frame > img_cur_brush_frames)
brush_frame = 0;
dest.x = x;
dest.y = y;
SDL_BlitSurface(img_cur_brush, NULL, canvas, &dest);
src.x = brush_frame * img_cur_brush_w;
src.y = 0;
src.w = img_cur_brush_w;
src.h = img_cur_brush_h;
SDL_BlitSurface(img_cur_brush, &src, canvas, &dest);
}
}
@ -5165,14 +5189,13 @@ static void loadbrush_callback(SDL_Surface * screen,
/* Load brush metadata, if any: */
strcpy(strcasestr(fname, ".png"), ".dat");
fi = fopen(fname, "r");
if (fi == NULL)
{
brushes_frames[num_brushes] = 1;
brushes_directional[num_brushes] = 0;
}
else
strcpy(strcasestr(fname, ".png"), ".dat");
fi = fopen(fname, "r");
if (fi != NULL)
{
do
{
@ -8533,17 +8556,32 @@ static void render_brush(void)
SDL_GetRGBA(getpixel_brush(img_brushes[cur_brush], x, y),
img_brushes[cur_brush]->format, &r, &g, &b, &a);
if (r == g && g == b)
{
putpixel_brush(img_cur_brush, x, y,
SDL_MapRGBA(img_cur_brush->format,
color_hexes[cur_color][0],
color_hexes[cur_color][1],
color_hexes[cur_color][2], a));
}
else
{
putpixel_brush(img_cur_brush, x, y,
SDL_MapRGBA(img_cur_brush->format,
(r + color_hexes[cur_color][0]) >> 1,
(g + color_hexes[cur_color][1]) >> 1,
(b + color_hexes[cur_color][2]) >> 1, a));
}
}
}
SDL_UnlockSurface(img_cur_brush);
SDL_UnlockSurface(img_brushes[cur_brush]);
img_cur_brush_w = img_cur_brush->w / brushes_frames[cur_brush];
img_cur_brush_h = img_cur_brush->h / (brushes_directional[cur_brush] ? 3 : 1);
img_cur_brush_frames = brushes_frames[cur_brush];
brush_counter = 0;
}