2007-09-18 23:57:02 +00:00
|
|
|
/* ase -- allegro-sprite-editor: the ultimate sprites factory
|
2007-09-20 00:32:35 +00:00
|
|
|
* Copyright (C) 2001-2005, 2007 David A. Capello
|
2007-09-18 23:57:02 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifndef USE_PRECOMPILED_HEADER
|
|
|
|
|
|
|
|
#include <allegro.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "jinete/alert.h"
|
|
|
|
#include "jinete/list.h"
|
|
|
|
|
|
|
|
#include "console/console.h"
|
|
|
|
#include "core/core.h"
|
|
|
|
#include "file/file.h"
|
|
|
|
#include "modules/gui.h"
|
|
|
|
#include "modules/palette.h"
|
|
|
|
#include "raster/raster.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "file/list.h"
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
/* to load */
|
|
|
|
Sprite *sprite;
|
|
|
|
Layer *layer;
|
|
|
|
int frpos;
|
|
|
|
Image *last_image;
|
|
|
|
Frame *last_frame;
|
|
|
|
/* to save */
|
|
|
|
Image *image;
|
|
|
|
} file_sequence;
|
|
|
|
|
|
|
|
static PALETTE file_palette;
|
|
|
|
static char file_extensions[512];
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
static FileType *get_filetype(const char *extension);
|
|
|
|
static int split_filename(const char *filename, char *left, char *right, int *width);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
void file_sequence_set_color(int index, int r, int g, int b)
|
|
|
|
{
|
|
|
|
file_palette[index].r = r;
|
|
|
|
file_palette[index].g = g;
|
|
|
|
file_palette[index].b = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
void file_sequence_get_color(int index, int *r, int *g, int *b)
|
|
|
|
{
|
|
|
|
*r = file_palette[index].r;
|
|
|
|
*g = file_palette[index].g;
|
|
|
|
*b = file_palette[index].b;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
Image *file_sequence_image(int imgtype, int w, int h)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
Sprite *sprite;
|
|
|
|
Image *image;
|
|
|
|
Layer *layer;
|
|
|
|
|
|
|
|
/* create the image */
|
|
|
|
if (!file_sequence.sprite) {
|
2007-09-20 00:32:35 +00:00
|
|
|
sprite = sprite_new(imgtype, w, h);
|
2007-09-18 23:57:02 +00:00
|
|
|
if (!sprite)
|
|
|
|
return NULL;
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
layer = layer_new(imgtype);
|
2007-09-18 23:57:02 +00:00
|
|
|
if (!layer) {
|
2007-09-20 00:32:35 +00:00
|
|
|
sprite_free(sprite);
|
2007-09-18 23:57:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
layer_set_name(layer, _("Background"));
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* add the layer */
|
2007-09-20 00:32:35 +00:00
|
|
|
layer_add_layer(sprite->set, layer);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
|
|
|
/* done */
|
|
|
|
file_sequence.sprite = sprite;
|
|
|
|
file_sequence.layer = layer;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprite = file_sequence.sprite;
|
|
|
|
|
|
|
|
if (sprite->imgtype != imgtype)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create a bitmap */
|
|
|
|
|
|
|
|
if (file_sequence.last_frame) {
|
2007-09-20 00:32:35 +00:00
|
|
|
console_printf(_("Error: called two times \"file_sequence_image ()\".\n"));
|
2007-09-18 23:57:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
image = image_new (imgtype, w, h);
|
|
|
|
if (!image) {
|
2007-09-20 00:32:35 +00:00
|
|
|
console_printf(_("Not enough memory to allocate a bitmap.\n"));
|
2007-09-18 23:57:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
file_sequence.last_image = image;
|
|
|
|
file_sequence.last_frame = frame_new(file_sequence.frpos++, 0);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
Sprite *file_sequence_sprite(void)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
return file_sequence.sprite;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
Image *file_sequence_image_to_save(void)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
return file_sequence.image;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
const char *get_readable_extensions(void)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* clear the string */
|
|
|
|
ustrcpy (file_extensions, empty_string);
|
|
|
|
|
|
|
|
/* insert file type */
|
|
|
|
for (c=0; filetypes[c]; c++) {
|
|
|
|
if (filetypes[c]->load)
|
|
|
|
ustrcat (file_extensions, filetypes[c]->exts);
|
|
|
|
|
|
|
|
if (filetypes[c+1] && filetypes[c]->load)
|
|
|
|
ustrcat (file_extensions, ",");
|
|
|
|
}
|
|
|
|
|
|
|
|
return file_extensions;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
const char *get_writeable_extensions(void)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
/* clear the string */
|
|
|
|
ustrcpy(file_extensions, empty_string);
|
|
|
|
|
|
|
|
/* insert file type */
|
|
|
|
for (c=0; filetypes[c]; c++) {
|
|
|
|
if (filetypes[c]->save)
|
|
|
|
ustrcat (file_extensions, filetypes[c]->exts);
|
|
|
|
|
|
|
|
if (filetypes[c+1] && filetypes[c]->save)
|
|
|
|
ustrcat (file_extensions, ",");
|
|
|
|
}
|
|
|
|
|
|
|
|
return file_extensions;
|
|
|
|
}
|
|
|
|
|
2007-09-20 00:32:35 +00:00
|
|
|
Sprite *sprite_load(const char *filename)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
|
|
|
char extension[32];
|
|
|
|
FileType *file;
|
|
|
|
Sprite *sprite;
|
|
|
|
|
|
|
|
ustrcpy (extension, get_extension(filename));
|
|
|
|
ustrlwr (extension);
|
|
|
|
|
|
|
|
PRINTF ("Loading file \"%s\" (%s)\n", filename, extension);
|
|
|
|
|
|
|
|
file = get_filetype (extension);
|
|
|
|
if ((!file) || (!file->load)) {
|
|
|
|
console_printf (_("Load file type \"%s\" isn't supported\n"), extension);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* default values */
|
|
|
|
memcpy(file_palette, default_palette, sizeof(PALETTE));
|
|
|
|
|
|
|
|
/* use the "sequence" interface */
|
|
|
|
if (file->flags & FILE_SUPPORT_SEQUENCES) {
|
|
|
|
#define SEQUENCE_IMAGE() \
|
|
|
|
do { \
|
|
|
|
index = stock_add_image(file_sequence.layer->stock, \
|
|
|
|
file_sequence.last_image); \
|
|
|
|
\
|
|
|
|
file_sequence.last_frame->image = index; \
|
|
|
|
\
|
|
|
|
layer_add_frame(file_sequence.layer, \
|
|
|
|
file_sequence.last_frame); \
|
|
|
|
\
|
|
|
|
sprite_set_palette(file_sequence.sprite, file_palette, c); \
|
|
|
|
\
|
|
|
|
old_image = file_sequence.last_image; \
|
|
|
|
\
|
|
|
|
file_sequence.last_image = NULL; \
|
|
|
|
file_sequence.last_frame = NULL; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
char buf[512], left[512], right[512];
|
|
|
|
int c, index = 0, width, start_from, frames;
|
|
|
|
Image *old_image;
|
|
|
|
/* PALETTE first_palette; */
|
|
|
|
JList file_names = jlist_new();
|
|
|
|
JLink link;
|
|
|
|
|
|
|
|
/* first of all, we must generate the list of files to load in the
|
|
|
|
sequence... */
|
|
|
|
|
|
|
|
/* per now, we want load just one file */
|
|
|
|
jlist_append (file_names, jstrdup (filename));
|
|
|
|
|
|
|
|
/* check is this could be a sequence */
|
|
|
|
start_from = split_filename(filename, left, right, &width);
|
|
|
|
if (start_from >= 0) {
|
|
|
|
/* try to get more file names */
|
|
|
|
for (c=start_from+1; ; c++) {
|
|
|
|
/* get the next file name */
|
|
|
|
usprintf(buf, "%s%0*d%s", left, width, c, right);
|
|
|
|
|
|
|
|
/* if the file doesn't exist, we doesn't need more files to load */
|
|
|
|
if (!exists(buf))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* add this file name to the list */
|
|
|
|
jlist_append (file_names, jstrdup (buf));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_interactive()) {
|
|
|
|
/* really want load all files? */
|
|
|
|
if ((jlist_length(file_names) > 1) &&
|
|
|
|
(jalert(_("Notice"
|
|
|
|
"<<Possible animation with:"
|
|
|
|
"<<%s"
|
|
|
|
"<<Load the sequence of bitmaps?"
|
|
|
|
"||&Agree||&Skip"),
|
|
|
|
get_filename(filename)) != 1)) {
|
|
|
|
/* if the user replies "Skip", we need just one file name */
|
|
|
|
while (jlist_length(file_names) > 1)
|
|
|
|
jlist_delete_link (file_names, jlist_last (file_names));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count how many frames to load */
|
|
|
|
frames = jlist_length(file_names);
|
|
|
|
|
|
|
|
/* prepare the sequence */
|
|
|
|
file_sequence.sprite = NULL;
|
|
|
|
file_sequence.layer = NULL;
|
|
|
|
file_sequence.frpos = 0;
|
|
|
|
file_sequence.last_image = NULL;
|
|
|
|
file_sequence.last_frame = NULL;
|
|
|
|
|
|
|
|
/* load the sequence */
|
|
|
|
c = 0;
|
|
|
|
old_image = NULL;
|
|
|
|
if (frames > 1)
|
|
|
|
add_progress(frames);
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(file_names, link) {
|
|
|
|
/* call the "load" procedure to read the first bitmap */
|
|
|
|
add_progress(100);
|
|
|
|
sprite = (*file->load)(link->data);
|
|
|
|
del_progress();
|
|
|
|
|
|
|
|
/* for the first frame */
|
|
|
|
if (!old_image) {
|
|
|
|
/* error reading the first frame */
|
|
|
|
if ((!sprite) || (!file_sequence.last_frame)) {
|
|
|
|
if (file_sequence.last_image)
|
|
|
|
image_free (file_sequence.last_image);
|
|
|
|
|
|
|
|
if (file_sequence.last_frame)
|
|
|
|
frame_free (file_sequence.last_frame);
|
|
|
|
|
|
|
|
if (file_sequence.sprite) {
|
|
|
|
sprite_free (file_sequence.sprite);
|
|
|
|
file_sequence.sprite = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* read ok */
|
|
|
|
else {
|
|
|
|
/* add the keyframe */
|
|
|
|
SEQUENCE_IMAGE ();
|
|
|
|
|
|
|
|
/* the first palette will be the palette to use */
|
|
|
|
/* memcpy (first_palette, file_palette, sizeof (PALETTE)); */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* for other frames */
|
|
|
|
else {
|
|
|
|
/* all done (or maybe not enough memory) */
|
|
|
|
if ((!sprite) || (!file_sequence.last_frame)) {
|
|
|
|
if (file_sequence.last_image)
|
|
|
|
image_free (file_sequence.last_image);
|
|
|
|
|
|
|
|
if (file_sequence.last_frame)
|
|
|
|
frame_free (file_sequence.last_frame);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* compare the old frame with the new one */
|
|
|
|
if (image_count_diff (old_image, file_sequence.last_image)) {
|
|
|
|
SEQUENCE_IMAGE ();
|
|
|
|
}
|
|
|
|
/* we don't need this image */
|
|
|
|
else {
|
|
|
|
image_free (file_sequence.last_image);
|
|
|
|
|
|
|
|
/* but add a link frame */
|
|
|
|
file_sequence.last_frame->image = index;
|
|
|
|
layer_add_frame (file_sequence.layer,
|
|
|
|
file_sequence.last_frame);
|
|
|
|
|
|
|
|
file_sequence.last_image = NULL;
|
|
|
|
file_sequence.last_frame = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frames > 1)
|
|
|
|
do_progress (c);
|
|
|
|
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frames > 1)
|
|
|
|
del_progress();
|
|
|
|
|
|
|
|
/* the sprite */
|
|
|
|
sprite = file_sequence.sprite;
|
|
|
|
if (sprite) {
|
|
|
|
/* set the frames range */
|
|
|
|
sprite_set_frames(sprite, c);
|
|
|
|
|
|
|
|
/* restore by the first palette */
|
|
|
|
/* XXXXX remove this */
|
|
|
|
/* memcpy(sprite->palette, first_palette, sizeof(PALETTE)); */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete the entire file names list */
|
|
|
|
JI_LIST_FOR_EACH(file_names, link)
|
|
|
|
jfree(link->data);
|
|
|
|
jlist_free(file_names);
|
|
|
|
}
|
|
|
|
/* direct load */
|
|
|
|
else {
|
|
|
|
/* call the "load" procedure */
|
|
|
|
sprite = (*file->load)(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* error */
|
|
|
|
if (!sprite)
|
|
|
|
console_printf(_("Error loading \"%s\"\n"), filename);
|
|
|
|
else {
|
|
|
|
Layer *last_layer = jlist_last_data(sprite->set->layers);
|
|
|
|
|
|
|
|
/* select the last layer */
|
|
|
|
sprite_set_layer(sprite, last_layer);
|
|
|
|
|
|
|
|
/* set the filename */
|
|
|
|
sprite_set_filename(sprite, filename);
|
|
|
|
|
|
|
|
rebuild_sprite_list();
|
|
|
|
}
|
|
|
|
|
|
|
|
return sprite;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sprite_save(Sprite *sprite)
|
|
|
|
{
|
|
|
|
char extension[32], buf[2048];
|
|
|
|
FileType *file;
|
|
|
|
int ret = -1;
|
|
|
|
bool fatal;
|
|
|
|
|
|
|
|
ustrcpy(extension, get_extension(sprite->filename));
|
|
|
|
ustrlwr(extension);
|
|
|
|
|
|
|
|
PRINTF ("Saving sprite \"%s\" (%s)\n", sprite->filename, extension);
|
|
|
|
|
|
|
|
file = get_filetype(extension);
|
|
|
|
if ((!file) || (!file->save)) {
|
|
|
|
console_printf (_("Save file type \"%s\" isn't supported\n"), extension);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* warnings */
|
|
|
|
ustrcpy(buf, empty_string);
|
|
|
|
fatal = FALSE;
|
|
|
|
|
|
|
|
/* check image type support */
|
|
|
|
switch (sprite->imgtype) {
|
|
|
|
|
|
|
|
case IMAGE_RGB:
|
|
|
|
if (!(file->flags & FILE_SUPPORT_RGB)) {
|
|
|
|
usprintf(buf+ustrlen (buf), "<<- %s", _("RGB format"));
|
|
|
|
fatal = TRUE;
|
|
|
|
}
|
|
|
|
if (!(file->flags & FILE_SUPPORT_RGBA)) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", _("Alpha channel"));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_GRAYSCALE:
|
|
|
|
if (!(file->flags & FILE_SUPPORT_GRAY)) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", _("Grayscale format"));
|
|
|
|
fatal = TRUE;
|
|
|
|
}
|
|
|
|
if (!(file->flags & FILE_SUPPORT_GRAYA)) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", _("Alpha channel"));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IMAGE_INDEXED:
|
|
|
|
if (!(file->flags & FILE_SUPPORT_INDEXED)) {
|
|
|
|
usprintf(buf+ustrlen(buf), "<<- %s", _("Indexed format"));
|
|
|
|
fatal = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check frames support */
|
|
|
|
if (!(file->flags & (FILE_SUPPORT_FRAMES |
|
|
|
|
FILE_SUPPORT_SEQUENCES))) {
|
|
|
|
if (sprite->frames > 1)
|
|
|
|
usprintf(buf+ustrlen (buf), "<<- %s", _("Frames"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* layers support */
|
|
|
|
if (jlist_length(sprite->set->layers) > 1) {
|
|
|
|
if (!(file->flags & FILE_SUPPORT_LAYERS)) {
|
|
|
|
usprintf(buf+ustrlen (buf), "<<- %s", _("Layers"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* palettes support */
|
|
|
|
if (jlist_length(sprite->palettes) > 1) {
|
|
|
|
if (!(file->flags & (FILE_SUPPORT_PALETTES |
|
|
|
|
FILE_SUPPORT_SEQUENCES))) {
|
|
|
|
usprintf(buf+ustrlen (buf), "<<- %s", _("Palette changes"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* repositories */
|
|
|
|
if (!jlist_empty(sprite->repository.masks)) {
|
|
|
|
Mask *mask;
|
|
|
|
JLink link;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
JI_LIST_FOR_EACH(sprite->repository.masks, link) {
|
|
|
|
mask = link->data;
|
|
|
|
|
|
|
|
/* names starting with '*' are ignored */
|
|
|
|
if (mask->name && *mask->name == '*')
|
|
|
|
continue;
|
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((count > 0) && !(file->flags & FILE_SUPPORT_MASKS_REPOSITORY)) {
|
|
|
|
usprintf (buf+ustrlen (buf), "<<- %s", _("Mask Repository"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!jlist_empty(sprite->repository.paths)) {
|
|
|
|
if (!(file->flags & FILE_SUPPORT_PATHS_REPOSITORY)) {
|
|
|
|
usprintf (buf+ustrlen (buf), "<<- %s", _("Path Repository"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* show the confirmation alert */
|
|
|
|
if (ugetc (buf)) {
|
|
|
|
if (is_interactive ()) {
|
|
|
|
if (fatal)
|
|
|
|
ret = jalert (_("Error<<File type \"%s\" doesn't support:%s"
|
|
|
|
"||&Close"),
|
|
|
|
file->name, buf);
|
|
|
|
else
|
|
|
|
ret = jalert (_("Warning<<File type \"%s\" doesn't support:%s"
|
|
|
|
"<<Do you want continue?"
|
|
|
|
"||&Yes||&No"),
|
|
|
|
file->name, buf);
|
|
|
|
|
|
|
|
if ((fatal) || (ret != 1))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* palette */
|
|
|
|
/* memcpy(file_palette, sprite->palette, sizeof (PALETTE)); */
|
|
|
|
|
|
|
|
/* use the "sequence" interface */
|
|
|
|
if (file->flags & FILE_SUPPORT_SEQUENCES) {
|
|
|
|
Image *image;
|
|
|
|
int old_frpos = sprite->frpos;
|
|
|
|
char *old_filename = jstrdup (sprite->filename);
|
|
|
|
|
|
|
|
/* create a temporary bitmap */
|
|
|
|
image = image_new (sprite->imgtype, sprite->w, sprite->h);
|
|
|
|
|
|
|
|
if (image) {
|
|
|
|
/* save one frame */
|
|
|
|
if (sprite->frames == 1) {
|
|
|
|
/* draw all the sprite in the image */
|
|
|
|
sprite->frpos = 0;
|
|
|
|
image_clear (image, 0);
|
|
|
|
sprite_render (sprite, image, 0, 0);
|
|
|
|
|
|
|
|
/* save the temporary image */
|
|
|
|
file_sequence.image = image;
|
|
|
|
|
|
|
|
palette_copy(file_palette, sprite_get_palette(sprite, sprite->frpos));
|
|
|
|
|
|
|
|
add_progress(100);
|
|
|
|
ret = (*file->save)(sprite);
|
|
|
|
del_progress();
|
|
|
|
}
|
|
|
|
/* save more frames */
|
|
|
|
else {
|
|
|
|
char buf[256], left[256], right[256];
|
|
|
|
int width, start_from;
|
|
|
|
|
|
|
|
start_from = split_filename (sprite->filename, left, right, &width);
|
|
|
|
if (start_from < 0) {
|
|
|
|
start_from = 0;
|
|
|
|
width = (sprite->frames < 10)? 1:
|
|
|
|
(sprite->frames < 100)? 2:
|
|
|
|
(sprite->frames < 1000)? 3: 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_progress(sprite->frames);
|
|
|
|
|
|
|
|
for (sprite->frpos=0; sprite->frpos<sprite->frames; sprite->frpos++) {
|
|
|
|
/* draw all the sprite in this frame in the image */
|
|
|
|
image_clear (image, 0);
|
|
|
|
sprite_render (sprite, image, 0, 0);
|
|
|
|
|
|
|
|
/* get the name for this image */
|
|
|
|
usprintf (buf, "%s%0*d%s", left, width, start_from+sprite->frpos, right);
|
|
|
|
|
|
|
|
/* save the image */
|
|
|
|
file_sequence.image = image;
|
|
|
|
ustrcpy (sprite->filename, buf);
|
|
|
|
|
|
|
|
palette_copy(file_palette, sprite_get_palette(sprite, sprite->frpos));
|
|
|
|
|
|
|
|
add_progress(100);
|
|
|
|
ret = (*file->save)(sprite);
|
|
|
|
del_progress();
|
|
|
|
|
|
|
|
/* error? */
|
|
|
|
if (ret != 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
do_progress (sprite->frpos);
|
|
|
|
}
|
|
|
|
|
|
|
|
del_progress ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* destroy the image */
|
|
|
|
image_free (image);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console_printf (_("Not enough memory for the temporary bitmap.\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
sprite->frpos = old_frpos;
|
|
|
|
ustrcpy (sprite->filename, old_filename);
|
|
|
|
jfree (old_filename);
|
|
|
|
}
|
|
|
|
/* direct save */
|
|
|
|
else {
|
|
|
|
/* call the "save" procedure */
|
|
|
|
ret = (*file->save)(sprite);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
console_printf(_("Error saving \"%s\"\n"), sprite->filename);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FileType *get_filetype(const char *extension)
|
|
|
|
{
|
|
|
|
char buf[512], *tok;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c=0; filetypes[c]; c++) {
|
|
|
|
ustrcpy (buf, filetypes[c]->exts);
|
|
|
|
|
|
|
|
for (tok=ustrtok (buf, ","); tok;
|
|
|
|
tok=ustrtok (NULL, ",")) {
|
|
|
|
if (ustricmp (extension, tok) == 0)
|
|
|
|
return filetypes[c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* splits a file-name like "my_ani0000.pcx" to "my_ani" and ".pcx",
|
|
|
|
returning the number of the center; returns "-1" if the function
|
|
|
|
can't split anything */
|
|
|
|
static int split_filename(const char *filename, char *left, char *right, int *width)
|
|
|
|
{
|
|
|
|
char *ptr, *ext;
|
|
|
|
char buf[16];
|
|
|
|
int chr, ret;
|
|
|
|
|
|
|
|
/* get the extension */
|
|
|
|
ext = get_extension (filename);
|
|
|
|
|
|
|
|
/* with extension */
|
|
|
|
if ((ext) && (*ext)) {
|
|
|
|
/* left side (the filename without the extension and without the '.') */
|
|
|
|
ext--;
|
|
|
|
*ext = 0;
|
|
|
|
ustrcpy (left, filename);
|
|
|
|
*ext = '.';
|
|
|
|
|
|
|
|
/* right side (the extension with the '.') */
|
|
|
|
ustrcpy (right, ext);
|
|
|
|
}
|
|
|
|
/* without extension (without right side) */
|
|
|
|
else {
|
|
|
|
ustrcpy (left, filename);
|
|
|
|
ustrcpy (right, empty_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove all trailing numbers in the "left" side, and pass they to "buf" */
|
|
|
|
|
|
|
|
ptr = buf+9;
|
|
|
|
ptr[1] = 0;
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
if (width)
|
|
|
|
*width = 0;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
chr = ugetat (left, -1);
|
|
|
|
if ((chr >= '0') && (chr <= '9')) {
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (ptr >= buf) {
|
|
|
|
*(ptr--) = chr;
|
|
|
|
|
|
|
|
if (width)
|
|
|
|
(*width)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
uremove(left, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert the "buf" to integer and return it */
|
|
|
|
if (ret == 0) {
|
|
|
|
while (ptr >= buf)
|
|
|
|
*(ptr--) = '0';
|
|
|
|
|
|
|
|
ret = ustrtol (buf, NULL, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|