Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2002:
[Freeciv-Dev] (PR#1930) switching tilesets at runtime
Home

[Freeciv-Dev] (PR#1930) switching tilesets at runtime

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Cc: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#1930) switching tilesets at runtime
From: "Jason Short via RT" <rt@xxxxxxxxxxxxxx>
Date: Tue, 12 Nov 2002 18:25:37 -0800
Reply-to: rt@xxxxxxxxxxxxxx

[jdorje - Fri Aug 16 18:10:12 2002]:

> The time has finally come...the client is, IMO, ready for a patch that 
> will switch tilesets at runtime.

Here is an updated patch to do this.  It adds a new entry to the "local
options" dialog that allows you to change the current tileset.  Simply
apply it and try it out.  It works best if you have lots of tilesets
sitting around (put them in ~/.freeciv).

Raimar wanted this to instead be controlled through menus.  I agree that
doing so will be more friendly to new players.  It will also take a lot
more gui-specific code.  And I don't think having it in two places is
that bad.

It would be desirable to have a popup dialog to tell the player this is
an experimental feature.  This also has to be done for each GUI.

The only GUI code written so far is for GTK.  It partially updates the
city dialog windows when the tileset switches.  But it does not give the
user a dialog yet.

I have added a new GUI function, update_for_changed_tileset().  For lack
of anywhere better I've placed this in mapview.c.  Is there somewhere it
should go instead?  What about a better name (it shouldn't be too
specific, though - the function may have to do very different things in
different tilesets)?

jason

? client/gui-gtk/diff
? client/gui-stub/stub-update.diff
? client/gui-xaw/diff
Index: client//options.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/options.c,v
retrieving revision 1.69
diff -u -r1.69 options.c
--- client//options.c   2002/11/12 23:19:42     1.69
+++ client//options.c   2002/11/13 02:13:52
@@ -22,6 +22,7 @@
 
 #include "audio.h"
 #include "clinet.h"
+#include "civclient.h"
 #include "events.h"
 #include "fcintl.h"
 #include "log.h"
@@ -89,8 +90,10 @@
   GEN_INT_OPTION(default_server_port,       N_("Default server's port")),
   GEN_STR_OPTION(default_metaserver,        N_("Default metaserver"),
                 NULL, NULL),
-  GEN_STR_OPTION(default_tile_set_name,     N_("Tileset"),
+  GEN_STR_OPTION(default_tile_set_name,     N_("Default tileset"),
                 get_tileset_list, NULL),
+  GEN_STR_OPTION(tile_set_name,             N_("Current tileset"),
+                 get_tileset_list, tilespec_reread_callback),
   GEN_STR_OPTION(default_sound_set_name,    N_("Default name of sound set"),
                 get_soundset_list, NULL),
   GEN_STR_OPTION(default_sound_plugin_name, N_("Default sound plugin"),
Index: client//tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.88
diff -u -r1.88 tilespec.c
--- client//tilespec.c  2002/11/12 15:43:55     1.88
+++ client//tilespec.c  2002/11/13 02:13:53
@@ -45,6 +45,7 @@
 #include "climisc.h" /* for tile_get_known() */
 #include "control.h" /* for fill_xxx */
 #include "graphics_g.h"
+#include "mapview_g.h" /* for update_map_canvas_visible */
 #include "options.h" /* for fill_xxx */
 
 #include "tilespec.h"
@@ -226,6 +227,124 @@
   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().
+***********************************************************************/
+static void tilespec_free_toplevel(void)
+{
+  if (city_names_font) {
+    free(city_names_font);
+    city_names_font = NULL;
+  }
+  if (city_productions_font_name) {
+    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 */
+}
+
+/**********************************************************************
+  Read a new tilespec in from scratch.
+
+  Unlike the initial reading code, which reads pieces one at a time,
+  this gets rid of the old data and reads in the new all at once.
+
+  It will also call the necessary functions to redraw the graphics.
+***********************************************************************/
+void tilespec_reread(const char *tileset_name)
+{
+  int id;
+  int center_x, center_y;
+
+  freelog(LOG_NORMAL, "Loading tileset %s.", tileset_name);
+
+  /* Step 0:  Record old data.
+   *
+   * We record the current mapcanvas center, etc.
+   */
+  get_center_tile_mapcanvas(&center_x, &center_y);
+
+  /* Step 1:  Cleanup.
+   *
+   * We free any old data in preparation for re-reading it.
+   * This is pretty certainly incomplete, although the memory leak
+   * doesn't seem to be debilitating.
+   */
+  hash_free(sprite_hash);
+  tilespec_free_toplevel();
+
+  /* Step 2:  Read.
+   *
+   * We read in the new tileset.  This should be pretty straightforward.
+   */
+  tilespec_read_toplevel(tileset_name);
+  tilespec_load_tiles();
+
+  /* Step 3: Setup
+   *
+   * This is a seriously sticky problem.  On
+   * startup, we build a hash from all the sprite data.
+   * Then, when we connect to a server, the server sends us
+   * ruleset data a piece at a time and we use this data to
+   * assemble the sprite structures.  But if we change
+   * while connected we have to reassemble all of these.  This
+   * _should_ just involve calling tilespec_setup_*** on
+   * everything.  But how do we tell what "everything" is?
+   *
+   * The below code assumes that everything really _is_
+   * everything.  But this probably isn't true.  In fact,
+   * it's _certainly_ not true if we haven't received the
+   * info from the server yet.  OTOH, this may just
+   * initialize things to NULL in this case.
+   */
+  for (id = T_FIRST; id < T_COUNT; id++) {
+    tilespec_setup_tile_type(id);
+  }
+  unit_type_iterate(id) {
+    tilespec_setup_unit_type(id);
+  } unit_type_iterate_end;
+  for (id = 0; id < game.government_count; id++) {
+    tilespec_setup_government(id);
+  }
+  for (id = 0; id < game.nation_count; id++) {
+    tilespec_setup_nation_flag(id);
+  }
+
+  /* tilespec_load_tiles reverts the city tile pointers to 0.  This
+     is a workaround. */
+  tilespec_alloc_city_tiles(game.styles_count);
+  for (id = 0; id < game.styles_count; id++) {
+    tilespec_setup_city_tiles(id);
+  }
+
+  /* Step 4:  Draw.
+   *
+   * Do any necessary redraws.
+   */
+  update_for_changed_tileset();
+  center_tile_mapcanvas(center_x, center_y);
+}
+
+/**************************************************************************
+  This is merely a wrapper for tilespec_reread (above) for use in
+  options.c and the client local options dialog.
+**************************************************************************/
+void tilespec_reread_callback(struct client_option *option)
+{
+  assert(option->p_string_value && *option->p_string_value);
+  tilespec_reread(option->p_string_value);
 }
 
 /**********************************************************************
Index: client//tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.30
diff -u -r1.30 tilespec.h
--- client//tilespec.h  2002/09/28 01:36:20     1.30
+++ client//tilespec.h  2002/11/13 02:13:53
@@ -21,6 +21,7 @@
 #include "map.h"               /* NUM_DIRECTION_NSEW */
 
 #include "colors_g.h"
+#include "options.h"
 
 struct Sprite;                 /* opaque; gui-dep */
 struct unit;
@@ -31,6 +32,9 @@
 void tilespec_read_toplevel(const char *tileset_name);
 void tilespec_load_tiles(void);
 void tilespec_free_tiles(void);
+
+void tilespec_reread(const char *tileset_name);
+void tilespec_reread_callback(struct client_option *option);
 
 void tilespec_setup_unit_type(int id);
 void tilespec_setup_tile_type(int id);
Index: client//gui-gtk/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/citydlg.c,v
retrieving revision 1.144
diff -u -r1.144 citydlg.c
--- client//gui-gtk/citydlg.c   2002/11/07 16:04:52     1.144
+++ client//gui-gtk/citydlg.c   2002/11/13 02:13:55
@@ -313,17 +313,11 @@
 static void switch_city_callback(GtkWidget * w, gpointer data);
 
 /****************************************************************
-...
+  Called to set the dimensions of the city dialog, both on
+  startup and if the tileset is changed.
 *****************************************************************/
-static void initialize_city_dialogs(void)
+static void init_citydlg_dimensions(void)
 {
-  int i;
-  GdkColor orange = { 0, 65535, 32768, 0 };    /* not currently used */
-  GdkColor red = { 0, 65535, 0, 0 };
-
-  assert(!city_dialogs_have_been_initialised);
-
-  dialog_list_init(&dialog_list);
   if (is_isometric) {
     canvas_width = 4 * NORMAL_TILE_WIDTH;
     canvas_height = 4 * NORMAL_TILE_HEIGHT;
@@ -333,7 +327,22 @@
     canvas_height = 5 * NORMAL_TILE_HEIGHT;
     MAX_UNIT_ROWS = (int) (100 / (UNIT_TILE_HEIGHT + 6));
   }
+}
 
+/****************************************************************
+...
+*****************************************************************/
+static void initialize_city_dialogs(void)
+{
+  int i;
+  GdkColor orange = { 0, 65535, 32768, 0 };    /* not currently used */
+  GdkColor red = { 0, 65535, 0, 0 };
+
+  assert(!city_dialogs_have_been_initialised);
+
+  dialog_list_init(&dialog_list);
+  init_citydlg_dimensions();
+
   NUM_UNITS_SHOWN = (int) (MAX_UNIT_ROWS * 500) / (UNIT_TILE_WIDTH);
 
   /* make the styles */
@@ -348,6 +357,25 @@
   info_label_style[RED]->fg[GTK_STATE_NORMAL] = red;
 
   city_dialogs_have_been_initialised = TRUE;
+}
+
+/****************************************************************
+  Called when the tileset changes.
+*****************************************************************/
+void reset_city_dialogs(void)
+{
+  if (!city_dialogs_have_been_initialised) {
+    return;
+  }
+
+  init_citydlg_dimensions();
+
+  dialog_list_iterate(dialog_list, pdialog) {
+    /* There's no reasonable way to resize a GtkPixcomm, so we don't try.
+       Instead we just redraw the overview within the existing area.  The
+       player has to close and reopen the dialog to fix this. */
+    city_dialog_update_map(pdialog);
+  } dialog_list_iterate_end;
 }
 
 /****************************************************************
Index: client//gui-gtk/citydlg.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/citydlg.h,v
retrieving revision 1.7
diff -u -r1.7 citydlg.h
--- client//gui-gtk/citydlg.h   2002/02/09 02:04:30     1.7
+++ client//gui-gtk/citydlg.h   2002/11/13 02:13:55
@@ -15,4 +15,6 @@
 
 #include "citydlg_g.h"
 
+void reset_city_dialogs(void);
+
 #endif                         /* FC__CITYDLG_H */
Index: client//gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.127
diff -u -r1.127 mapview.c
--- client//gui-gtk/mapview.c   2002/08/25 11:20:56     1.127
+++ client//gui-gtk/mapview.c   2002/11/13 02:13:56
@@ -45,6 +45,7 @@
 #include "options.h"
 #include "tilespec.h"
 
+#include "citydlg.h" /* For reset_city_dialogs() */
 #include "mapview.h"
 
 /* contains the x0, y0 coordinates of the upper left corner block */
@@ -2267,4 +2268,12 @@
                                 sprites.tx.fortress,
                                 offset_x, offset_y_unit,
                                 width, height_unit, fog);
+}
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  reset_city_dialogs();
 }
Index: client//gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.14
diff -u -r1.14 mapview.c
--- client//gui-gtk-2.0/mapview.c       2002/11/02 21:27:44     1.14
+++ client//gui-gtk-2.0/mapview.c       2002/11/13 02:13:57
@@ -2316,3 +2316,16 @@
                                 offset_x, offset_y_unit,
                                 width, height_unit, fog);
 }
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  /* PORTME */
+  /* Here you should do any necessary redraws (for instance, the city
+   * dialogs usually need to be resized), and pop up a disclaimer
+   * window (something like "Switching tilesets is an experimental
+   * feature.  You may want to restart the client before proceeding.").
+   */
+}
Index: client//gui-mui/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/mapview.c,v
retrieving revision 1.41
diff -u -r1.41 mapview.c
--- client//gui-mui/mapview.c   2002/08/24 14:37:44     1.41
+++ client//gui-mui/mapview.c   2002/11/13 02:13:57
@@ -637,3 +637,16 @@
 {
   DoMethod(main_map_area, MUIM_Map_UndrawSegment, src_x, src_y, dir);
 }
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  /* PORTME */
+  /* Here you should do any necessary redraws (for instance, the city
+   * dialogs usually need to be resized), and pop up a disclaimer
+   * window (something like "Switching tilesets is an experimental
+   * feature.  You may want to restart the client before proceeding.").
+   */
+}
Index: client//gui-stub/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-stub/mapview.c,v
retrieving revision 1.12
diff -u -r1.12 mapview.c
--- client//gui-stub/mapview.c  2002/08/24 14:37:46     1.12
+++ client//gui-stub/mapview.c  2002/11/13 02:13:57
@@ -150,3 +150,16 @@
 {
        /* PORTME */
 }
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  /* PORTME */
+  /* Here you should do any necessary redraws (for instance, the city
+   * dialogs usually need to be resized), and pop up a disclaimer
+   * window (something like "Switching tilesets is an experimental
+   * feature.  You may want to restart the client before proceeding.").
+   */
+}
Index: client//gui-win32/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/mapview.c,v
retrieving revision 1.29
diff -u -r1.29 mapview.c
--- client//gui-win32/mapview.c 2002/08/24 14:37:47     1.29
+++ client//gui-win32/mapview.c 2002/11/13 02:13:58
@@ -2129,3 +2129,16 @@
     }
   }
 }
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  /* PORTME */
+  /* Here you should do any necessary redraws (for instance, the city
+   * dialogs usually need to be resized), and pop up a disclaimer
+   * window (something like "Switching tilesets is an experimental
+   * feature.  You may want to restart the client before proceeding.").
+   */
+}
Index: client//gui-xaw/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/mapview.c,v
retrieving revision 1.99
diff -u -r1.99 mapview.c
--- client//gui-xaw/mapview.c   2002/08/24 14:37:48     1.99
+++ client//gui-xaw/mapview.c   2002/11/13 02:13:59
@@ -1287,3 +1287,16 @@
     }
   }
 }
+
+/**************************************************************************
+  This function is called when the tileset is changed.
+**************************************************************************/
+void update_for_changed_tileset(void)
+{
+  /* PORTME */
+  /* Here you should do any necessary redraws (for instance, the city
+   * dialogs usually need to be resized), and pop up a disclaimer
+   * window (something like "Switching tilesets is an experimental
+   * feature.  You may want to restart the client before proceeding.").
+   */
+}
Index: client//include/mapview_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/mapview_g.h,v
retrieving revision 1.19
diff -u -r1.19 mapview_g.h
--- client//include/mapview_g.h 2002/08/24 14:37:50     1.19
+++ client//include/mapview_g.h 2002/11/13 02:13:59
@@ -54,4 +54,6 @@
 void draw_segment(int src_x, int src_y, int dir);
 void undraw_segment(int src_x, int src_y, int dir);
 
+void update_for_changed_tileset(void);
+
 #endif  /* FC__MAPVIEW_G_H */

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