Complete.Org: Mailing Lists: Archives: freeciv-dev: June 2004:
[Freeciv-Dev] (PR#8973) build citydlg canvas sizes on demand
Home

[Freeciv-Dev] (PR#8973) build citydlg canvas sizes on demand

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8973) build citydlg canvas sizes on demand
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 13 Jun 2004 00:49:12 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8973 >

This is a preliminary patch to determine the citydlg size at runtime.

The way it works is this:

- When the topology is set or the tileset is changed, the citydlg width 
and height are recalculated.

- city_to_canvas_pos and canvas_to_city_pos are anchored only by the 
citydlg width and height.  Once these are set correctly the rest will 
just work - without any additional "magic" numbers.

The width and height are actually calculated by a series of calls to 
city_to_canvas_pos.  Although this may seem hackish it's actually pretty 
logical.

With this patch all magic numbers are removed from the citydlg and all 
sorts of city changes should work transparently.  We can change 
CITY_MAP_RADIUS or allow this value to be set by the ruleset.  Or we can 
use hex tiles and have a different set of citymap tiles.  So long as the 
width and height are generated in the proper places it should all just work.

I say this patch is preliminary because it depends at least on the 
map_to_gui_vector() patch.  That patch makes the necessary changes for 
city_to_canvas_pos.  This patch also includes the extra width/height 
changes as well as changes to canvas_to_city_pos.

jason

Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.35
diff -u -r1.35 citydlg_common.c
--- client/citydlg_common.c     2 Jun 2004 22:54:14 -0000       1.35
+++ client/citydlg_common.c     13 Jun 2004 07:12:54 -0000
@@ -31,16 +31,14 @@
 #include "options.h"           /* for concise_city_production */
 #include "tilespec.h"          /* for is_isometric */
 
+static int citydlg_width, citydlg_height;
+
 /**************************************************************************
   Return the width of the city dialog canvas.
 **************************************************************************/
 int get_citydlg_canvas_width(void)
 {
-  if (is_isometric) {
-    return (CITY_MAP_SIZE - 1) * NORMAL_TILE_WIDTH;
-  } else {
-    return CITY_MAP_SIZE * NORMAL_TILE_WIDTH;
-  }
+  return citydlg_width;
 }
 
 /**************************************************************************
@@ -48,11 +46,32 @@
 **************************************************************************/
 int get_citydlg_canvas_height(void)
 {
-  if (is_isometric) {
-    return (CITY_MAP_SIZE - 1) * NORMAL_TILE_HEIGHT;
-  } else {
-    return CITY_MAP_SIZE * NORMAL_TILE_HEIGHT;
-  }
+  return citydlg_height;
+}
+
+/**************************************************************************
+  Calculate the citydlg width and height.
+**************************************************************************/
+void generate_citydlg_dimensions(void)
+{
+  int min_x = 0, max_x = 0, min_y = 0, max_y = 0;
+
+  citydlg_width = citydlg_height = 0;
+  city_map_iterate(city_x, city_y) {
+    int canvas_x, canvas_y;
+
+    if (!city_to_canvas_pos(&canvas_x, &canvas_y, city_x, city_y)) {
+      assert(0);
+    }
+
+    min_x = MIN(canvas_x, min_x);
+    max_x = MAX(canvas_x, max_x);
+    min_y = MIN(canvas_y, min_y);
+    max_y = MAX(canvas_y, max_y);
+  } city_map_iterate_end;
+
+  citydlg_width = max_x - min_x + NORMAL_TILE_WIDTH;
+  citydlg_height = max_y - min_y + NORMAL_TILE_HEIGHT;
 }
 
 /**************************************************************************
@@ -61,22 +80,13 @@
 **************************************************************************/
 bool city_to_canvas_pos(int *canvas_x, int *canvas_y, int city_x, int city_y)
 {
-  if (is_isometric) {
-    /*
-     * The top-left corner is in the center of tile (-2, 2).  However,
-     * we're looking for the top-left corner of the tile, so we
-     * subtract off half a tile in each direction.  For a more
-     * rigorous example, see map_pos_to_canvas_pos().
-     */
-    int iso_x = (city_x - city_y) + (2 * CITY_MAP_RADIUS);
-    int iso_y = (city_x + city_y) - (0);
-
-    *canvas_x = (iso_x - 1) * NORMAL_TILE_WIDTH / 2;
-    *canvas_y = (iso_y - 1) * NORMAL_TILE_HEIGHT / 2;
-  } else {
-    *canvas_x = city_x * NORMAL_TILE_WIDTH;
-    *canvas_y = city_y * NORMAL_TILE_HEIGHT;
-  }
+  const int x0 = CITY_MAP_RADIUS, y0 = CITY_MAP_RADIUS;
+  const int width = get_citydlg_canvas_width();
+  const int height = get_citydlg_canvas_height();
+
+  map_to_gui_vector(canvas_x, canvas_y, city_x - x0, city_y - y0);
+  *canvas_x += (width - NORMAL_TILE_WIDTH) / 2;
+  *canvas_y += (height - NORMAL_TILE_HEIGHT) / 2;
 
   if (!is_valid_city_coords(city_x, city_y)) {
     assert(FALSE);
@@ -92,27 +102,33 @@
 bool canvas_to_city_pos(int *city_x, int *city_y, int canvas_x, int canvas_y)
 {
   int orig_canvas_x = canvas_x, orig_canvas_y = canvas_y;
+  const int width = get_citydlg_canvas_width();
+  const int height = get_citydlg_canvas_height();
+
+  canvas_x -= (width - NORMAL_TILE_WIDTH) / 2;
+  canvas_y -= (height - NORMAL_TILE_HEIGHT) / 2;
 
   if (is_isometric) {
     const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
 
-    /* Shift the tile right so the top corner of tile (-2,2) is at
+    /* Shift the tile left so the top corner of the origin tile is at
        canvas position (0,0). */
-    canvas_y += H / 2;
+    canvas_x -= W / 2;
 
     /* Perform a pi/4 rotation, with scaling.  See canvas_pos_to_map_pos
        for a full explanation. */
     *city_x = DIVIDE(canvas_x * H + canvas_y * W, W * H);
     *city_y = DIVIDE(canvas_y * W - canvas_x * H, W * H);
-
-    /* Add on the offset of the top-left corner to get the final
-     * coordinates (like in canvas_to_map_pos). */
-    *city_x -= CITY_MAP_RADIUS;
-    *city_y += CITY_MAP_RADIUS;
   } else {
-    *city_x = canvas_x / NORMAL_TILE_WIDTH;
-    *city_y = canvas_y / NORMAL_TILE_HEIGHT;
+    *city_x = DIVIDE(canvas_x, NORMAL_TILE_WIDTH);
+    *city_y = DIVIDE(canvas_y, NORMAL_TILE_HEIGHT);
   }
+
+  /* Add on the offset of the top-left corner to get the final
+   * coordinates (like in canvas_to_map_pos). */
+  *city_x += CITY_MAP_RADIUS;
+  *city_y += CITY_MAP_RADIUS;
+
   freelog(LOG_DEBUG, "canvas_to_city_pos(pos=(%d,%d))=(%d,%d)",
          orig_canvas_x, orig_canvas_y, *city_x, *city_y);
 
Index: client/citydlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.h,v
retrieving revision 1.20
diff -u -r1.20 citydlg_common.h
--- client/citydlg_common.h     4 Apr 2004 14:49:10 -0000       1.20
+++ client/citydlg_common.h     13 Jun 2004 07:12:54 -0000
@@ -36,6 +36,7 @@
 
 int get_citydlg_canvas_width(void);
 int get_citydlg_canvas_height(void);
+void generate_citydlg_dimensions(void);
 
 bool city_to_canvas_pos(int *canvas_x, int *canvas_y,
                        int city_x, int city_y);
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.124
diff -u -r1.124 mapview_common.c
--- client/mapview_common.c     12 Jun 2004 06:38:29 -0000      1.124
+++ client/mapview_common.c     13 Jun 2004 07:12:54 -0000
@@ -122,12 +122,15 @@
 }
 
 /****************************************************************************
-  Translate from map to gui coordinate systems.
+  Translate from a cartesian system to the GUI system.  This function works
+  on vectors, meaning it can be passed a (dx,dy) pair and will return the
+  change in GUI coordinates corresponding to this vector.  It is thus more
+  general than map_to_gui_pos.
 
-  GUI coordinates are comparable to canvas coordinates but extend in all
-  directions.  gui(0,0) == map(0,0).
+  Note that a gui_to_map_vector function is not possible, since the
+  resulting map vector may differ based on the origin of the gui vector.
 ****************************************************************************/
-static void map_to_gui_pos(int *gui_x, int *gui_y, int map_x, int map_y)
+void map_to_gui_vector(int *gui_dx, int *gui_dy, int map_dx, int map_dy)
 {
   if (is_isometric) {
     /*
@@ -141,15 +144,28 @@
      * 789                4 8
      *                     7
      */
-    *gui_x = (map_x - map_y) * NORMAL_TILE_WIDTH / 2;
-    *gui_y = (map_x + map_y) * NORMAL_TILE_HEIGHT / 2;
+    *gui_dx = (map_dx - map_dy) * NORMAL_TILE_WIDTH / 2;
+    *gui_dy = (map_dx + map_dy) * NORMAL_TILE_HEIGHT / 2;
   } else {
-    *gui_x = map_x * NORMAL_TILE_HEIGHT;
-    *gui_y = map_y * NORMAL_TILE_WIDTH;
+    *gui_dx = map_dx * NORMAL_TILE_HEIGHT;
+    *gui_dy = map_dy * NORMAL_TILE_WIDTH;
   }
 }
 
 /****************************************************************************
+  Translate from map to gui coordinate systems.
+
+  GUI coordinates are comparable to canvas coordinates but extend in all
+  directions.  gui(0,0) == map(0,0).
+****************************************************************************/
+static void map_to_gui_pos(int *gui_x, int *gui_y, int map_x, int map_y)
+{
+  /* Since the GUI origin is the same as the map origin we can just do a
+   * vector conversion. */
+  map_to_gui_vector(gui_x, gui_y, map_x, map_y);
+}
+
+/****************************************************************************
   Translate from gui to map coordinate systems.  See map_to_gui_pos().
 
   Note that you lose some information in this conversion.  If you convert
@@ -1870,14 +1886,7 @@
 
     assert(smooth_move_unit_msec > 0);
 
-    /* See map_to_canvas_pos for an explanation. */
-    if (is_isometric) {
-      canvas_dx = (dx - dy) * NORMAL_TILE_WIDTH / 2;
-      canvas_dy = (dx + dy) * NORMAL_TILE_HEIGHT / 2;
-    } else {
-      canvas_dx = NORMAL_TILE_WIDTH * dx;
-      canvas_dy = NORMAL_TILE_HEIGHT * dy;
-    }
+    map_to_gui_vector(&canvas_dx, &canvas_dy, dx, dy);
 
     map_to_canvas_pos(&start_x, &start_y, map_x, map_y);
     if (is_isometric) {
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.66
diff -u -r1.66 mapview_common.h
--- client/mapview_common.h     10 Jun 2004 01:04:52 -0000      1.66
+++ client/mapview_common.h     13 Jun 2004 07:12:54 -0000
@@ -226,6 +226,7 @@
 void refresh_tile_mapcanvas(int x, int y, bool write_to_screen);
 enum color_std get_grid_color(int x1, int y1, int x2, int y2);
 
+void map_to_gui_vector(int *gui_dx, int *gui_dy, int map_dx, int map_dy);
 bool map_to_canvas_pos(int *canvas_x, int *canvas_y, int map_x, int map_y);
 bool canvas_to_map_pos(int *map_x, int *map_y, int canvas_x, int canvas_y);
 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.380
diff -u -r1.380 packhand.c
--- client/packhand.c   12 Jun 2004 17:42:27 -0000      1.380
+++ client/packhand.c   13 Jun 2004 07:12:55 -0000
@@ -1318,6 +1318,8 @@
   map_allocate();
   init_client_goto();
 
+  generate_citydlg_dimensions();
+
   set_overview_dimensions(map.xsize, map.ysize);
 }
 
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.174
diff -u -r1.174 tilespec.c
--- client/tilespec.c   6 Jun 2004 06:09:46 -0000       1.174
+++ client/tilespec.c   13 Jun 2004 07:12:55 -0000
@@ -419,6 +419,7 @@
        we don't want/need to redraw. */
     return;
   }
+  generate_citydlg_dimensions();
   tileset_changed();
   center_tile_mapcanvas(center_x, center_y);
 }
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.148
diff -u -r1.148 city.h
--- common/city.h       13 Jun 2004 03:57:05 -0000      1.148
+++ common/city.h       13 Jun 2004 07:12:56 -0000
@@ -60,7 +60,7 @@
 
 
 /* Changing this requires updating CITY_TILES and network capabilities. */
-#define CITY_MAP_RADIUS 2
+#define CITY_MAP_RADIUS 3
 
 /* Diameter of the workable city area.  Some places harcdode this number. */
 #define CITY_MAP_SIZE (CITY_MAP_RADIUS * 2 + 1) 

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