Freeciv-3.1
Loading...
Searching...
No Matches
overview_common.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
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)
6 any later version.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <math.h> /* floor */
19
20/* utility */
21#include "log.h"
22
23/* client */
24#include "client_main.h" /* can_client_change_view() */
25#include "climap.h"
26#include "control.h"
27#include "mapview_g.h"
28#include "options.h"
29#include "zoom.h"
30
31#include "overview_common.h"
32
34#if 0
35struct overview overview = {
36 /* These are the default values. All others are zeroed automatically. */
37 .fog = TRUE,
38 .layers = {[OLAYER_BACKGROUND] = TRUE,
42};
43#endif
44
45/*
46 * Set to TRUE if the backing store is more recent than the version
47 * drawn into overview.window.
48 */
49static bool overview_dirty = FALSE;
50
51/************************************************************************/
56static void gui_to_natural_pos(const struct tileset *t,
57 double *ntl_x, double *ntl_y,
58 int gui_x, int gui_y)
59{
60 const double gui_xd = gui_x, gui_yd = gui_y;
61 const double W = tileset_tile_width(t) * map_zoom;
62 const double H = tileset_tile_height(t) * map_zoom;
63 double map_x, map_y;
64
65 /* First convert to map positions. This ignores hex conversions; we're
66 * not looking for an exact tile. */
67 if (tileset_is_isometric(t)) {
68 /* Includes hex cases. */
69 map_x = (gui_xd * H + gui_yd * W) / (W * H);
70 map_y = (gui_yd * W - gui_xd * H) / (W * H);
71 } else {
72 map_x = gui_xd / W;
73 map_y = gui_yd / H;
74 }
75
76 /* Now convert to natural positions. Note this assumes the macro form
77 * of the conversion will work with floating-point values. */
78 MAP_TO_NATURAL_POS(ntl_x, ntl_y, map_x, map_y);
79
80}
81
82/************************************************************************/
85static void gui_to_overview_pos(const struct tileset *t,
86 int *ovr_x, int *ovr_y,
87 int gui_x, int gui_y)
88{
89 double ntl_x, ntl_y;
90
91 gui_to_natural_pos(t, &ntl_x, &ntl_y, gui_x, gui_y);
92
93 /* Now convert straight to overview coordinates. */
94 *ovr_x = floor((ntl_x - (double)gui_options.overview.map_x0) * OVERVIEW_TILE_SIZE);
95 *ovr_y = floor((ntl_y - (double)gui_options.overview.map_y0) * OVERVIEW_TILE_SIZE);
96
97 /* Now do additional adjustments. See map_to_overview_pos(). */
98 if (current_topo_has_flag(TF_WRAPX)) {
99 *ovr_x = FC_WRAP(*ovr_x, NATURAL_WIDTH * OVERVIEW_TILE_SIZE);
100 } else {
101 if (MAP_IS_ISOMETRIC) {
102 /* HACK: For iso-maps that don't wrap in the X direction we clip
103 * a half-tile off of the left and right of the overview. This
104 * means some tiles only are halfway shown. However it means we
105 * don't show any unreal tiles, which we'd otherwise be doing. The
106 * rest of the code can't handle unreal tiles in the overview. */
107 *ovr_x -= OVERVIEW_TILE_SIZE;
108 }
109 }
110 if (current_topo_has_flag(TF_WRAPY)) {
111 *ovr_y = FC_WRAP(*ovr_y, NATURAL_HEIGHT * OVERVIEW_TILE_SIZE);
112 }
113}
114
115/************************************************************************/
118static struct color *overview_tile_color(struct tile *ptile)
119{
121 struct city *pcity = tile_city(ptile);
122
123 if (pcity) {
124 if (NULL == client.conn.playing
125 || city_owner(pcity) == client.conn.playing) {
126 return get_color(tileset, COLOR_OVERVIEW_MY_CITY);
127 } else if (pplayers_allied(city_owner(pcity), client.conn.playing)) {
128 /* Includes teams. */
129 return get_color(tileset, COLOR_OVERVIEW_ALLIED_CITY);
130 } else {
131 return get_color(tileset, COLOR_OVERVIEW_ENEMY_CITY);
132 }
133 }
134 }
136 struct unit *punit = find_visible_unit(ptile);
137
138 if (punit) {
139 if (NULL == client.conn.playing
141 return get_color(tileset, COLOR_OVERVIEW_MY_UNIT);
143 /* Includes teams. */
144 return get_color(tileset, COLOR_OVERVIEW_ALLIED_UNIT);
145 } else {
146 return get_color(tileset, COLOR_OVERVIEW_ENEMY_UNIT);
147 }
148 }
149 }
151 struct player *owner = tile_owner(ptile);
152
153 if (owner) {
156 } else if (!is_ocean_tile(ptile)) {
158 }
159 }
160 }
162 && tile_terrain(ptile) != T_UNKNOWN) {
163 return get_terrain_color(tileset, tile_terrain(ptile));
164 }
166 && tile_terrain(ptile) != T_UNKNOWN) {
167 if (terrain_has_flag(tile_terrain(ptile), TER_FROZEN)) {
168 return get_color(tileset, COLOR_OVERVIEW_FROZEN);
169 } else {
170 if (is_ocean_tile(ptile)) {
171 return get_color(tileset, COLOR_OVERVIEW_OCEAN);
172 } else {
173 return get_color(tileset, COLOR_OVERVIEW_LAND);
174 }
175 }
176 }
177
178 return get_color(tileset, COLOR_OVERVIEW_UNKNOWN);
179}
180
181/************************************************************************/
186{
187 struct canvas *dest = get_overview_window();
188
189 if (!dest) {
190 return;
191 }
193 0, 0, 0, 0,
195}
196
197/************************************************************************/
201static void redraw_overview(void)
202{
203 int i, x[4], y[4];
204
205 if (!gui_options.overview.map) {
206 return;
207 }
208
209 {
210 struct canvas *src = gui_options.overview.map;
211 struct canvas *dst = gui_options.overview.window;
214 int ix = gui_options.overview.width - x_left;
215 int iy = gui_options.overview.height - y_top;
216
217 canvas_copy(dst, src, 0, 0, ix, iy, x_left, y_top);
218 canvas_copy(dst, src, 0, y_top, ix, 0, x_left, iy);
219 canvas_copy(dst, src, x_left, 0, 0, iy, ix, y_top);
220 canvas_copy(dst, src, x_left, y_top, 0, 0, ix, iy);
221 }
222
223 gui_to_overview_pos(tileset, &x[0], &y[0],
225 gui_to_overview_pos(tileset, &x[1], &y[1],
227 gui_to_overview_pos(tileset, &x[2], &y[2],
230 gui_to_overview_pos(tileset, &x[3], &y[3],
232
233 for (i = 0; i < 4; i++) {
234 int src_x = x[i];
235 int src_y = y[i];
236 int dst_x = x[(i + 1) % 4];
237 int dst_y = y[(i + 1) % 4];
238
240 get_color(tileset, COLOR_OVERVIEW_VIEWRECT),
242 src_x, src_y, dst_x - src_x, dst_y - src_y);
243 }
244
246
248}
249
250/************************************************************************/
253static void dirty_overview(void)
254{
256}
257
258/************************************************************************/
262{
263 /* Currently this function is called from mapview_common. However it
264 * should be made static eventually. */
265 if (overview_dirty) {
267 }
268}
269
270/************************************************************************/
273static double wrap_double(double value, double wrap)
274{
275 while (value < 0) {
276 value += wrap;
277 }
278 while (value >= wrap) {
279 value -= wrap;
280 }
281 return value;
282}
283
284/************************************************************************/
288{
289 double ntl_x, ntl_y;
290 int ox, oy;
291
292 gui_to_natural_pos(tileset, &ntl_x, &ntl_y,
295
296 /* NOTE: this embeds the map wrapping in the overview code. This is
297 * basically necessary for the overview to be efficiently
298 * updated. */
299 if (current_topo_has_flag(TF_WRAPX)) {
300 gui_options.overview.map_x0 = wrap_double(ntl_x - (double)NATURAL_WIDTH / 2.0,
302 } else {
304 }
305 if (current_topo_has_flag(TF_WRAPY)) {
306 gui_options.overview.map_y0 = wrap_double(ntl_y - (double)NATURAL_HEIGHT / 2.0,
308 } else {
310 }
311
313
317}
318
319/************************************************************************/
322void map_to_overview_pos(int *overview_x, int *overview_y,
323 int map_x, int map_y)
324{
325 /* The map position may not be normal, for instance when the mapview
326 * origin is not a normal position.
327 *
328 * NOTE: this embeds the map wrapping in the overview code. */
329 do_in_natural_pos(ntl_x, ntl_y, map_x, map_y) {
330 int ovr_x = ntl_x - gui_options.overview.map_x0;
331 int ovr_y = ntl_y - gui_options.overview.map_y0;
332
333 if (current_topo_has_flag(TF_WRAPX)) {
334 ovr_x = FC_WRAP(ovr_x, NATURAL_WIDTH);
335 } else {
336 if (MAP_IS_ISOMETRIC) {
337 /* HACK: For iso-maps that don't wrap in the X direction we clip
338 * a half-tile off of the left and right of the overview. This
339 * means some tiles only are halfway shown. However it means we
340 * don't show any unreal tiles, which we'd otherwise be doing. The
341 * rest of the code can't handle unreal tiles in the overview. */
342 ovr_x--;
343 }
344 }
345 if (current_topo_has_flag(TF_WRAPY)) {
346 ovr_y = FC_WRAP(ovr_y, NATURAL_HEIGHT);
347 }
348 *overview_x = OVERVIEW_TILE_SIZE * ovr_x;
349 *overview_y = OVERVIEW_TILE_SIZE * ovr_y;
351}
352
353/************************************************************************/
356void overview_to_map_pos(int *map_x, int *map_y,
357 int overview_x, int overview_y)
358{
359 int ntl_x = overview_x / OVERVIEW_TILE_SIZE + gui_options.overview.map_x0;
360 int ntl_y = overview_y / OVERVIEW_TILE_SIZE + gui_options.overview.map_y0;
361
362 if (MAP_IS_ISOMETRIC && !current_topo_has_flag(TF_WRAPX)) {
363 /* Clip half tile left and right. See comment in map_to_overview_pos. */
364 ntl_x++;
365 }
366
367 NATURAL_TO_MAP_POS(map_x, map_y, ntl_x, ntl_y);
368 /* All positions on the overview should be valid. */
369 fc_assert(normalize_map_pos(&(wld.map), map_x, map_y));
370}
371
372/************************************************************************/
376{
377 if (!can_client_change_view()) {
378 return;
379 }
380 whole_map_iterate(&(wld.map), ptile) {
384}
385
386/************************************************************************/
393 struct tile *ptile,
394 int x, int y, int w, int h)
395{
397 overview_tile_color(ptile),
398 x, y, w, h);
402 0, 0, w, h);
403 }
404}
405
406/************************************************************************/
409void overview_update_tile(struct tile *ptile)
410{
411 int tile_x, tile_y;
412
413 /* Base overview positions are just like natural positions, but scaled to
414 * the overview tile dimensions. */
415 index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
416 do_in_natural_pos(ntl_x, ntl_y, tile_x, tile_y) {
417 int overview_y = ntl_y * OVERVIEW_TILE_SIZE;
418 int overview_x = ntl_x * OVERVIEW_TILE_SIZE;
419
420 if (MAP_IS_ISOMETRIC) {
421 if (current_topo_has_flag(TF_WRAPX)) {
422 if (overview_x > gui_options.overview.width - OVERVIEW_TILE_WIDTH) {
423 /* This tile is shown half on the left and half on the right
424 * side of the overview. So we have to draw it in two parts. */
426 overview_x - gui_options.overview.width,
427 overview_y,
429 }
430 } else {
431 /* Clip half tile left and right.
432 * See comment in map_to_overview_pos. */
433 overview_x -= OVERVIEW_TILE_SIZE;
434 }
435 }
436
438 overview_x, overview_y,
440
443}
444
445/************************************************************************/
449{
450 int w, h;
451 int xfact = MAP_IS_ISOMETRIC ? 2 : 1;
452
453 static int recursion = 0; /* Just to be safe. */
454
455 /* Clip half tile left and right. See comment in map_to_overview_pos. */
456 int shift = (MAP_IS_ISOMETRIC && !current_topo_has_flag(TF_WRAPX)) ? -1 : 0;
457
458 if (recursion > 0 || wld.map.xsize <= 0 || wld.map.ysize <= 0) {
459 return;
460 }
461 recursion++;
462
465
466 /* Set the scale of the overview map. This attempts to limit the
467 * overview to the size of the area available.
468 *
469 * It rounds up since this gives good results with the default settings.
470 * It may need tweaking if the panel resizes itself. */
471 OVERVIEW_TILE_SIZE = MIN((w - 1) / (wld.map.xsize * xfact) + 1,
472 (h - 1) / wld.map.ysize + 1);
474
475 log_debug("Map size %d,%d - area size %d,%d - scale: %d", wld.map.xsize,
477
481
485 }
491 get_color(tileset, COLOR_OVERVIEW_UNKNOWN),
492 0, 0,
495
496 /* Call gui specific function. */
498
501 }
502
503 recursion--;
504}
505
506/************************************************************************/
518
519/************************************************************************/
523{
524 /* This is called once for each option changed so it is slower than
525 * necessary. If this becomes a problem it could be switched to use a
526 * queue system like the mapview drawing code does. */
528}
canvas_put_sprite
Definition canvas_g.h:42
struct canvas * pcanvas
Definition canvas_g.h:42
@ LINE_NORMAL
Definition canvas_g.h:26
#define city_owner(_pcity_)
Definition city.h:543
struct civclient client
bool can_client_change_view(void)
enum known_type client_tile_get_known(const struct tile *ptile)
Definition climap.c:36
struct color * get_player_color(const struct tileset *t, const struct player *pplayer)
struct color * get_color(const struct tileset *t, enum color_std stdcolor)
struct color * get_terrain_color(const struct tileset *t, const struct terrain *pterrain)
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:823
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct world wld
Definition game.c:58
void canvas_put_rectangle(struct canvas *pcanvas, struct color *pcolor, int canvas_x, int canvas_y, int width, int height)
Definition canvas.c:176
void canvas_free(struct canvas *store)
Definition canvas.c:44
void canvas_put_line(struct canvas *pcanvas, struct color *pcolor, enum line_type ltype, int start_x, int start_y, int dx, int dy)
Definition canvas.c:223
void canvas_copy(struct canvas *dest, struct canvas *src, int src_x, int src_y, int dest_x, int dest_y, int width, int height)
Definition canvas.c:76
struct canvas * canvas_create(int width, int height)
Definition canvas.c:28
struct city * owner
Definition citydlg.c:219
void update_map_canvas_scrollbars_size(void)
Definition mapview.c:675
void get_overview_area_dimensions(int *width, int *height)
Definition mapview.c:300
void update_overview_scroll_window_pos(int x, int y)
Definition mapview.c:636
void overview_size_changed(void)
Definition mapview.c:309
struct canvas * get_overview_window(void)
Definition mapview.c:320
#define fc_assert(condition)
Definition log.h:176
#define log_debug(message,...)
Definition log.h:115
bool normalize_map_pos(const struct civ_map *nmap, int *x, int *y)
Definition map.c:977
#define current_topo_has_flag(flag)
Definition map.h:45
#define NATURAL_TO_MAP_POS(pmap_x, pmap_y, nat_x, nat_y)
Definition map.h:172
#define do_in_natural_pos(ntl_x, ntl_y, map_x, map_y)
Definition map.h:204
#define NATURAL_HEIGHT
Definition map.h:221
#define MAP_IS_ISOMETRIC
Definition map.h:40
#define MAP_TO_NATURAL_POS(pnat_x, pnat_y, map_x, map_y)
Definition map.h:178
#define whole_map_iterate(_map, _tile)
Definition map.h:539
#define NATURAL_WIDTH
Definition map.h:220
#define do_in_natural_pos_end
Definition map.h:211
#define whole_map_iterate_end
Definition map.h:548
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:227
struct view mapview
#define H(x, y, z)
Definition md5.c:92
struct client_options gui_options
Definition options.c:71
@ OLAYER_BORDERS
Definition options.h:82
@ OLAYER_BACKGROUND
Definition options.h:80
@ OLAYER_CITIES
Definition options.h:85
@ OLAYER_BORDERS_ON_OCEAN
Definition options.h:83
@ OLAYER_UNITS
Definition options.h:84
@ OLAYER_RELIEF
Definition options.h:81
static double wrap_double(double value, double wrap)
static void gui_to_overview_pos(const struct tileset *t, int *ovr_x, int *ovr_y, int gui_x, int gui_y)
void flush_dirty_overview(void)
void overview_to_map_pos(int *map_x, int *map_y, int overview_x, int overview_y)
static void gui_to_natural_pos(const struct tileset *t, double *ntl_x, double *ntl_y, int gui_x, int gui_y)
void overview_redraw_callback(struct option *option)
void refresh_overview_canvas(void)
static bool overview_dirty
void center_tile_overviewcanvas(void)
void refresh_overview_from_canvas(void)
static void redraw_overview(void)
static struct color * overview_tile_color(struct tile *ptile)
void overview_update_tile(struct tile *ptile)
int OVERVIEW_TILE_SIZE
static void put_overview_tile_area(struct canvas *pcanvas, struct tile *ptile, int x, int y, int w, int h)
void calculate_overview_dimensions(void)
void overview_free(void)
static void dirty_overview(void)
void map_to_overview_pos(int *overview_x, int *overview_y, int map_x, int map_y)
#define OVERVIEW_TILE_WIDTH
#define OVERVIEW_TILE_HEIGHT
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
#define FC_WRAP(value, range)
Definition shared.h:65
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
static int recursion[AIT_LAST]
Definition srv_log.c:44
Definition city.h:309
int xsize
Definition map_types.h:77
int ysize
Definition map_types.h:77
struct connection conn
Definition client_main.h:96
struct overview overview
Definition options.h:402
Definition colors.h:20
struct player * playing
Definition connection.h:156
double map_y0
Definition options.h:92
double map_x0
Definition options.h:92
bool fog
Definition options.h:101
bool layers[OLAYER_COUNT]
Definition options.h:102
struct canvas * map
Definition options.h:96
int width
Definition options.h:93
struct canvas * window
Definition options.h:99
int height
Definition options.h:93
Definition tile.h:49
Definition unit.h:138
int height
float gui_x0
float gui_y0
int width
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define T_UNKNOWN
Definition terrain.h:57
#define is_ocean_tile(ptile)
Definition terrain.h:289
#define terrain_has_flag(terr, flag)
Definition terrain.h:269
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:87
@ TILE_KNOWN_UNSEEN
Definition tile.h:36
#define tile_terrain(_tile)
Definition tile.h:109
#define tile_owner(_tile)
Definition tile.h:95
struct sprite * get_basic_fog_sprite(const struct tileset *t)
Definition tilespec.c:6748
bool tileset_is_isometric(const struct tileset *t)
Definition tilespec.c:675
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:728
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:716
#define unit_owner(_pu)
Definition unit.h:394
float map_zoom
Definition zoom.c:25