1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifndef FC__MAPVIEW_COMMON_H
15 #define FC__MAPVIEW_COMMON_H
19 #endif /* __cplusplus */
22 #include "support.h" /* bool type */
26 #include "featured_text.h" /* enum text_link_type type */
34 struct canvas_store
; /* opaque type, real type is gui-dep */
38 int width
, height
; /* Size in pixels. */
39 int tile_width
, tile_height
; /* Size in tiles. Rounded up. */
40 int store_width
, store_height
;
41 bool can_do_cached_drawing
; /* TRUE if cached drawing is possible. */
42 struct canvas
*store
, *tmp_store
;
45 void mapdeco_init(void);
46 void mapdeco_free(void);
47 void mapdeco_set_highlight(const struct tile
*ptile
, bool highlight
);
48 bool mapdeco_is_highlight_set(const struct tile
*ptile
);
49 void mapdeco_clear_highlights(void);
50 void mapdeco_set_crosshair(const struct tile
*ptile
, bool crosshair
);
51 bool mapdeco_is_crosshair_set(const struct tile
*ptile
);
52 void mapdeco_clear_crosshairs(void);
53 void mapdeco_set_gotoroute(const struct unit
*punit
);
54 void mapdeco_add_gotoline(const struct tile
*ptile
,
56 void mapdeco_remove_gotoline(const struct tile
*ptile
,
58 bool mapdeco_is_gotoline_set(const struct tile
*ptile
,
60 void mapdeco_clear_gotoroutes(void);
63 extern struct view mapview
;
65 /* HACK: Callers can set this to FALSE to disable sliding. It should be
66 * reenabled afterwards. */
67 extern bool can_slide
;
69 #define BORDER_WIDTH 2
73 * Iterate over all map tiles that intersect with the given GUI rectangle.
74 * The order of iteration is guaranteed to satisfy the painter's algorithm.
75 * The iteration covers not only tiles but tile edges and corners.
77 * GRI_x0, GRI_y0: gives the GUI origin of the rectangle.
79 * GRI_width, GRI_height: gives the GUI width and height of the rectangle.
80 * These values may be negative.
82 * _t, _e, _c: the tile, edge, or corner that is being iterated, declared
83 * inside the macro. Usually, only one of them will be non-NULL at a time.
84 * These values may be passed directly to fill_sprite_array().
86 * _x, _y: the canvas position of the current element, declared inside
87 * the macro. Each element is assumed to be tileset_tile_width(tileset) *
88 * tileset_tile_height(tileset) in size. If an element is larger, the
89 * caller needs to use a larger rectangle of iteration.
91 * The grid of iteration is rather complicated. For a picture of it see
92 * http://bugs.freeciv.org/Ticket/Attachment/89565/56824/newgrid.png
93 * or the other text in PR#12085.
95 #define gui_rect_iterate(GRI_x0, GRI_y0, GRI_width, GRI_height, \
98 int _x_##_0 = (GRI_x0), _y_##_0 = (GRI_y0); \
99 int _x_##_w = (GRI_width), _y_##_h = (GRI_height); \
102 _x_##_0 += _x_##_w; \
103 _x_##_w = -_x_##_w; \
106 _y_##_0 += _y_##_h; \
107 _y_##_h = -_y_##_h; \
109 if (_x_##_w > 0 && _y_##_h > 0) { \
110 struct tile_edge _t##_e; \
111 struct tile_corner _t##_c; \
112 int _t##_xi, _t##_yi, _t##_si, _t##_di; \
113 const int _t##_r1 = (tileset_is_isometric(tileset) ? 2 : 1); \
114 const int _t##_r2 = _t##_r1 * 2; /* double the ratio */ \
115 const int _t##_w = tileset_tile_width(tileset); \
116 const int _t##_h = tileset_tile_height(tileset); \
117 /* Don't divide by _r2 yet, to avoid integer rounding errors. */ \
118 const int _t##_x0 = DIVIDE(_x_##_0 * _t##_r2, _t##_w) - _t##_r1 / 2;\
119 const int _t##_y0 = DIVIDE(_y_##_0 * _t##_r2, _t##_h) - _t##_r1 / 2;\
120 const int _t##_x1 = DIVIDE((_x_##_0 + _x_##_w) * _t##_r2 + _t##_w - 1,\
122 const int _t##_y1 = DIVIDE((_y_##_0 + _y_##_h) * _t##_r2 + _t##_h - 1,\
124 const int _t##_count = (_t##_x1 - _t##_x0) * (_t##_y1 - _t##_y0); \
125 int _t##_index = 0; \
127 log_debug("Iterating over %d-%d x %d-%d rectangle.", \
128 _t##_x1, _t##_x0, _t##_y1, _t##_y0); \
129 for (; _t##_index < _t##_count; _t##_index++) { \
130 struct tile *_t = NULL; \
131 struct tile_edge *_e = NULL; \
132 struct tile_corner *_c = NULL; \
134 _t##_xi = _t##_x0 + (_t##_index % (_t##_x1 - _t##_x0)); \
135 _t##_yi = _t##_y0 + (_t##_index / (_t##_x1 - _t##_x0)); \
136 _t##_si = _t##_xi + _t##_yi; \
137 _t##_di = _t##_yi - _t##_xi; \
138 if (2 == _t##_r1 /*tileset_is_isometric(tileset)*/) { \
139 if ((_t##_xi + _t##_yi) % 2 != 0) { \
142 if (_t##_xi % 2 == 0 && _t##_yi % 2 == 0) { \
143 if ((_t##_xi + _t##_yi) % 4 == 0) { \
145 _t = map_pos_to_tile(_t##_si / 4 - 1, _t##_di / 4); \
149 _c->tile[0] = map_pos_to_tile((_t##_si - 6) / 4, \
150 (_t##_di - 2) / 4); \
151 _c->tile[1] = map_pos_to_tile((_t##_si - 2) / 4, \
152 (_t##_di - 2) / 4); \
153 _c->tile[2] = map_pos_to_tile((_t##_si - 2) / 4, \
154 (_t##_di + 2) / 4); \
155 _c->tile[3] = map_pos_to_tile((_t##_si - 6) / 4, \
156 (_t##_di + 2) / 4); \
157 if (tileset_hex_width(tileset) > 0) { \
159 _e->type = EDGE_UD; \
160 _e->tile[0] = _c->tile[0]; \
161 _e->tile[1] = _c->tile[2]; \
162 } else if (tileset_hex_height(tileset) > 0) { \
164 _e->type = EDGE_LR; \
165 _e->tile[0] = _c->tile[1]; \
166 _e->tile[1] = _c->tile[3]; \
172 if (_t##_si % 4 == 0) { \
173 _e->type = EDGE_NS; \
174 _e->tile[0] = map_pos_to_tile((_t##_si - 4) / 4, \
175 (_t##_di - 2) / 4); /*N*/ \
176 _e->tile[1] = map_pos_to_tile((_t##_si - 4) / 4, \
177 (_t##_di + 2) / 4); /*S*/ \
179 _e->type = EDGE_WE; \
180 _e->tile[0] = map_pos_to_tile((_t##_si - 6) / 4, \
181 _t##_di / 4); /*W*/ \
182 _e->tile[1] = map_pos_to_tile((_t##_si - 2) / 4, \
183 _t##_di / 4); /*E*/ \
187 if (_t##_si % 2 == 0) { \
188 if (_t##_xi % 2 == 0) { \
191 _c->tile[0] = map_pos_to_tile(_t##_xi / 2 - 1, \
192 _t##_yi / 2 - 1); /*NW*/ \
193 _c->tile[1] = map_pos_to_tile(_t##_xi / 2, \
194 _t##_yi / 2 - 1); /*NE*/ \
195 _c->tile[2] = map_pos_to_tile(_t##_xi / 2, \
196 _t##_yi / 2); /*SE*/ \
197 _c->tile[3] = map_pos_to_tile(_t##_xi / 2 - 1, \
198 _t##_yi / 2); /*SW*/ \
201 _t = map_pos_to_tile((_t##_xi - 1) / 2, \
202 (_t##_yi - 1) / 2); \
207 if (_t##_yi % 2 == 0) { \
208 _e->type = EDGE_NS; \
209 _e->tile[0] = map_pos_to_tile((_t##_xi - 1) / 2, \
210 _t##_yi / 2 - 1); /*N*/ \
211 _e->tile[1] = map_pos_to_tile((_t##_xi - 1) / 2, \
212 _t##_yi / 2); /*S*/ \
214 _e->type = EDGE_WE; \
215 _e->tile[0] = map_pos_to_tile(_t##_xi / 2 - 1, \
216 (_t##_yi - 1) / 2); /*W*/ \
217 _e->tile[1] = map_pos_to_tile(_t##_xi / 2, \
218 (_t##_yi - 1) / 2); /*E*/ \
223 #define gui_rect_iterate_end \
228 #define gui_rect_iterate_coord(GRI_x0, GRI_y0, GRI_width, GRI_height, \
229 _t, _e, _c, _x, _y) \
230 gui_rect_iterate(GRI_x0, GRI_y0, GRI_width, GRI_height, \
234 _x = _t##_xi * _t##_w / _t##_r2 - _t##_w / 2; \
235 _y = _t##_yi * _t##_h / _t##_r2 - _t##_h / 2;
237 #define gui_rect_iterate_coord_end \
238 } gui_rect_iterate_end
240 void refresh_tile_mapcanvas(struct tile
*ptile
,
241 bool full_refresh
, bool write_to_screen
);
242 void refresh_unit_mapcanvas(struct unit
*punit
, struct tile
*ptile
,
243 bool full_refresh
, bool write_to_screen
);
244 void refresh_city_mapcanvas(struct city
*pcity
, struct tile
*ptile
,
245 bool full_refresh
, bool write_to_screen
);
247 void unqueue_mapview_updates(bool write_to_screen
);
249 void map_to_gui_vector(const struct tileset
*t
,
250 int *gui_dx
, int *gui_dy
, int map_dx
, int map_dy
);
251 bool tile_to_canvas_pos(int *canvas_x
, int *canvas_y
, struct tile
*ptile
);
252 struct tile
*canvas_pos_to_tile(int canvas_x
, int canvas_y
);
253 struct tile
*canvas_pos_to_nearest_tile(int canvas_x
, int canvas_y
);
255 void get_mapview_scroll_window(int *xmin
, int *ymin
,
256 int *xmax
, int *ymax
,
257 int *xsize
, int *ysize
);
258 void get_mapview_scroll_step(int *xstep
, int *ystep
);
259 void get_mapview_scroll_pos(int *scroll_x
, int *scroll_y
);
260 void set_mapview_scroll_pos(int scroll_x
, int scroll_y
);
262 void set_mapview_origin(int gui_x0
, int gui_y0
);
263 struct tile
*get_center_tile_mapcanvas(void);
264 void center_tile_mapcanvas(struct tile
*ptile
);
266 bool tile_visible_mapcanvas(struct tile
*ptile
);
267 bool tile_visible_and_not_on_border_mapcanvas(struct tile
*ptile
);
269 void put_unit(const struct unit
*punit
, struct canvas
*pcanvas
, int canvas_x
,
271 void put_unittype(const struct unit_type
*putype
, struct canvas
*pcanvas
,
272 int canvas_x
, int canvas_y
);
273 void put_city(struct city
*pcity
,
274 struct canvas
*pcanvas
, int canvas_x
, int canvas_y
);
275 void put_terrain(struct tile
*ptile
,
276 struct canvas
*pcanvas
, int canvas_x
, int canvas_y
);
278 void put_unit_city_overlays(struct unit
*punit
,
279 struct canvas
*pcanvas
,
280 int canvas_x
, int canvas_y
, int *upkeep_cost
,
282 void toggle_city_color(struct city
*pcity
);
283 void toggle_unit_color(struct unit
*punit
);
285 void put_nuke_mushroom_pixmaps(struct tile
*ptile
);
287 void put_one_element(struct canvas
*pcanvas
, enum mapview_layer layer
,
288 const struct tile
*ptile
,
289 const struct tile_edge
*pedge
,
290 const struct tile_corner
*pcorner
,
291 const struct unit
*punit
, const struct city
*pcity
,
292 int canvas_x
, int canvas_y
,
293 const struct city
*citymode
,
294 const struct unit_type
*putype
);
296 void put_drawn_sprites(struct canvas
*pcanvas
,
297 int canvas_x
, int canvas_y
,
298 int count
, struct drawn_sprite
*pdrawn
,
301 void update_map_canvas(int canvas_x
, int canvas_y
, int width
, int height
);
302 void update_map_canvas_visible(void);
303 void update_city_description(struct city
*pcity
);
304 void update_tile_label(struct tile
*ptile
);
306 void show_city_descriptions(int canvas_x
, int canvas_y
,
307 int width
, int height
);
308 void show_tile_labels(int canvas_x
, int canvas_y
,
309 int width
, int height
);
310 bool show_unit_orders(struct unit
*punit
);
312 void draw_segment(struct tile
*ptile
, enum direction8 dir
);
313 void undraw_segment(struct tile
*ptile
, enum direction8 dir
);
315 void decrease_unit_hp_smooth(struct unit
*punit0
, int hp0
,
316 struct unit
*punit1
, int hp1
);
317 void move_unit_map_canvas(struct unit
*punit
,
318 struct tile
*ptile
, int dx
, int dy
);
320 struct city
*find_city_or_settler_near_tile(const struct tile
*ptile
,
321 struct unit
**punit
);
322 struct city
*find_city_near_tile(const struct tile
*ptile
);
324 void get_city_mapview_production(struct city
*pcity
,
325 char *buf
, size_t buf_len
);
326 void get_city_mapview_name_and_growth(struct city
*pcity
,
328 size_t name_buffer_len
,
330 size_t growth_buffer_len
,
331 enum color_std
*grwoth_color
);
332 void get_city_mapview_trade_routes(struct city
*pcity
,
333 char *trade_routes_buffer
,
334 size_t trade_routes_buffer_len
,
335 enum color_std
*trade_routes_color
);
337 bool map_canvas_resized(int width
, int height
);
338 void init_mapcanvas_and_overview(void);
339 void free_mapcanvas_and_overview(void);
341 void get_spaceship_dimensions(int *width
, int *height
);
342 void put_spaceship(struct canvas
*pcanvas
, int canvas_x
, int canvas_y
,
343 const struct player
*pplayer
);
345 void link_marks_init(void);
346 void link_marks_free(void);
348 void link_marks_draw_all(void);
349 void link_marks_clear_all(void);
350 void link_marks_decrease_turn_counters(void);
352 void link_mark_add_new(enum text_link_type type
, int id
);
353 void link_mark_restore(enum text_link_type type
, int id
);
357 #endif /* __cplusplus */
359 #endif /* FC__MAPVIEW_COMMON_H */