Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2003:
[Freeciv-Dev] (PR#2922) Data reorganization patch
Home

[Freeciv-Dev] (PR#2922) Data reorganization patch

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] (PR#2922) Data reorganization patch
From: "esr@xxxxxxxxxxx via RT" <rt@xxxxxxxxxxxxxx>
Date: Mon, 27 Jan 2003 17:14:04 -0800
Reply-to: rt@xxxxxxxxxxxxxx

This is the stage 1 data reorganization patch.

This patch eliminates graphics spec files and sprite-array PNGs.  Instead,
sprites are stored one per file, in files named after the sprite tag, under
data/graphics.

I have tested this patch.  It looked horribly broken until I fixed imagehack
to pass transparency information from the parent PNG through to the extracted
sprites, at which point it started working perfectly.  That is, the main 
display looks exactly as it did before.

Only one C file is touched.  Everything else is data changes.

To apply it:

1. cd to the top-level directory of the source distribution

2. Apply patch -p0 <PATCH

3. Unpack the enclosed tarball to create the data/graphics directory.

To revert to the old organization, simply reverse PATCH.  This
patch leaves the graphics specfiles and image grids in place.  Those
will be removed by a cleanup patch once this one proves out.
-- 
                <a href="http://www.tuxedo.org/~esr/";>Eric S. Raymond</a>

Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.106
diff -u -r1.106 tilespec.c
--- client/tilespec.c   2003/01/21 20:25:30     1.106
+++ client/tilespec.c   2003/01/27 21:19:24
@@ -25,6 +25,9 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "astring.h"
 #include "capability.h"
@@ -81,8 +84,8 @@
 static bool is_mountainous = FALSE;
 static int roadstyle;
 
-static int num_spec_files = 0;
-static char **spec_filenames;  /* full pathnames */
+static int num_spec_directories = 0;
+static char **spec_directories;        /* full pathnames */
 
 static struct hash_table *sprite_hash = NULL;
 /*
@@ -104,14 +107,7 @@
                      should specify "+roadstyle".
 */
 
-#define SPEC_CAPSTR "+spec2"
 /*
-   Individual spec file capabilities acceptable to this program:
-   +spec2          -  basic format, required
-*/
-
-
-/*
   If focus_unit_hidden is true, then no units at
   the location of the foc unit are ever drawn.
 */
@@ -187,25 +183,23 @@
 /**********************************************************************
   Checks options in filename match what we require and support.
   Die if not.
-  'which' should be "tilespec" or "spec".
 ***********************************************************************/
 static void check_tilespec_capabilities(struct section_file *file,
-                                       const char *which,
                                        const char *us_capstr,
                                        const char *filename)
 {
-  char *file_capstr = secfile_lookup_str(file, "%s.options", which);
+  char *file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
   
   if (!has_capabilities(us_capstr, file_capstr)) {
-    freelog(LOG_FATAL, _("%s file appears incompatible:"), which);
+    freelog(LOG_FATAL, _("tilespec file appears incompatible:"));
     freelog(LOG_FATAL, _("file: \"%s\""), filename);
     freelog(LOG_FATAL, _("file options: %s"), file_capstr);
     freelog(LOG_FATAL, _("supported options: %s"), us_capstr);
     exit(EXIT_FAILURE);
   }
   if (!has_capabilities(file_capstr, us_capstr)) {
-    freelog(LOG_FATAL, _("%s file claims required option(s)"
-                        " which we don't support:"), which);
+    freelog(LOG_FATAL, _("tilespec file claims required option(s)"
+                        " which we don't support:"));
     freelog(LOG_FATAL, _("file: \"%s\""), filename);
     freelog(LOG_FATAL, _("file options: %s"), file_capstr);
     freelog(LOG_FATAL, _("supported options: %s"), us_capstr);
@@ -265,7 +259,7 @@
     free(minimap_intro_filename);
     minimap_intro_filename = NULL;
   }
-  /* FIXME: free spec_filenames */
+  /* FIXME: free spec_directories */
 }
 
 /**********************************************************************
@@ -393,7 +387,7 @@
     freelog(LOG_FATAL, _("Could not open \"%s\"."), fname);
     exit(EXIT_FAILURE);
   }
-  check_tilespec_capabilities(file, "tilespec", TILESPEC_CAPSTR, fname);
+  check_tilespec_capabilities(file, TILESPEC_CAPSTR, fname);
 
   (void) section_file_lookup(file, "tilespec.name"); /* currently unused */
 
@@ -457,16 +451,16 @@
   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);
+  spec_directories = secfile_lookup_str_vec(file, &num_spec_directories,
+                                         "tilespec.directories");
+  if (num_spec_directories == 0) {
+    freelog(LOG_FATAL, "No tile directories specified in \"%s\"", fname);
     exit(EXIT_FAILURE);
   }
   
-  for(i=0; i<num_spec_files; i++) {
-    spec_filenames[i] = mystrdup(datafilename_required(spec_filenames[i]));
-    freelog(LOG_DEBUG, "spec file %s", spec_filenames[i]);
+  for(i=0; i<num_spec_directories; i++) {
+    spec_directories[i] = mystrdup(datafilename_required(spec_directories[i]));
+    freelog(LOG_DEBUG, "spec directory %s", spec_directories[i]);
   }
 
   section_file_check_unused(file, fname);
@@ -477,102 +471,85 @@
 }
 
 /**********************************************************************
-  Load one specfile and specified xpm file; splits xpm into tiles,
-  and save sprites in sprite_hash.
+  Load sprites from a specified image directory, 
+  and save them in sprite_hash.
 ***********************************************************************/
-static void tilespec_load_one(const char *spec_filename)
+static void tilespec_load_one(const char *image_dir)
 {
-  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);
+  DIR *dir;
+  struct dirent *entry;
+  struct stat status;
+  struct Sprite *sprite = NULL;
+  const char *gfx_current_fileext, **gfx_fileexts;
+  char spritename[PATH_MAX+1], filename[PATH_MAX+1], *dot;
+
+  freelog(LOG_DEBUG, "loading image directory %s", image_dir);
+  dir = opendir(image_dir);
+  if (dir == NULL)
+  {
+    freelog(LOG_FATAL, _("Could not open \"%s\"."), image_dir);
+    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++))
+  while ((entry = readdir(dir)) != NULL)
   {
-    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 (strcmp(entry->d_name, ".")==0 || strcmp(entry->d_name, "..")==0)
+       continue;
+    if (!strchr(entry->d_name, '.'))   /* skip artists file and README */
+      continue;
 
-    if((real_full_name = datafilename(full_name)))
+    strcpy(spritename, entry->d_name);
+    dot = strrchr(spritename, '.');
+    dot[0] = '\0';
+
+    strcpy(filename, image_dir);
+    strcat(filename, "/");
+    strcat(filename, entry->d_name);
+    dot = strrchr(filename, '.');
+    for (gfx_current_fileext = *gfx_fileexts; 
+        gfx_current_fileext; 
+        gfx_current_fileext = *gfx_fileexts++)
     {
-      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);
-      }
+      if (strcmp(dot+1, gfx_current_fileext) == 0)
+         goto found_gfx;
     }
-    free(full_name);
-  }
+    freelog(LOG_DEBUG, 
+           "extension of %s doesn't match a known graphics type", 
+           entry->d_name);
+    continue;
 
-  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);
+    found_gfx:
+    {
+      char *real_full_name;
+      real_full_name = datafilename(filename);
+      if (stat(real_full_name, &status) != 0)
+      {
+       freelog(LOG_FATAL, _("Could not stat \"%s\"."), real_full_name);
+       exit(EXIT_FAILURE);    
+      }
+      if (!S_ISREG(status.st_mode))
+       continue;
+      if (real_full_name)
+      {
+         freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
+         if ((sprite = load_gfxfile(real_full_name)))
+         {
+             freelog(LOG_DEBUG, "trying to load gfx file %s", real_full_name);
+             /* don't free old sprite, could be many tags pointing to it */
+             (void) hash_replace(sprite_hash,mystrdup(spritename),sprite);
+         }
+         else
+         {
+             freelog(LOG_FATAL, _("Couldn't load gfx file %s"),entry->d_name);
+             exit(EXIT_FAILURE);
+         }
       }
-      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);
+  closedir(dir);
+  freelog(LOG_DEBUG, "finished %s", image_dir);
 }
 
 /**********************************************************************
@@ -910,11 +887,11 @@
 {
   int i;
   
-  assert(num_spec_files>0);
+  assert(num_spec_directories>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]);
+  for(i=0; i<num_spec_directories; i++) {
+    tilespec_load_one(spec_directories[i]);
   }
 
   tilespec_lookup_sprite_tags();
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.6
diff -u -r1.6 isotrident.tilespec
--- data/isotrident.tilespec    2003/01/21 20:25:31     1.6
+++ data/isotrident.tilespec    2003/01/27 21:19:28
@@ -38,21 +38,21 @@
 main_intro_file    = "misc/intro"
 minimap_intro_file = "misc/radar"
 
-; Below, the graphics spec files; must be somewhere (anywhere) in 
+; Below, the graphics directories; 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
 ; tag is used).
-files = 
-  "isotrident/terrain1.spec",
-  "isotrident/terrain2.spec",
-  "isotrident/tiles.spec",
-  "isotrident/small.spec",
-  "isotrident/units.spec",
-  "isotrident/flags.spec",
-  "misc/buildings.spec",
-  "misc/space.spec",
-  "misc/techs.spec",
-  "misc/treaty.spec",
-  "isotrident/nuke.spec",
-  "isotrident/cities.spec",
-  "isotrident/morecities.spec"
+directories = 
+  "graphics/isotrident/terrain1",
+  "graphics/isotrident/terrain2",
+  "graphics/isotrident/tiles",
+  "graphics/isotrident/small",
+  "graphics/isotrident/units",
+  "graphics/isotrident/flags",
+  "graphics/misc/buildings",
+  "graphics/misc/space",
+  "graphics/misc/techs",
+  "graphics/misc/treaty",
+  "graphics/isotrident/nuke",
+  "graphics/isotrident/cities",
+  "graphics/isotrident/morecities"
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.13
diff -u -r1.13 trident.tilespec
--- data/trident.tilespec       2003/01/21 20:25:31     1.13
+++ data/trident.tilespec       2003/01/27 21:19:28
@@ -38,19 +38,19 @@
 main_intro_file    = "misc/intro"
 minimap_intro_file = "misc/radar"
 
-; Below, the graphics spec files; must be somewhere (anywhere) in 
+; Below, the graphics directories; 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
 ; tag is used).
-files = 
-  "trident/tiles.spec",
-  "misc/small.spec",
-  "trident/units.spec",
-  "trident/flags.spec",
-  "trident/roads.spec",
-  "misc/buildings.spec",
-  "misc/space.spec",
-  "misc/techs.spec",
-  "misc/treaty.spec",
-  "trident/cities.spec",
-  "trident/explosions.spec"
+directories = 
+  "graphics/trident/tiles.spec",
+  "graphics/misc/small.spec",
+  "graphics/trident/units.spec",
+  "graphics/trident/flags.spec",
+  "graphics/trident/roads.spec",
+  "graphics/misc/buildings.spec",
+  "graphics/misc/space.spec",
+  "graphics/misc/techs.spec",
+  "graphics/misc/treaty.spec",
+  "graphics/trident/cities.spec",
+  "graphics/trident/explosions.spec"
Index: data/trident_shields.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident_shields.tilespec,v
retrieving revision 1.5
diff -u -r1.5 trident_shields.tilespec
--- data/trident_shields.tilespec       2003/01/21 20:25:31     1.5
+++ data/trident_shields.tilespec       2003/01/27 21:19:28
@@ -38,22 +38,22 @@
 main_intro_file    = "misc/intro"
 minimap_intro_file = "misc/radar"
 
-; Below, the graphics spec files; must be somewhere (anywhere) in 
+; Below, the graphics directories; 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
 ; tag is used).
 files = 
-  "trident/tiles.spec",
-  "misc/small.spec",
-  "trident/units.spec",
-  "trident/flags.spec",
-  "trident/roads.spec",
-  "misc/buildings.spec",
-  "misc/space.spec",
-  "misc/techs.spec",
-  "misc/treaty.spec",
-  "trident/cities.spec",
-  "trident/explosions.spec",
-  "trident/auto_ll.spec",
-  "misc/chiefs.spec",
-  "misc/shields.spec"
+  "graphics/trident/tiles",
+  "graphics/misc/small",
+  "graphics/trident/units",
+  "graphics/trident/flags",
+  "graphics/trident/roads",
+  "graphics/misc/buildings",
+  "graphics/misc/space",
+  "graphics/misc/techs",
+  "graphics/misc/treaty",
+  "graphics/trident/cities",
+  "graphics/trident/explosions",
+  "graphics/trident/auto_ll",
+  "graphics/misc/chiefs",
+  "graphics/misc/shields"
Index: doc/PEOPLE
===================================================================
RCS file: /home/freeciv/CVS/freeciv/doc/PEOPLE,v
retrieving revision 1.24
diff -u -r1.24 PEOPLE
--- doc/PEOPLE  2002/12/02 17:55:00     1.24
+++ doc/PEOPLE  2003/01/27 21:19:30
@@ -133,6 +133,7 @@
      Ross Wetmore <rwetmore@xxxxxxxxxxxx> (autogame, fixes)
      Janus N. T�ndering <j@xxxxxxxxxxxxx> (chat history)
      Martin Douda <martin@xxxxxxxxx> (fixes)
+     Eric S. Raymond <esr@xxxxxxxxxxx> (new data file organization)
 
   Coders since 1.11.4 release:
 
Index: doc/README.graphics
===================================================================
RCS file: /home/freeciv/CVS/freeciv/doc/README.graphics,v
retrieving revision 1.4
diff -u -r1.4 README.graphics
--- doc/README.graphics 2002/12/17 00:50:43     1.4
+++ doc/README.graphics 2003/01/27 21:19:31
@@ -20,7 +20,7 @@
 That is all you need to know to use alternative graphics provided by
 Freeciv or by third-party add-ons.  The rest of this file describes
 (though not fully) the contents of the tilespec file and related
-files.  This is intended as developer reference, and for people
+directories.  This is intended as developer reference, and for people
 wanting to create/compile alternative tilesets and modpacks for
 Freeciv.
 
@@ -28,30 +28,24 @@
 Overview:
 ---------
 
-The purpose of the 'tilespec' file and related 'spec' files is to
-allow the detailed layout of the graphics within the files to be
-flexible and not hard-coded into Freeciv, and to allow add-ons to
-conveniently provide additional graphics.
-
-There are two layers to the tilespec files:
-
-The top-level file is named, eg: 'trident.tilespec'.  The basename of
-this file (here, 'trident') corresponds to the parameter of the
-'--tiles' command-line argument for the Freeciv client, as described
-above.
-
-The top-level tilespec file contains general information on the full
-tileset, and a list of files which specify information about the
-individual graphics files.  These filenames must be located somewhere
-in the data path, though not necessarily the same place as the
-top-level tilespec file.  Note that with this system the number and
-contents of the referenced files are completely flexible at this
-level.
-
-An exception is that the intro graphics must be in individual files,
-as listed in the tilespec file, because Freeciv treats these
-specially: these graphics are freed after the game starts, and
-reloaded later as necessary.
+The purpose of the 'tilespec' file and related directories is to allow
+choice of graphics flexible and not hard-coded into Freeciv, and to
+allow add-ons to conveniently provide additional graphics.
+
+Each tilespec is named with a basename plus the tilespec extension, e.g.:
+'trident.tilespec'.  The basename of this file (here, 'trident')
+corresponds to the parameter of the '--tiles' command-line argument
+for the Freeciv client, as described above.
+
+The tilespec file contains general information on the full tileset,
+and a list of directories to search for the individual sprite files.
+These directories must be located somewhere in the data path, though
+not necessarily the same place as the top-level tilespec file.
+
+Note: the second-level graphics resource files and graphics array
+files found in Freeciv versions up to 1.14 are gone. They have been
+replaced by a much simpler system of individual sprites kept as files
+in a common graphics directory.
 
 ----------------------------------------------------------------------
 Tileset options:
@@ -85,47 +79,17 @@
 
   String lists (a comma-separated list of strings)
   ------------------------------------------------
-  files                 : A list of .spec files to scan for sprites.
-                          See "individual spec files", below.
+  directories           : A list of directories to scan for sprites.
 
 ----------------------------------------------------------------------
-Individual spec files:
-----------------------
-
-Each spec file describes one graphics file (PNG format is standard,
-although some clients may accept other formats as well) as specified in
-the spec file.  The graphics file must be in the Freeciv data path, but
-not necessarily in the same location as the spec file.  Note you can have
-multiple spec files using a single graphics file in different ways.
-
-The main data described in the spec file is in sections named
-[grid_*], where * is some arbitrary tag (but unique within each file).
-A grid corresponds to a regular rectangular array of tiles.  In
-general one may have multiple grids in one file, but the default
-tilesets usually only have one per file.  (Multiple grids would be
-useful to have different size tiles in the same file.)  Each grid
-defines an origin (top left) and spacing, both in terms of pixels, and
-then refers to individual tiles of the grid by row and column.  The
-origin, and rows and columns, are counted as (0,0) = top left.
-
-Each individual tile is given a "tag", which is a string which is
-referenced in the code and/or from ruleset files.  A grid may be
-sparse, with some elements unused (simply don't mention their row and
-column), and a single tile may have multiple tags (eg, to use the same
-graphic for multiple purposes in the game): just specify a list of
-comma-separated strings.
-
-If a given tag appears multiple times in the spec files, the *last*
-such tag is used.  (That is, in the order of files listed in the
-tilespec file, and order within each file.)  This allows selected
-graphics to be "overridden" by listing a replacement spec file near
-the end of the 'files' list in the toplevel tilespec file, without
-having to modify earlier files in the list.
-
-----------------------------------------------------------------------
-Tag prefixes:
+Sprite files:
 -------------
 
+Each individual sprite is given an internal "tag", a name
+referenced in the code and/or from ruleset files.  The sprite lives in a
+PNG file named after its tag, somewhere in the set of graphics
+directories listed in the parent tilespec file.
+
 To help keep the tags organised, there is a rough prefix system used 
 for standard tags:
 
@@ -152,11 +116,8 @@
 provided by ruleset files (at least for the "standard" rulesets)
 should also be provided, but generally the client will continue even
 if they are not, though the results may not be satisfactory for the
-user.  To work properly tags should correspond to appropriately sized
-graphics.  (The basic size may vary, as specified in the top-level
-tilespec file, but the individual tiles should be consistent with
-those sizes and/or the usage of those graphics.)
-  
+user.
+
 ----------------------------------------------------------------------
 
 Information on certain tags:

Attachment: graphics.tgz
Description: graphics.tgz


[Prev in Thread] Current Thread [Next in Thread]