[Freeciv-Dev] (PR#3457) New sprite loading
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
I wrote a nice explanation of the patch but than I hit 'q' in the mail
reader. ARGL. So here is the very short version:
Problems:
- special case for not permanently loaded/used graphics needed
- gui-sdl need sprites which other guis doesn't want to load
Solution has three functions load_sprite, unload_sprite and
finish_loading. See code for usage.
Raimar
--
email: rf13@xxxxxxxxxxxxxxxxx
Two OS engineers facing a petri net chart:
"dead lock in four moves!"
diff -Nurd -X clean/diff_ignore clean/client/gui-gtk-2.0/graphics.c
tileset/client/gui-gtk-2.0/graphics.c
--- clean/client/gui-gtk-2.0/graphics.c Mon Feb 17 19:32:12 2003
+++ tileset/client/gui-gtk-2.0/graphics.c Mon Feb 17 20:49:44 2003
@@ -114,8 +114,8 @@
face_gc = gdk_gc_new(root_window);
/* Main graphic */
- intro_gfx_sprite = load_gfxfile(main_intro_filename);
- tot=intro_gfx_sprite->width;
+ intro_gfx_sprite = load_sprite("special.intro");
+ tot = intro_gfx_sprite->width;
pango_layout_set_text(layout, freeciv_motto(), -1);
pango_layout_get_pixel_extents(layout, &rect, NULL);
@@ -128,9 +128,11 @@
gdk_gc_destroy (face_gc);
/* Minimap graphic */
- radar_gfx_sprite = load_gfxfile(minimap_intro_filename);
+ radar_gfx_sprite = load_sprite("special.radar");
tot=radar_gfx_sprite->width;
+ finish_loading();
+
my_snprintf(s, sizeof(s), "%d.%d.%d%s",
MAJOR_VERSION, MINOR_VERSION,
PATCH_VERSION, VERSION_LABEL);
@@ -329,12 +331,16 @@
/***************************************************************************
Deletes a sprite. These things can use a lot of memory.
***************************************************************************/
-void free_sprite(SPRITE *s)
+void free_sprite(SPRITE * s)
{
- if (s->pixmap)
+ if (s->pixmap) {
g_object_unref(s->pixmap);
- if (s->mask)
+ s->pixmap = NULL;
+ }
+ if (s->mask) {
g_object_unref(s->mask);
+ s->mask = NULL;
+ }
free(s);
return;
}
@@ -379,14 +385,11 @@
***************************************************************************/
void free_intro_radar_sprites(void)
{
- if (intro_gfx_sprite) {
- free_sprite(intro_gfx_sprite);
- intro_gfx_sprite=NULL;
- }
- if (radar_gfx_sprite) {
- free_sprite(radar_gfx_sprite);
- radar_gfx_sprite=NULL;
- }
+ unload_sprite("special.intro");
+ intro_gfx_sprite = NULL;
+
+ unload_sprite("special.radar");
+ radar_gfx_sprite = NULL;
}
/***************************************************************************
diff -Nurd -X clean/diff_ignore clean/client/tilespec.c
tileset/client/tilespec.c
--- clean/client/tilespec.c Mon Feb 17 19:32:12 2003
+++ tileset/client/tilespec.c Mon Feb 17 20:36:21 2003
@@ -53,9 +53,6 @@
#define TILESPEC_SUFFIX ".tilespec"
-char *main_intro_filename;
-char *minimap_intro_filename;
-
struct named_sprites sprites;
char current_tile_set_name[512];
@@ -79,15 +76,52 @@
static bool is_mountainous = FALSE;
static int roadstyle;
-static int num_spec_files = 0;
-static char **spec_filenames; /* full pathnames */
+struct specfile;
+
+#define SPECLIST_TAG specfile
+#define SPECLIST_TYPE struct specfile
+#include "speclist.h"
+
+#define SPECLIST_TAG specfile
+#define SPECLIST_TYPE struct specfile
+#include "speclist_c.h"
+
+#define specfile_list_iterate(list, pitem) \
+ TYPED_LIST_ITERATE(struct specfile, list, pitem)
+#define specfile_list_iterate_end LIST_ITERATE_END
+
+struct small_sprite;
+#define SPECLIST_TAG small_sprite
+#define SPECLIST_TYPE struct small_sprite
+#include "speclist.h"
+
+#define SPECLIST_TAG small_sprite
+#define SPECLIST_TYPE struct small_sprite
+#include "speclist_c.h"
+
+#define small_sprite_list_iterate(list, pitem) \
+ TYPED_LIST_ITERATE(struct small_sprite, list, pitem)
+#define small_sprite_list_iterate_end LIST_ITERATE_END
+
+static struct specfile_list specfiles;
+
+struct specfile {
+ struct Sprite *big_sprite;
+ char *file_name;
+ struct small_sprite_list small_sprites;
+};
+
+struct small_sprite {
+ int ref_count;
+ int x, y, width, height;
+ struct specfile *sf;
+ struct Sprite *sprite;
+};
-static struct hash_table *sprite_hash = NULL;
/*
- This hash table sprite_hash maps tilespec tags to tile Sprite pointers.
- This is kept permanently after setup, for doing lookups on ruleset
- information (including on reconnections etc).
-*/
+ * This hash table maps tilespec tags to struct small_sprites.
+ */
+static struct hash_table *sprite_hash = NULL;
#define TILESPEC_CAPSTR "+tilespec2 duplicates_ok roadstyle"
/*
@@ -212,35 +246,6 @@
}
/**********************************************************************
- Returns the correct name of the gfx file (with path and extension)
- Must be free'd when no longer used
-***********************************************************************/
-static char *tilespec_gfx_filename(const char *gfx_filename)
-{
- const char *gfx_current_fileext;
- const char **gfx_fileexts = gfx_fileextensions();
-
- while((gfx_current_fileext = *gfx_fileexts++))
- {
- char *full_name =
- fc_malloc(strlen(gfx_filename) + strlen(gfx_current_fileext) + 2);
- char *real_full_name;
-
- sprintf(full_name,"%s.%s",gfx_filename,gfx_current_fileext);
-
- real_full_name = datafilename(full_name);
- free(full_name);
- if (real_full_name) {
- return mystrdup(real_full_name);
- }
- }
-
- freelog(LOG_FATAL, _("Couldn't find a supported gfx file extension for %s"),
- gfx_filename);
- exit(EXIT_FAILURE);
-}
-
-/**********************************************************************
Frees the tilespec toplevel data, in preparation for re-reading it.
See tilespec_read_toplevel().
@@ -255,14 +260,6 @@
free(city_productions_font_name);
city_productions_font_name = NULL;
}
- if (main_intro_filename) {
- free(main_intro_filename);
- main_intro_filename = NULL;
- }
- if (minimap_intro_filename) {
- free(minimap_intro_filename);
- minimap_intro_filename = NULL;
- }
/* FIXME: free spec_filenames */
}
@@ -374,6 +371,130 @@
}
/**********************************************************************
+ Ensure that the big sprite of the given spec file is loaded.
+***********************************************************************/
+static void ensure_big_sprite(struct specfile *sf)
+{
+ struct section_file the_file, *file = &the_file;
+ const char *gfx_filename, *gfx_current_fileext, **gfx_fileexts;
+
+ if (sf->big_sprite) {
+ return;
+ }
+
+ if (!section_file_load(file, sf->file_name)) {
+ freelog(LOG_FATAL, _("Could not open \"%s\"."), sf->file_name);
+ exit(EXIT_FAILURE);
+ }
+ check_tilespec_capabilities(file, "spec", SPEC_CAPSTR, sf->file_name);
+
+ gfx_fileexts = gfx_fileextensions();
+ gfx_filename = secfile_lookup_str(file, "file.gfx");
+
+ while (!sf->big_sprite && (gfx_current_fileext = *gfx_fileexts++)) {
+ char *real_full_name;
+ char *full_name =
+ fc_malloc(strlen(gfx_filename) + strlen(gfx_current_fileext) + 2);
+ sprintf(full_name, "%s.%s", gfx_filename, gfx_current_fileext);
+
+ if ((real_full_name = datafilename(full_name))) {
+ freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
+ sf->big_sprite = load_gfxfile(real_full_name);
+ if (!sf->big_sprite) {
+ freelog(LOG_VERBOSE, "loading the gfx file %s failed",
+ real_full_name);
+ }
+ }
+ free(full_name);
+ }
+
+ if (!sf->big_sprite) {
+ freelog(LOG_FATAL, _("Couldn't load gfx file for the spec file %s"),
+ sf->file_name);
+ exit(EXIT_FAILURE);
+ }
+ section_file_free(file);
+}
+
+/**********************************************************************
+***********************************************************************/
+static void scan_specfile(struct specfile *sf)
+{
+ struct section_file the_file, *file = &the_file;
+ char **gridnames;
+ int num_grids, i;
+
+ if (!section_file_load(file, sf->file_name)) {
+ freelog(LOG_FATAL, _("Could not open \"%s\"."), sf->file_name);
+ exit(EXIT_FAILURE);
+ }
+ check_tilespec_capabilities(file, "spec", SPEC_CAPSTR, sf->file_name);
+
+ (void) section_file_lookup(file, "info.artists"); /* currently unused */
+ (void)secfile_lookup_str(file, "file.gfx");
+
+ gridnames = secfile_get_secnames_prefix(file, "grid_", &num_grids);
+ if (num_grids == 0) {
+ freelog(LOG_FATAL, "spec %s has no grid_* sections", sf->file_name);
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < num_grids; i++) {
+ int j, k;
+ int x_top_left, y_top_left, dx, dy;
+ bool is_pixel_border =
+ secfile_lookup_bool_default(file, FALSE, "%s.is_pixel_border",
gridnames[i]);
+ x_top_left = secfile_lookup_int(file, "%s.x_top_left", gridnames[i]);
+ y_top_left = secfile_lookup_int(file, "%s.y_top_left", gridnames[i]);
+ dx = secfile_lookup_int(file, "%s.dx", gridnames[i]);
+ dy = secfile_lookup_int(file, "%s.dy", gridnames[i]);
+
+ j = -1;
+ while (section_file_lookup(file, "%s.tiles%d.tag", gridnames[i], ++j)) {
+ struct small_sprite *ss = fc_malloc(sizeof(*ss));
+ int row, column;
+ int x1, y1;
+ char **tags;
+ int num_tags;
+
+ row = secfile_lookup_int(file, "%s.tiles%d.row", gridnames[i], j);
+ column = secfile_lookup_int(file, "%s.tiles%d.column", gridnames[i], j);
+ tags = secfile_lookup_str_vec(file, &num_tags, "%s.tiles%d.tag",
+ gridnames[i], j);
+
+ /* there must be at least 1 because of the while(): */
+ assert(num_tags > 0);
+
+ x1 = x_top_left + column * dx + (is_pixel_border ? column : 0);
+ y1 = y_top_left + row * dy + (is_pixel_border ? row : 0);
+
+ ss->ref_count = 0;
+ ss->x = x1;
+ ss->y = y1;
+ ss->width = dx;
+ ss->height = dy;
+ ss->sf = sf;
+ ss->sprite = NULL;
+
+ small_sprite_list_insert(&ss->sf->small_sprites, ss);
+
+ for (k = 0; k < num_tags; k++) {
+ if (!hash_insert(sprite_hash, mystrdup(tags[k]), ss)) {
+ die("already have a sprite for %s", tags[k]);
+ }
+ }
+ free(tags);
+ tags = NULL;
+ }
+ }
+ free(gridnames);
+ gridnames = NULL;
+
+ section_file_check_unused(file, sf->file_name);
+ section_file_free(file);
+}
+
+/**********************************************************************
Finds and reads the toplevel tilespec file based on given name.
Sets global variables, including tile sizes and full names for
intro files.
@@ -383,6 +504,8 @@
struct section_file the_file, *file = &the_file;
char *fname, *c;
int i;
+ int num_spec_files;
+ char **spec_filenames;
fname = tilespec_fullname(tileset_name);
freelog(LOG_VERBOSE, "tilespec file is %s", fname);
@@ -444,24 +567,26 @@
"tilespec.city_productions_font");
city_productions_font_name = mystrdup(c);
- c = secfile_lookup_str(file, "tilespec.main_intro_file");
- main_intro_filename = tilespec_gfx_filename(c);
- freelog(LOG_DEBUG, "intro file %s", main_intro_filename);
-
- c = secfile_lookup_str(file, "tilespec.minimap_intro_file");
- minimap_intro_filename = tilespec_gfx_filename(c);
- freelog(LOG_DEBUG, "radar file %s", minimap_intro_filename);
-
spec_filenames = secfile_lookup_str_vec(file, &num_spec_files,
"tilespec.files");
if (num_spec_files == 0) {
freelog(LOG_FATAL, "No tile files specified in \"%s\"", fname);
exit(EXIT_FAILURE);
}
-
- for(i=0; i<num_spec_files; i++) {
- spec_filenames[i] = mystrdup(datafilename_required(spec_filenames[i]));
+
+ sprite_hash = hash_new(hash_fval_string, hash_fcmp_string);
+ specfile_list_init(&specfiles);
+ for (i = 0; i < num_spec_files; i++) {
+ struct specfile *sf = fc_malloc(sizeof(*sf));
+
freelog(LOG_DEBUG, "spec file %s", spec_filenames[i]);
+
+ sf->big_sprite = NULL;
+ sf->file_name = mystrdup(datafilename_required(spec_filenames[i]));
+ small_sprite_list_init(&sf->small_sprites);
+ scan_specfile(sf);
+
+ specfile_list_insert(&specfiles, sf);
}
section_file_check_unused(file, fname);
@@ -472,105 +597,6 @@
}
/**********************************************************************
- Load one specfile and specified xpm file; splits xpm into tiles,
- and save sprites in sprite_hash.
-***********************************************************************/
-static void tilespec_load_one(const char *spec_filename)
-{
- struct section_file the_file, *file = &the_file;
- struct Sprite *big_sprite = NULL, *small_sprite;
- const char *gfx_filename, *gfx_current_fileext, **gfx_fileexts;
- char **gridnames, **tags;
- int num_grids, num_tags;
- int i, j, k;
- int x_top_left, y_top_left, dx, dy;
- int row, column;
- int x1, y1;
-
- freelog(LOG_DEBUG, "loading spec %s", spec_filename);
- if (!section_file_load(file, spec_filename)) {
- freelog(LOG_FATAL, _("Could not open \"%s\"."), spec_filename);
- exit(EXIT_FAILURE);
- }
- check_tilespec_capabilities(file, "spec", SPEC_CAPSTR, spec_filename);
-
- (void) section_file_lookup(file, "info.artists"); /* currently unused */
-
- gfx_fileexts = gfx_fileextensions();
- gfx_filename = secfile_lookup_str(file, "file.gfx");
-
- while((!big_sprite) && (gfx_current_fileext = *gfx_fileexts++))
- {
- char *full_name,*real_full_name;
- full_name = fc_malloc(strlen(gfx_filename)+strlen(gfx_current_fileext)+2);
- sprintf(full_name,"%s.%s",gfx_filename,gfx_current_fileext);
-
- if((real_full_name = datafilename(full_name)))
- {
- freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
- if(!(big_sprite = load_gfxfile(real_full_name)))
- {
- freelog(LOG_VERBOSE, "loading the gfx file %s failed", real_full_name);
- }
- }
- free(full_name);
- }
-
- if(!big_sprite) {
- freelog(LOG_FATAL, _("Couldn't load gfx file for the spec file %s"),
- spec_filename);
- exit(EXIT_FAILURE);
- }
-
-
- gridnames = secfile_get_secnames_prefix(file, "grid_", &num_grids);
- if (num_grids==0) {
- freelog(LOG_FATAL, "spec %s has no grid_* sections", spec_filename);
- exit(EXIT_FAILURE);
- }
-
- for(i=0; i<num_grids; i++) {
- bool is_pixel_border =
- secfile_lookup_bool_default(file, FALSE, "%s.is_pixel_border",
gridnames[i]);
- x_top_left = secfile_lookup_int(file, "%s.x_top_left", gridnames[i]);
- y_top_left = secfile_lookup_int(file, "%s.y_top_left", gridnames[i]);
- dx = secfile_lookup_int(file, "%s.dx", gridnames[i]);
- dy = secfile_lookup_int(file, "%s.dy", gridnames[i]);
-
- j = -1;
- while(section_file_lookup(file, "%s.tiles%d.tag", gridnames[i], ++j)) {
- row = secfile_lookup_int(file, "%s.tiles%d.row", gridnames[i], j);
- column = secfile_lookup_int(file, "%s.tiles%d.column", gridnames[i], j);
- tags = secfile_lookup_str_vec(file, &num_tags, "%s.tiles%d.tag",
- gridnames[i], j);
-
- /* there must be at least 1 because of the while(): */
- assert(num_tags>0);
-
- x1 = x_top_left + column * dx + (is_pixel_border ? column : 0);
- y1 = y_top_left + row * dy + (is_pixel_border ? row : 0);
- small_sprite = crop_sprite(big_sprite, x1, y1, dx, dy);
-
- for(k=0; k<num_tags; k++) {
- /* don't free old sprite, since could be multiple tags
- pointing to it */
- (void) hash_replace(sprite_hash, mystrdup(tags[k]), small_sprite);
- }
- free(tags);
- tags = NULL;
- }
- }
- free(gridnames);
- gridnames = NULL;
-
- free_sprite(big_sprite);
-
- section_file_check_unused(file, spec_filename);
- section_file_free(file);
- freelog(LOG_DEBUG, "finished %s", spec_filename);
-}
-
-/**********************************************************************
Returns a text name for the citizen, as used in the tileset.
***********************************************************************/
static const char *get_citizen_name(enum citizen_type citizen)
@@ -613,7 +639,7 @@
/* Not very safe, but convenient: */
#define SET_SPRITE(field, tag) do { \
- sprites.field = hash_lookup_data(sprite_hash, tag);\
+ sprites.field = load_sprite(tag);\
if (!sprites.field) { \
die("Sprite tag %s missing.", buffer); \
} \
@@ -621,9 +647,9 @@
/* Sets sprites.field to tag or (if tag isn't available) to alt */
#define SET_SPRITE_ALT(field, tag, alt) do { \
- sprites.field = hash_lookup_data(sprite_hash, tag); \
+ sprites.field = load_sprite(tag); \
if (!sprites.field) { \
- sprites.field = hash_lookup_data(sprite_hash, alt); \
+ sprites.field = load_sprite(alt); \
} \
if (!sprites.field) { \
die("Sprite tag %s and alternate %s are both missing.", tag, alt); \
@@ -632,7 +658,7 @@
/* Sets sprites.field to tag, or NULL if not available */
#define SET_SPRITE_OPT(field, tag) \
- sprites.field = hash_lookup_data(sprite_hash, tag)
+ sprites.field = load_sprite(tag)
/**********************************************************************
Initialize 'sprites' structure based on hardwired tags which
@@ -668,7 +694,7 @@
/* Load the citizen sprite graphics. */
for (i = 0; i < NUM_TILES_CITIZEN; i++) {
my_snprintf(buffer, sizeof(buffer), "citizen.%s", get_citizen_name(i));
- sprites.citizen[i].sprite[0] = hash_lookup_data(sprite_hash, buffer);
+ sprites.citizen[i].sprite[0] = load_sprite(buffer);
if (sprites.citizen[i].sprite[0]) {
/*
* If this form exists, use it as the only sprite. This allows
@@ -682,7 +708,7 @@
for (j = 0; j < NUM_TILES_CITIZEN; j++) {
my_snprintf(buffer, sizeof(buffer), "citizen.%s_%d",
get_citizen_name(i), j);
- sprites.citizen[i].sprite[j] = hash_lookup_data(sprite_hash, buffer);
+ sprites.citizen[i].sprite[j] = load_sprite(buffer);
if (!sprites.citizen[i].sprite[j]) {
break;
}
@@ -766,7 +792,7 @@
do {
my_snprintf(buffer, sizeof(buffer), "explode.unit_%d",
num_tiles_explode_unit++);
- } while (hash_key_exists(sprite_hash, buffer));
+ } while (load_sprite(buffer));
num_tiles_explode_unit--;
if (num_tiles_explode_unit==0) {
@@ -907,16 +933,8 @@
***********************************************************************/
void tilespec_load_tiles(void)
{
- int i;
-
- assert(num_spec_files>0);
- sprite_hash = hash_new(hash_fval_string, hash_fcmp_string);
-
- for(i=0; i<num_spec_files; i++) {
- tilespec_load_one(spec_filenames[i]);
- }
-
tilespec_lookup_sprite_tags();
+ finish_loading();
}
/**********************************************************************
@@ -935,10 +953,10 @@
die("attempt to lookup for %s %s before sprite_hash setup", what, name);
}
- sp = hash_lookup_data(sprite_hash, tag);
+ sp = load_sprite(tag);
if (sp) return sp;
- sp = hash_lookup_data(sprite_hash, alt);
+ sp = load_sprite(alt);
if (sp) {
freelog(loglevel, "Using alternate graphic %s (instead of %s) for %s %s",
alt, tag, what, name);
@@ -2119,10 +2137,10 @@
for(j=0; j<32 && city_styles[style].tiles_num < MAX_CITY_TILES; j++) {
my_snprintf(buffer, sizeof(buffer), "%s_%d", graphics, j);
- sp = hash_lookup_data(sprite_hash, buffer);
+ sp = load_sprite(buffer);
if (is_isometric) {
my_snprintf(buffer, sizeof(buffer_wall), "%s_%d_wall", graphics, j);
- sp_wall = hash_lookup_data(sprite_hash, buffer);
+ sp_wall = load_sprite(buffer);
}
if (sp) {
sprites.city.tile[style][city_styles[style].tiles_num] = sp;
@@ -2142,7 +2160,7 @@
if (!is_isometric) {
/* the wall tile */
my_snprintf(buffer, sizeof(buffer), "%s_wall", graphics);
- sp = hash_lookup_data(sprite_hash, buffer);
+ sp = load_sprite(buffer);
if (sp) {
sprites.city.tile[style][city_styles[style].tiles_num] = sp;
} else {
@@ -2152,7 +2170,7 @@
/* occupied tile */
my_snprintf(buffer, sizeof(buffer), "%s_occupied", graphics);
- sp = hash_lookup_data(sprite_hash, buffer);
+ sp = load_sprite(buffer);
if (sp) {
sprites.city.tile[style][city_styles[style].tiles_num+1] = sp;
} else {
@@ -2183,12 +2201,9 @@
"No tiles for alternate %s style, using default tiles",
city_styles[style].graphic_alt);
- sprites.city.tile[style][0] =
- hash_lookup_data(sprite_hash, "cd.city");
- sprites.city.tile[style][1] =
- hash_lookup_data(sprite_hash, "cd.city_wall");
- sprites.city.tile[style][2] =
- hash_lookup_data(sprite_hash, "cd.occupied");
+ sprites.city.tile[style][0] = load_sprite("cd.city");
+ sprites.city.tile[style][1] = load_sprite("cd.city_wall");
+ sprites.city.tile[style][2] = load_sprite("cd.occupied");
city_styles[style].tiles_num = 1;
city_styles[style].tresh[0] = 0;
}
@@ -2321,24 +2336,18 @@
return NULL;
}
-/**********************************************************************
-...
-***********************************************************************/
-static int my_cmp(const void *a1, const void *a2)
+static void unload_all_sprites(void )
{
- const struct Sprite **b1 = (const struct Sprite **) a1;
- const struct Sprite **b2 = (const struct Sprite **) a2;
+ int i, entries = hash_num_entries(sprite_hash);
- const struct Sprite *c1 = *b1;
- const struct Sprite *c2 = *b2;
+ for (i = 0; i < entries; i++) {
+ const char *tag_name = hash_key_by_number(sprite_hash, i);
+ struct small_sprite *ss = hash_lookup_data(sprite_hash, tag_name);
- if (c1 < c2) {
- return -1;
- }
- if (c2 < c1) {
- return 1;
+ while (ss->ref_count > 0) {
+ unload_sprite(tag_name);
+ }
}
- return 0;
}
/**********************************************************************
@@ -2347,33 +2356,35 @@
void tilespec_free_tiles(void)
{
int i, entries = hash_num_entries(sprite_hash);
- struct Sprite **sprites = fc_malloc(sizeof(*sprites) * entries);
- struct Sprite *last_sprite = NULL;
freelog(LOG_DEBUG, "tilespec_free_tiles");
+ unload_all_sprites();
+
for (i = 0; i < entries; i++) {
const char *key = hash_key_by_number(sprite_hash, 0);
- sprites[i] = hash_delete_entry(sprite_hash, key);
+ hash_delete_entry(sprite_hash, key);
free((void *) key);
}
- qsort(sprites, entries, sizeof(sprites[0]), my_cmp);
-
- for (i = 0; i < entries; i++) {
- if (sprites[i] == last_sprite) {
- continue;
- }
-
- last_sprite = sprites[i];
- free_sprite(sprites[i]);
- }
-
- free(sprites);
-
hash_free(sprite_hash);
sprite_hash = NULL;
+
+ specfile_list_iterate(specfiles, sf) {
+ small_sprite_list_iterate(sf->small_sprites, ss) {
+ small_sprite_list_unlink(&sf->small_sprites, ss);
+ assert(ss->sprite == NULL);
+ free(ss);
+ } small_sprite_list_iterate_end;
+
+ specfile_list_unlink(&specfiles, sf);
+ if (sf->big_sprite) {
+ free_sprite(sf->big_sprite);
+ sf->big_sprite = NULL;
+ }
+ free(sf);
+ } specfile_list_iterate_end;
}
/**************************************************************************
@@ -2390,3 +2401,52 @@
citizen_index %= sprites.citizen[type].count;
return sprites.citizen[type].sprite[citizen_index];
}
+
+struct Sprite *load_sprite(const char *tag_name)
+{
+ struct small_sprite *ss = hash_lookup_data(sprite_hash, tag_name);
+
+ freelog(LOG_DEBUG, "load_sprite(tag='%s')", tag_name);
+ if (!ss) {
+ return NULL;
+ }
+
+ assert(ss->ref_count >= 0);
+
+ if (!ss->sprite) {
+ assert(ss->ref_count == 0);
+ ensure_big_sprite(ss->sf);
+ ss->sprite =
+ crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height);
+ }
+
+ ss->ref_count++;
+ return ss->sprite;
+}
+
+void finish_loading(void)
+{
+ specfile_list_iterate(specfiles, sf) {
+ if (sf->big_sprite) {
+ free_sprite(sf->big_sprite);
+ sf->big_sprite = NULL;
+ }
+ } specfile_list_iterate_end;
+}
+
+void unload_sprite(const char *tag_name)
+{
+ struct small_sprite *ss = hash_lookup_data(sprite_hash, tag_name);
+
+ assert(ss);
+ assert(ss->ref_count >= 1);
+ assert(ss->sprite);
+
+ ss->ref_count--;
+
+ if (ss->ref_count == 0) {
+ freelog(LOG_NORMAL, "freeing sprite '%s'", tag_name);
+ free_sprite(ss->sprite);
+ ss->sprite = NULL;
+ }
+}
diff -Nurd -X clean/diff_ignore clean/client/tilespec.h
tileset/client/tilespec.h
--- clean/client/tilespec.h Mon Feb 17 19:32:12 2003
+++ tileset/client/tilespec.h Sat Feb 15 22:20:29 2003
@@ -210,10 +210,6 @@
extern char current_tile_set_name[512];
-/* full pathnames: */
-extern char *main_intro_filename;
-extern char *minimap_intro_filename;
-
/* NOTE: The following comments are out of date and need to
* be revised! -- dwp
*
@@ -261,4 +257,8 @@
extern int num_tiles_explode_unit;
+struct Sprite *load_sprite(const char *tag_name);
+void unload_sprite(const char *tag_name);
+void finish_loading(void);
+
#endif /* FC__TILESPEC_H */
diff -Nurd -X clean/diff_ignore clean/data/misc/intro.spec
tileset/data/misc/intro.spec
--- clean/data/misc/intro.spec Thu Jan 1 01:00:00 1970
+++ tileset/data/misc/intro.spec Sat Feb 15 22:37:44 2003
@@ -0,0 +1,27 @@
+
+[spec]
+
+; Format and options of this spec file:
+options = "+spec2"
+
+[info]
+
+artists = ""
+
+[file]
+gfx = "misc/intro"
+
+[grid_main]
+
+; Could use separate "grids" for the smaller components, but not
+; bothering for now.
+
+x_top_left = 0
+y_top_left = 0
+dx = 510
+dy = 300
+
+tiles = { "row", "column", "tag"
+
+ 0, 0, "special.intro"
+}
diff -Nurd -X clean/diff_ignore clean/data/misc/radar.spec
tileset/data/misc/radar.spec
--- clean/data/misc/radar.spec Thu Jan 1 01:00:00 1970
+++ tileset/data/misc/radar.spec Sat Feb 15 22:38:00 2003
@@ -0,0 +1,27 @@
+
+[spec]
+
+; Format and options of this spec file:
+options = "+spec2"
+
+[info]
+
+artists = ""
+
+[file]
+gfx = "misc/radar"
+
+[grid_main]
+
+; Could use separate "grids" for the smaller components, but not
+; bothering for now.
+
+x_top_left = 0
+y_top_left = 0
+dx = 160
+dy = 100
+
+tiles = { "row", "column", "tag"
+
+ 0, 0, "special.radar"
+}
diff -Nurd -X clean/diff_ignore clean/data/trident.tilespec
tileset/data/trident.tilespec
--- clean/data/trident.tilespec Mon Feb 17 19:32:12 2003
+++ tileset/data/trident.tilespec Sat Feb 15 22:41:05 2003
@@ -30,11 +30,6 @@
; Font to use to draw city productions:
city_productions_font = "6x13"
-; These are special because they get freed and reloaded
-; as required:
-main_intro_file = "misc/intro"
-minimap_intro_file = "misc/radar"
-
; Below, the graphics spec files; must be somewhere (anywhere) in
; the data path. Order may be important for color allocation on
; low-color systems, and if there are any duplicate tags (lattermost
@@ -50,4 +45,6 @@
; "misc/techs.spec",
"misc/treaty.spec",
"trident/cities.spec",
- "trident/explosions.spec"
+ "trident/explosions.spec",
+ "misc/intro.spec",
+ "misc/radar.spec"
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#3457) New sprite loading,
Raimar Falke <=
|
|