[Freeciv-Dev] Re: (PR#12085) RFC: better iteration in gui_rect_iterate
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12085 >
Attached is a patch that uses the edge structures to place grid sprites.
This is just a demo at this point, intended to show that the code
actually does work (although it is surely not without bugs).
Also attached:
- Grid PNG graphics for isotrident. I based these on the generated mask
and believe them to be perfect.
- A screenshot showing the code in action. To show that it's working I
changed the grid graphics to have 50% alpha, so the grid is a lot less
intrusive than normal.
http://bugs.freeciv.org/Ticket/Attachment/89385/56626/grid.png
-jason
? data/isotrident/grid-ew.png
? data/isotrident/grid-ns.png
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.172
diff -u -r1.172 mapview_common.c
--- client/mapview_common.c 2 Feb 2005 02:43:29 -0000 1.172
+++ client/mapview_common.c 4 Feb 2005 02:15:27 -0000
@@ -522,7 +522,7 @@
} while (mytime < timing_sec);
mytime = read_timer_seconds(anim_timer);
- freelog(LOG_DEBUG, "Got %d frames in %f seconds: %f FPS.",
+ freelog(LOG_NORMAL, "Got %d frames in %f seconds: %f FPS.",
frames, mytime, (double)frames / mytime);
} else {
base_set_mapview_origin(gui_x0, gui_y0);
@@ -872,6 +872,23 @@
}
}
+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, bool citymode)
+{
+ struct drawn_sprite tile_sprs[80];
+ int count = fill_sprite_array(tile_sprs, layer, ptile, pedge, pcorner,
+ punit, pcity, citymode);
+ bool fog = (ptile && tile_get_known(ptile) == TILE_KNOWN_FOGGED
+ && draw_fog_of_war && fogstyle == 0);
+
+ /*** Draw terrain and specials ***/
+ put_drawn_sprites(pcanvas, canvas_x, canvas_y, count, tile_sprs, fog);
+}
+
/**************************************************************************
Draw the given unit onto the canvas store at the given location. The
area of drawing is UNIT_TILE_HEIGHT x UNIT_TILE_WIDTH.
@@ -879,15 +896,10 @@
void put_unit(const struct unit *punit,
struct canvas *pcanvas, int canvas_x, int canvas_y)
{
- struct drawn_sprite drawn_sprites[40];
-
canvas_y += (UNIT_TILE_HEIGHT - NORMAL_TILE_HEIGHT);
mapview_layer_iterate(layer) {
- int count = fill_sprite_array(drawn_sprites, layer,
- NULL, punit, NULL, FALSE);
-
- put_drawn_sprites(pcanvas, canvas_x, canvas_y,
- count, drawn_sprites, FALSE);
+ put_one_element(pcanvas, layer, NULL, NULL, NULL,
+ punit, NULL, canvas_x, canvas_y, FALSE);
} mapview_layer_iterate_end;
}
@@ -898,15 +910,11 @@
void put_city(struct city *pcity,
struct canvas *pcanvas, int canvas_x, int canvas_y)
{
- struct drawn_sprite drawn_sprites[40];
-
canvas_y += (UNIT_TILE_HEIGHT - NORMAL_TILE_HEIGHT);
mapview_layer_iterate(layer) {
- int count = fill_sprite_array(drawn_sprites, layer,
- NULL, NULL, pcity, FALSE);
-
- put_drawn_sprites(pcanvas, canvas_x, canvas_y,
- count, drawn_sprites, FALSE);
+ put_one_element(pcanvas, layer,
+ NULL, NULL, NULL, NULL, pcity,
+ canvas_x, canvas_y, FALSE);
} mapview_layer_iterate_end;
}
@@ -918,16 +926,11 @@
void put_terrain(struct tile *ptile,
struct canvas *pcanvas, int canvas_x, int canvas_y)
{
- struct drawn_sprite drawn_sprites[40];
-
/* Use full tile height, even for terrains. */
canvas_y += (UNIT_TILE_HEIGHT - NORMAL_TILE_HEIGHT);
mapview_layer_iterate(layer) {
- int count = fill_sprite_array(drawn_sprites, layer,
- ptile, NULL, NULL, FALSE);
-
- put_drawn_sprites(pcanvas, canvas_x, canvas_y,
- count, drawn_sprites, FALSE);
+ put_one_element(pcanvas, layer, ptile, NULL, NULL, NULL, NULL,
+ canvas_x, canvas_y, FALSE);
} mapview_layer_iterate_end;
}
@@ -1439,15 +1442,11 @@
struct tile *ptile,
int canvas_x, int canvas_y, bool citymode)
{
- struct drawn_sprite tile_sprs[80];
- int count = fill_sprite_array(tile_sprs, layer, ptile,
- get_drawable_unit(ptile, citymode),
- ptile->city, citymode);
- bool fog = (tile_get_known(ptile) == TILE_KNOWN_FOGGED && draw_fog_of_war
- && fogstyle == 0);
-
- /*** Draw terrain and specials ***/
- put_drawn_sprites(pcanvas, canvas_x, canvas_y, count, tile_sprs, fog);
+ if (tile_get_known(ptile) != TILE_UNKNOWN) {
+ put_one_element(pcanvas, layer, ptile, NULL, NULL,
+ get_drawable_unit(ptile, citymode),
+ ptile->city, canvas_x, canvas_y, citymode);
+ }
}
/**************************************************************************
@@ -1507,14 +1506,21 @@
canvas_x, canvas_y, width, height);
mapview_layer_iterate(layer) {
+ // freelog(LOG_NORMAL, "Update map canvas.");
gui_rect_iterate(gui_x0, gui_y0, width,
height + (is_isometric ? (NORMAL_TILE_HEIGHT / 2) : 0),
- ptile) {
- int cx, cy;
-
- if (tile_get_known(ptile) != TILE_UNKNOWN
- && tile_to_canvas_pos(&cx, &cy, ptile)) {
+ ptile, pedge, pcorner, cx, cy) {
+ if (ptile) {
+ // freelog(LOG_NORMAL, " Putting %d,%d at %d,%d.",
TILE_XY(ptile), cx, cy);
put_one_tile(mapview_canvas.store, layer, ptile, cx, cy, FALSE);
+ } else if (pedge) {
+ put_one_element(mapview_canvas.store, layer, NULL, pedge, NULL,
+ NULL, NULL, cx, cy, FALSE);
+ } else if (pcorner) {
+ put_one_element(mapview_canvas.store, layer, NULL, NULL, pcorner,
+ NULL, NULL, cx, cy, FALSE);
+ } else {
+ /* This can happen, for instance for unreal tiles. */
}
} gui_rect_iterate_end;
} mapview_layer_iterate_end;
@@ -1527,7 +1533,10 @@
* 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) {
+ ptile, pedge, pcorner, cx, cy) {
+ if (!ptile) {
+ continue;
+ }
adjc_dir_iterate(ptile, adjc_tile, dir) {
if (is_drawn_line(ptile, dir)) {
draw_segment(ptile, dir);
@@ -1536,17 +1545,17 @@
} gui_rect_iterate_end;
/* Draw citymap overlays on top. */
- gui_rect_iterate(gui_x0, gui_y0, width, height, ptile) {
- if (tile_get_known(ptile) != TILE_UNKNOWN) {
+ gui_rect_iterate(gui_x0, gui_y0, width, height,
+ ptile, pedge, pcorner, canvas_x2, canvas_y2) {
+ if (ptile && tile_get_known(ptile) != TILE_UNKNOWN) {
struct unit *punit;
struct city *pcity;
- int city_x, city_y, canvas_x2, canvas_y2;
+ int city_x, city_y;
pcity = find_city_or_settler_near_tile(ptile, &punit);
if (pcity
&& city_colors[pcity->client.color] != COLOR_STD_LAST
- && map_to_city_map(&city_x, &city_y, pcity, ptile)
- && tile_to_canvas_pos(&canvas_x2, &canvas_y2, ptile)) {
+ && map_to_city_map(&city_x, &city_y, pcity, ptile)) {
enum city_tile_type worker = get_worker_city(pcity, city_x, city_y);
put_city_worker(mapview_canvas.store,
@@ -1557,8 +1566,7 @@
mapview_canvas.store, canvas_x2, canvas_y2);
}
} else if (punit
- && city_colors[punit->client.color] != COLOR_STD_LAST
- && tile_to_canvas_pos(&canvas_x2, &canvas_y2, ptile)) {
+ && city_colors[punit->client.color] != COLOR_STD_LAST) {
/* Draw citymap overlay for settlers. */
put_city_worker(mapview_canvas.store,
city_colors[punit->client.color], C_TILE_EMPTY,
@@ -1628,6 +1636,8 @@
int width, int height)
{
const int dx = max_desc_width - NORMAL_TILE_WIDTH, dy = max_desc_height;
+ const int x0 = mapview_canvas.gui_x0 + canvas_x - dx / 2;
+ const int y0 = mapview_canvas.gui_y0 + canvas_y - dy;
if (!draw_city_names && !draw_city_productions) {
return;
@@ -1653,17 +1663,13 @@
* We must draw H2 extra pixels above and (W2 - W1) / 2 extra pixels
* to each side of the mapview.
*/
- gui_rect_iterate(mapview_canvas.gui_x0 + canvas_x - dx / 2,
- mapview_canvas.gui_y0 + canvas_y - dy,
+ gui_rect_iterate(x0, y0,
width + dx, height + dy - NORMAL_TILE_HEIGHT,
- ptile) {
- int canvas_x, canvas_y;
- struct city *pcity = ptile->city;
-
- if (pcity) {
+ ptile, pedge, pcorner, canvas_x, canvas_y) {
+ if (ptile && ptile->city) {
int width = 0, height = 0;
+ struct city *pcity = ptile->city;
- (void) tile_to_canvas_pos(&canvas_x, &canvas_y, ptile);
show_city_desc(mapview_canvas.store, canvas_x, canvas_y,
pcity, &width, &height);
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.85
diff -u -r1.85 mapview_common.h
--- client/mapview_common.h 25 Dec 2004 20:38:14 -0000 1.85
+++ client/mapview_common.h 4 Feb 2005 02:15:27 -0000
@@ -85,10 +85,11 @@
* iso-view iteration is at
* http://rt.freeciv.org/Ticket/Attachment/51374/37363/isogrid.png.
*/
-#define gui_rect_iterate(gui_x0, gui_y0, width, height, ptile) \
+#define gui_rect_iterate(GRI_gui_x0, GRI_gui_y0, width, height,
\
+ ptile, pedge, pcorner, canvas_x, canvas_y) \
{ \
- int _gui_x0 = (gui_x0), _gui_y0 = (gui_y0); \
- int _width = (width), _height = (height); \
+ int _gui_x0 = (GRI_gui_x0), _gui_y0 = (GRI_gui_y0); \
+ int _width = (width), _height = (height); \
\
if (_width < 0) { \
_gui_x0 += _width; \
@@ -99,38 +100,105 @@
_height = -_height;
\
} \
if (_width > 0 && _height > 0) { \
- int W = (is_isometric ? (NORMAL_TILE_WIDTH / 2) : NORMAL_TILE_WIDTH); \
- int H = (is_isometric ? (NORMAL_TILE_HEIGHT / 2) : NORMAL_TILE_HEIGHT); \
- int GRI_x0 = DIVIDE(_gui_x0, W), GRI_y0 = DIVIDE(_gui_y0, H); \
- int GRI_x1 = DIVIDE(_gui_x0 + _width + W - 1, W); \
- int GRI_y1 = DIVIDE(_gui_y0 + _height + H - 1, H); \
- int GRI_itr, GRI_x_itr, GRI_y_itr, _map_x, _map_y; \
- int count; \
- struct tile *ptile;
\
+ const int _ratio = (is_isometric ? 2 : 1); \
+ const int _W = NORMAL_TILE_WIDTH / (_ratio * 2); \
+ const int _H = NORMAL_TILE_HEIGHT / (_ratio * 2); \
+ const int GRI_x0 = DIVIDE(_gui_x0, _W) - 1;
\
+ const int GRI_y0 = DIVIDE(_gui_y0, _H) - 1;
\
+ const int GRI_x1 = DIVIDE(_gui_x0 + _width + _W - 1, _W) + _ratio; \
+ 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; \
\
- if (is_isometric) {
\
- /* Tiles to the left/above overlap with us. */ \
- GRI_x0--;
\
- GRI_y0--;
\
- } \
- count = (GRI_x1 - GRI_x0) * (GRI_y1 - GRI_y0); \
- for (GRI_itr = 0; GRI_itr < count; GRI_itr++) { \
+ for (GRI_itr = 0; GRI_itr < _count; GRI_itr++) { \
+ struct tile *ptile = NULL; \
+ struct tile_edge *pedge = NULL; \
+ struct tile_corner *pcorner = NULL; \
+ struct tile_edge GRI_edge; \
+ struct tile_corner GRI_corner; \
+ int canvas_x, canvas_y; \
+ \
GRI_x_itr = GRI_x0 + (GRI_itr % (GRI_x1 - GRI_x0)); \
GRI_y_itr = GRI_y0 + (GRI_itr / (GRI_x1 - GRI_x0)); \
+ GRI_sum = GRI_x_itr + GRI_y_itr; \
+ GRI_diff = GRI_y_itr - GRI_x_itr;
\
if (is_isometric) { \
- if ((GRI_x_itr + GRI_y_itr) % 2 != 0) { \
- continue; \
- } \
- _map_x = (GRI_x_itr + GRI_y_itr) / 2; \
- _map_y = (GRI_y_itr - GRI_x_itr) / 2; \
+ if ((GRI_x_itr + GRI_y_itr) % 2 != 0) { \
+ continue; \
+ } \
+ if (GRI_x_itr % 2 == 0 && GRI_y_itr % 2 == 0) { \
+ if ((GRI_x_itr + GRI_y_itr) % 4 == 0) { \
+ /* Tile */ \
+ ptile = map_pos_to_tile(GRI_sum / 4 - 1, GRI_diff / 4); \
+ } else { \
+ /* Corner */ \
+ pcorner = &GRI_corner; \
+ pcorner->tile[0] = map_pos_to_tile((GRI_sum - 2) / 4, \
+ (GRI_diff - 2) / 4); \
+ pcorner->tile[1] = map_pos_to_tile((GRI_sum + 2) / 4, \
+ (GRI_diff - 2) / 4); \
+ pcorner->tile[2] = map_pos_to_tile((GRI_sum + 2) / 4, \
+ (GRI_diff + 2) / 4); \
+ pcorner->tile[3] = map_pos_to_tile((GRI_sum - 2) / 4, \
+ (GRI_diff + 2) / 4); \
+ } \
+ } else { \
+ /* Edge. */ \
+ pedge = &GRI_edge; \
+ if (GRI_sum % 4 == 0) { \
+ pedge->type = EDGE_NS; \
+ pedge->tile[0] = map_pos_to_tile((GRI_sum - 4) / 4, /* N */ \
+ (GRI_diff - 2) / 4); \
+ pedge->tile[1] = map_pos_to_tile((GRI_sum - 4) / 4, /* S */ \
+ (GRI_diff + 2) / 4); \
+ } else { \
+ pedge->type = EDGE_EW; \
+ pedge->tile[0] = map_pos_to_tile((GRI_sum - 6) / 4, \
+ GRI_diff / 4); /* E */ \
+ pedge->tile[1] = map_pos_to_tile((GRI_sum - 2) / 4, \
+ GRI_diff / 4); /* W */ \
+ } \
+ } \
} else { \
- _map_x = GRI_x_itr; \
- _map_y = GRI_y_itr; \
- }
\
- ptile = map_pos_to_tile(_map_x, _map_y); \
- if (!ptile) { \
- continue; \
- }
+ if (GRI_sum % 2 == 0) { \
+ if (GRI_x_itr % 2 == 0) { \
+ /* Corner. */ \
+ pcorner = &GRI_corner; \
+ pcorner->tile[0] = map_pos_to_tile(GRI_x_itr / 2 - 1, \
+ GRI_y_itr / 2 - 1); /* NW */ \
+ pcorner->tile[1] = map_pos_to_tile(GRI_x_itr / 2, \
+ GRI_y_itr / 2 - 1); /* NE */ \
+ pcorner->tile[2] = map_pos_to_tile(GRI_x_itr / 2, \
+ GRI_y_itr / 2); /* SE */ \
+ pcorner->tile[3] = map_pos_to_tile(GRI_x_itr / 2 - 1, \
+ GRI_y_itr / 2); /* SW */ \
+ } else { \
+ /* Tile. */ \
+ ptile = map_pos_to_tile((GRI_x_itr - 1) / 2, \
+ (GRI_y_itr - 1) / 2); \
+ } \
+ } else { \
+ /* Edge. */ \
+ pedge = &GRI_edge; \
+ if (GRI_y_itr % 2 == 0) { \
+ pedge->type = EDGE_EW; \
+ pedge->tile[0] = map_pos_to_tile(GRI_x_itr / 2 - 1, \
+ (GRI_y_itr - 1) / 2); \
+ pedge->tile[1] = map_pos_to_tile(GRI_x_itr / 2, \
+ (GRI_y_itr - 1) / 2); \
+ } else { \
+ pedge->type = EDGE_NS; \
+ pedge->tile[0] = map_pos_to_tile((GRI_x_itr - 1) / 2, \
+ GRI_y_itr / 2 - 1); \
+ pedge->tile[1] = map_pos_to_tile((GRI_x_itr - 1) / 2, \
+ GRI_y_itr / 2); \
+ } \
+ } \
+ }
\
+ canvas_x \
+ = GRI_x_itr * _W - NORMAL_TILE_WIDTH / 2 - mapview_canvas.gui_x0; \
+ canvas_y \
+ = GRI_y_itr * _H - NORMAL_TILE_HEIGHT / 2 - mapview_canvas.gui_y0;
#define gui_rect_iterate_end \
} \
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.227
diff -u -r1.227 tilespec.c
--- client/tilespec.c 3 Feb 2005 19:28:40 -0000 1.227
+++ client/tilespec.c 4 Feb 2005 02:15:28 -0000
@@ -1457,6 +1457,9 @@
SET_SPRITE(tx.airbase, "tx.airbase");
SET_SPRITE(tx.fog, "tx.fog");
+ SET_SPRITE(tx.grid[EDGE_EW], "tx.grid_ew");
+ SET_SPRITE(tx.grid[EDGE_NS], "tx.grid_ns");
+
for (i = 0; i < num_index_cardinal; i++) {
my_snprintf(buffer, sizeof(buffer), "tx.s_river_%s",
cardinal_index_str(i));
@@ -2674,7 +2677,8 @@
is done differently.
****************************************************************************/
int fill_sprite_array(struct drawn_sprite *sprs, enum mapview_layer layer,
- struct tile *ptile,
+ struct tile *ptile, const struct tile_edge *pedge,
+ const struct tile_corner *pcorner,
const struct unit *punit, struct city *pcity,
bool citymode)
{
@@ -2791,8 +2795,17 @@
case LAYER_GRID1:
if (ptile && tile_get_known(ptile) != TILE_UNKNOWN && is_isometric) {
+#if 0
/* Add grid. In classic view this is done later. */
ADD_GRID(ptile, citymode);
+#endif
+ }
+ if (pedge && is_isometric
+ && ((pedge->tile[0]
+ && tile_get_known(pedge->tile[0]) != TILE_UNKNOWN)
+ || (pedge->tile[1]
+ && tile_get_known(pedge->tile[1]) != TILE_UNKNOWN))) {
+ ADD_SPRITE_SIMPLE(sprites.tx.grid[pedge->type]);
}
break;
@@ -2873,10 +2886,12 @@
break;
case LAYER_GRID2:
+#if 0
if (ptile && tile_get_known(ptile) != TILE_UNKNOWN && !is_isometric) {
/* Add grid. In iso-view this is done earlier. */
ADD_GRID(ptile, citymode);
}
+#endif
break;
case LAYER_COUNT:
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.97
diff -u -r1.97 tilespec.h
--- client/tilespec.h 22 Jan 2005 19:45:39 -0000 1.97
+++ client/tilespec.h 4 Feb 2005 02:15:28 -0000
@@ -26,6 +26,21 @@
struct Sprite; /* opaque; gui-dep */
+/* An edge is the border between two tiles. This structure represents one
+ * edge. The tiles are in unspecified order for the moment. */
+struct tile_edge {
+ enum {
+ EDGE_NS, EDGE_EW, EDGE_COUNT
+ } type;
+ struct tile *tile[2];
+};
+
+/* 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];
+};
+
struct drawn_sprite {
enum {
DRAWN_SPRITE, /* Draw a sprite. */
@@ -114,7 +129,8 @@
/* Gfx support */
int fill_sprite_array(struct drawn_sprite *sprs, enum mapview_layer layer,
- struct tile *ptile,
+ struct tile *ptile, const struct tile_edge *edge,
+ const struct tile_corner *corner,
const struct unit *punit, struct city *pcity,
bool citymode);
@@ -292,6 +308,7 @@
*airbase,
*fallout,
*fog,
+ *grid[EDGE_COUNT],
*spec_river[MAX_INDEX_CARDINAL],
*darkness[MAX_INDEX_CARDINAL], /* first unused */
*river_outlet[4]; /* indexed by enum direction4 */
Index: data/isotrident/tiles.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/tiles.spec,v
retrieving revision 1.4
diff -u -r1.4 tiles.spec
--- data/isotrident/tiles.spec 20 Nov 2004 17:45:52 -0000 1.4
+++ data/isotrident/tiles.spec 4 Feb 2005 02:15:30 -0000
@@ -142,3 +142,10 @@
2, 2, "explode.nuke_22"
}
+
+[extra]
+sprites =
+ { "tag", "file"
+ "tx.grid_ns", "data/isotrident/grid-ns"
+ "tx.grid_ew", "data/isotrident/grid-ew"
+ }
- [Freeciv-Dev] Re: (PR#12085) RFC: better iteration in gui_rect_iterate,
Jason Short <=
|
|