Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2005:
[Freeciv-Dev] (PR#12329) gui_rect_iterate for the citydlg
Home

[Freeciv-Dev] (PR#12329) gui_rect_iterate for the citydlg

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12329) gui_rect_iterate for the citydlg
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 22 Feb 2005 13:51:26 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12329 >

To allow more complicated drawing to be done with corner and edge 
sprites, it's necessary for the city dialog drawing to be able to 
iterate over corners and edges.  Currently it cannot, which is the main 
holdup preventing doing dspeyer-style terrain graphics, grid sprites, 
and a much simplified civ3gfx terrain drawing system.

This patch changes the citydlg to use gui_rect_iterate, and changes 
gui_rect_iterate so that it is no longer tied to the mapview.

At first glance I had thought this was a hack.  However if you consider 
that the mapview and the citydlg are both just "views" over the map 
itself (with different origins and slightly different parameters) this 
makes perfect sense.

This patch is necessary for further edge/corner work, so it should go in 
pretty soon.  However it's not perfect as it highlights some other 
problems with the system.  (One example is that fog is now drawn in the 
citydlg, and in non-iso-view the grid is drawn on top of the fog. 
Probably the grid should just be drawn later, at the same time it's 
drawn in iso-view.)

This also makes possible some interesting new work for the citydlg.  We 
could draw all non-citydlg tiles, but fog them (maybe at 80% darkness). 
  We could disable fog in the citydlg.  We should definitely move the 
"special cases" of citydlg overlay graphics into tilespec.c as a new 
view layer.  All of these are quite easy compared to this patch.

-jason

Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.61
diff -u -r1.61 citydlg_common.c
--- client/citydlg_common.c     17 Feb 2005 22:11:37 -0000      1.61
+++ client/citydlg_common.c     22 Feb 2005 21:43:43 -0000
@@ -140,25 +140,29 @@
 
 /* Iterate over all known tiles in the city.  This iteration follows the
  * painter's algorithm and can be used for drawing. */
-#define citydlg_known_iterate(pcity, city_x, city_y,                       \
-                             ptile, canvas_x, canvas_y)                    \
-{                                                                           \
-  int _itr;                                                                \
-                                                                            \
-  /* We must go in order to preserve the painter's algorithm. */           \
-  for (_itr = 0; _itr < CITY_MAP_SIZE * CITY_MAP_SIZE; _itr++) {            \
-    int city_x = _itr / CITY_MAP_SIZE, city_y = _itr % CITY_MAP_SIZE;      \
-    int canvas_x, canvas_y;                                                \
-    struct tile *ptile;                                                        
    \
-                                                                            \
-    if (is_valid_city_coords(city_x, city_y)                               \
-       && (ptile = city_map_to_map(pcity, city_x, city_y))                 \
-       && tile_get_known(ptile)                                            \
-       && city_to_canvas_pos(&canvas_x, &canvas_y, city_x, city_y)) {      \
+#define citydlg_iterate(pcity, ptile, pedge, pcorner, canvas_x, canvas_y)   \
+  {                                                                        \
+    int _my_gui_x0, _my_gui_y0;                                                
    \
+  struct city *_pcity = (pcity);                                           \
+  const int _my_width = get_citydlg_canvas_width();                        \
+  const int _my_height = get_citydlg_canvas_height();                      \
+                                                                           \
+  map_to_gui_vector(&_my_gui_x0, &_my_gui_y0,                              \
+                   _pcity->tile->x, _pcity->tile->y);                      \
+  _my_gui_x0 -= (_my_width - NORMAL_TILE_WIDTH) / 2;                       \
+  _my_gui_y0 -= (_my_height - NORMAL_TILE_HEIGHT) / 2;                     \
+  freelog(LOG_DEBUG, "citydlg: %d,%d + %dx%d",                             \
+         _my_gui_x0, _my_gui_y0, _my_width, _my_height);                   \
+                                                                           \
+  gui_rect_iterate(_my_gui_x0, _my_gui_y0, _my_width, _my_height,          \
+                  ptile, pedge, pcorner, _gui_x, _gui_y) {                 \
+    const int canvas_x = _gui_x - _my_gui_x0;                              \
+    const int canvas_y = _gui_y - _my_gui_y0;                              \
+    {
 
-#define citydlg_known_iterate_end                                           \
+#define citydlg_iterate_end                                                \
     }                                                                       \
-  }                                                                         \
+  } gui_rect_iterate_end;                                                  \
 }
 
 /****************************************************************************
@@ -174,32 +178,36 @@
                       get_citydlg_canvas_height());
 
   mapview_layer_iterate(layer) {
-    citydlg_known_iterate(pcity, city_x, city_y,
-                         ptile, canvas_x, canvas_y) {
-      put_one_tile(pcanvas, layer, ptile, canvas_x, canvas_y, pcity);
-    } citydlg_known_iterate_end;
+    citydlg_iterate(pcity, ptile, pedge, pcorner, canvas_x, canvas_y) {
+      struct unit *punit = ptile ? get_drawable_unit(ptile, pcity) : NULL;
+      struct city *pcity_draw = ptile ? ptile->city : NULL;
+
+      put_one_element(pcanvas, layer, ptile, pedge, pcorner,
+                     punit, pcity_draw, canvas_x, canvas_y, pcity);
+    } citydlg_iterate_end;
   } mapview_layer_iterate_end;
 
   /* We have to put the output afterwards or it will be covered
-   * in iso-view. */
-  citydlg_known_iterate(pcity, city_x, city_y,
-                       ptile, canvas_x, canvas_y) {
-    if (pcity->city_map[city_x][city_y] == C_TILE_WORKER) {
-      put_city_tile_output(pcity, city_x, city_y,
-                          pcanvas, canvas_x, canvas_y);
-    }
-  } citydlg_known_iterate_end;
-
-  /* This sometimes will draw one of the lines on top of a city or
+   * in iso-view.
+   *
+   * This sometimes will draw one of the lines on top of a city or
    * unit pixmap (in iso-view). This should maybe be moved to
    * put_one_tile to fix this, but maybe it wouldn't be a good idea because
    * the lines would get obscured. */
-  citydlg_known_iterate(pcity, city_x, city_y,
-                       ptile, canvas_x, canvas_y) {
-    if (pcity->city_map[city_x][city_y] == C_TILE_UNAVAILABLE) {
-      put_red_frame_tile(pcanvas, canvas_x, canvas_y);
+  citydlg_iterate(pcity, ptile, pedge, pcorner, canvas_x, canvas_y) {
+    int city_x, city_y;
+
+    if (ptile && map_to_city_map(&city_x, &city_y, pcity, ptile)
+       && tile_get_known(ptile) != TILE_UNKNOWN) {
+      if (pcity->city_map[city_x][city_y] == C_TILE_WORKER) {
+       put_city_tile_output(pcity, city_x, city_y,
+                            pcanvas, canvas_x, canvas_y);
+      }
+      if (pcity->city_map[city_x][city_y] == C_TILE_UNAVAILABLE) {
+       put_red_frame_tile(pcanvas, canvas_x, canvas_y);
+      }
     }
-  } citydlg_known_iterate_end;
+  } citydlg_iterate_end;
 }
 
 /**************************************************************************
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.193
diff -u -r1.193 mapview_common.c
--- client/mapview_common.c     19 Feb 2005 17:15:13 -0000      1.193
+++ client/mapview_common.c     22 Feb 2005 21:43:43 -0000
@@ -939,13 +939,13 @@
   Draw one layer of a tile, edge, corner, unit, and/or city onto the
   canvas at the given position.
 **************************************************************************/
-static void put_one_element(struct canvas *pcanvas, enum mapview_layer layer,
-                           struct tile *ptile,
-                           const struct tile_edge *pedge,
-                           const struct tile_corner *pcorner,
-                           const struct unit *punit, struct city *pcity,
-                           int canvas_x, int canvas_y,
-                           const struct city *citymode)
+void put_one_element(struct canvas *pcanvas, enum mapview_layer layer,
+                    struct tile *ptile,
+                    const struct tile_edge *pedge,
+                    const struct tile_corner *pcorner,
+                    const struct unit *punit, struct city *pcity,
+                    int canvas_x, int canvas_y,
+                    const struct city *citymode)
 {
   struct drawn_sprite tile_sprs[80];
   int count = fill_sprite_array(tile_sprs, layer, ptile, pedge, pcorner,
@@ -1562,9 +1562,9 @@
 /**************************************************************************
   Draw some or all of a tile onto the canvas.
 **************************************************************************/
-void put_one_tile(struct canvas *pcanvas, enum mapview_layer layer,
-                 struct tile *ptile, int canvas_x, int canvas_y,
-                 const struct city *citymode)
+static void put_one_tile(struct canvas *pcanvas, enum mapview_layer layer,
+                        struct tile *ptile, int canvas_x, int canvas_y,
+                        const struct city *citymode)
 {
   if (tile_get_known(ptile) != TILE_UNKNOWN) {
     put_one_element(pcanvas, layer, ptile, NULL, NULL,
@@ -1632,7 +1632,9 @@
   mapview_layer_iterate(layer) {
     gui_rect_iterate(gui_x0, gui_y0, width,
                     height + (is_isometric ? (NORMAL_TILE_HEIGHT / 2) : 0),
-                    ptile, pedge, pcorner, cx, cy) {
+                    ptile, pedge, pcorner, gui_x, gui_y) {
+      const int cx = gui_x - mapview.gui_x0, cy = gui_y - mapview.gui_y0;
+
       if (ptile) {
        put_one_tile(mapview.store, layer, ptile, cx, cy, NULL);
       } else if (pedge) {
@@ -1655,7 +1657,7 @@
    * from adjacent tiles (if they're close enough). */
   gui_rect_iterate(gui_x0 - GOTO_WIDTH, gui_y0 - GOTO_WIDTH,
                   width + 2 * GOTO_WIDTH, height + 2 * GOTO_WIDTH,
-                  ptile, pedge, pcorner, cx, cy) {
+                  ptile, pedge, pcorner, gui_x, gui_y) {
     if (!ptile) {
       continue;
     }
@@ -1668,7 +1670,10 @@
 
   /* Draw citymap overlays on top. */
   gui_rect_iterate(gui_x0, gui_y0, width, height,
-                  ptile, pedge, pcorner, canvas_x2, canvas_y2) {
+                  ptile, pedge, pcorner, gui_x, gui_y) {
+    const int canvas_x2 = gui_x - mapview.gui_x0;
+    const int canvas_y2 = gui_y - mapview.gui_y0;
+
     if (ptile && tile_get_known(ptile) != TILE_UNKNOWN) {
       struct unit *punit;
       struct city *pcity;
@@ -1775,7 +1780,10 @@
   gui_rect_iterate(mapview.gui_x0 + canvas_x - dx / 2,
                   mapview.gui_y0 + canvas_y - dy,
                   width + dx, height + dy - NORMAL_TILE_HEIGHT,
-                  ptile, pedge, pcorner, canvas_x, canvas_y) {
+                  ptile, pedge, pcorner, gui_x, gui_y) {
+    const int canvas_x = gui_x - mapview.gui_x0;
+    const int canvas_y = gui_y - mapview.gui_y0;
+
     if (ptile && ptile->city) {
       int width = 0, height = 0;
       struct city *pcity = ptile->city;
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.95
diff -u -r1.95 mapview_common.h
--- client/mapview_common.h     19 Feb 2005 17:15:13 -0000      1.95
+++ client/mapview_common.h     22 Feb 2005 21:43:43 -0000
@@ -84,7 +84,7 @@
  * or the other text in PR#12085.
  */
 #define gui_rect_iterate(GRI_gui_x0, GRI_gui_y0, width, height,                
    \
-                        ptile, pedge, pcorner, canvas_x, canvas_y)         \
+                        ptile, pedge, pcorner, gui_x, gui_y)               \
 {                                                                          \
   int _gui_x0 = (GRI_gui_x0), _gui_y0 = (GRI_gui_y0);                      \
   int _width = (width), _height = (height);                                \
@@ -107,6 +107,8 @@
     const int GRI_y1 = DIVIDE(_gui_y0 + _height + _H - 1, _H) + _ratio;        
    \
     const int _count = (GRI_x1 - GRI_x0) * (GRI_y1 - GRI_y0);              \
     int GRI_itr, GRI_x_itr, GRI_y_itr, GRI_sum, GRI_diff;                  \
+    freelog(LOG_DEBUG, "Iterating over %d-%d x %d-%d rectangle.",          \
+           (GRI_x1), (GRI_x0), GRI_y1,  (GRI_y0));                         \
                                                                            \
     for (GRI_itr = 0; GRI_itr < _count; GRI_itr++) {                       \
       struct tile *ptile = NULL;                                           \
@@ -114,7 +116,7 @@
       struct tile_corner *pcorner = NULL;                                  \
       struct tile_edge GRI_edge;                                           \
       struct tile_corner GRI_corner;                                       \
-      int canvas_x, canvas_y;                                              \
+      int gui_x, gui_y;                                                        
    \
                                                                            \
       GRI_x_itr = GRI_x0 + (GRI_itr % (GRI_x1 - GRI_x0));                  \
       GRI_y_itr = GRI_y0 + (GRI_itr / (GRI_x1 - GRI_x0));                  \
@@ -193,10 +195,8 @@
          }                                                                 \
        }                                                                   \
       }                                                                        
    \
-      canvas_x                                                             \
-       = GRI_x_itr * _W - NORMAL_TILE_WIDTH / 2 - mapview.gui_x0;          \
-      canvas_y                                                             \
-       = GRI_y_itr * _H - NORMAL_TILE_HEIGHT / 2 - mapview.gui_y0;
+      gui_x = GRI_x_itr * _W - NORMAL_TILE_WIDTH / 2;                      \
+      gui_y = GRI_y_itr * _H - NORMAL_TILE_HEIGHT / 2;
 
 #define gui_rect_iterate_end                                               \
     }                                                                      \
@@ -251,9 +251,13 @@
 
 void put_nuke_mushroom_pixmaps(struct tile *ptile);
 
-void put_one_tile(struct canvas *pcanvas, enum mapview_layer layer,
-                 struct tile *ptile, int canvas_x, int canvas_y,
-                 const struct city *citymode);
+void put_one_element(struct canvas *pcanvas, enum mapview_layer layer,
+                    struct tile *ptile,
+                    const struct tile_edge *pedge,
+                    const struct tile_corner *pcorner,
+                    const struct unit *punit, struct city *pcity,
+                    int canvas_x, int canvas_y,
+                    const struct city *citymode);
 
 void update_map_canvas(int canvas_x, int canvas_y, int width, int height);
 void update_map_canvas_visible(void);
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.237
diff -u -r1.237 tilespec.c
--- client/tilespec.c   17 Feb 2005 22:11:37 -0000      1.237
+++ client/tilespec.c   22 Feb 2005 21:43:44 -0000
@@ -2772,6 +2772,33 @@
   bool do_draw_unit = (punit && (draw_units || !ptile
                                 || (draw_focus_unit && pfocus == punit)));
 
+  if (citymode) {
+    int count = 0, i, cx, cy;
+    const struct tile *const *tiles = NULL;
+    bool valid = FALSE;
+
+    if (ptile) {
+      tiles = &ptile;
+      count = 1;
+    } else if (pcorner) {
+      tiles = pcorner->tile;
+      count = NUM_CORNER_TILES;
+    } else if (pedge) {
+      tiles = pedge->tile;
+      count = NUM_EDGE_TILES;
+    }
+
+    for (i = 0; i < count; i++) {
+      if (tiles[i] && map_to_city_map(&cx, &cy, citymode, tiles[i])) {
+       valid = TRUE;
+       break;
+      }
+    }
+    if (!valid) {
+      return 0;
+    }
+  }
+
   if (ptile && tile_get_known(ptile) != TILE_UNKNOWN) {
     build_tile_data(ptile,
                    &ttype, &tspecial, ttype_near, tspecial_near);
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.104
diff -u -r1.104 tilespec.h
--- client/tilespec.h   17 Feb 2005 22:11:37 -0000      1.104
+++ client/tilespec.h   22 Feb 2005 21:43:44 -0000
@@ -32,13 +32,15 @@
   enum {
     EDGE_NS, EDGE_EW
   } type;
-  struct tile *tile[2];
+#define NUM_EDGE_TILES 2
+  const struct tile *tile[NUM_EDGE_TILES];
 };
 
 /* A corner is the endpoint of several edges.  At each corner 4 tiles will
  * meet (3 in hex view).  Tiles are in clockwise order NESW. */
 struct tile_corner {
-  struct tile *tile[4];
+#define NUM_CORNER_TILES 4
+  const struct tile *tile[NUM_CORNER_TILES];
 };
 
 struct drawn_sprite {

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12329) gui_rect_iterate for the citydlg, Jason Short <=