OpenTTD
smallmap_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "clear_map.h"
14 #include "industry.h"
15 #include "station_map.h"
16 #include "landscape.h"
17 #include "tree_map.h"
18 #include "viewport_func.h"
19 #include "town.h"
20 #include "tunnelbridge_map.h"
21 #include "core/endian_func.hpp"
22 #include "vehicle_base.h"
23 #include "sound_func.h"
24 #include "window_func.h"
25 #include "company_base.h"
26 #include "guitimer_func.h"
27 
28 #include "smallmap_gui.h"
29 
30 #include "table/strings.h"
31 
32 #include <bitset>
33 
34 #include "safeguards.h"
35 
39 
41 static uint8 _linkstat_colours_in_legenda[] = {0, 1, 3, 5, 7, 9, 11};
42 
43 static const int NUM_NO_COMPANY_ENTRIES = 4;
44 
45 static const uint8 PC_ROUGH_LAND = 0x52;
46 static const uint8 PC_GRASS_LAND = 0x54;
47 static const uint8 PC_BARE_LAND = 0x37;
48 static const uint8 PC_FIELDS = 0x25;
49 static const uint8 PC_TREES = 0x57;
50 static const uint8 PC_WATER = 0xCA;
51 
53 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
54 
56 #define MC(col_break) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, col_break}
57 
59 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
60 
62 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
63 
65 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
66 
71 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
72 
75  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
76  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
77  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
78  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
79  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_VEHICLES),
80 
81  /* Placeholders for the colours and heights of the legend.
82  * The following values are set at BuildLandLegend() based
83  * on each colour scheme and the maximum map height. */
84  MC(true),
85  MC(false),
86  MC(false),
87  MC(false),
88  MC(false),
89  MC(false),
90  MC(true),
91  MC(false),
92  MC(false),
93  MC(false),
94  MC(false),
95  MC(false),
96  MKEND()
97 };
98 
99 static const LegendAndColour _legend_vehicles[] = {
100  MK(PC_RED, STR_SMALLMAP_LEGENDA_TRAINS),
101  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
102  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SHIPS),
103  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_AIRCRAFT),
104 
105  MS(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
106  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
107  MKEND()
108 };
109 
110 static const LegendAndColour _legend_routes[] = {
111  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
112  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
113  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
114 
115  MS(PC_VERY_DARK_BROWN, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
116  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
117  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_BUS_STATION),
118  MK(PC_RED, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
119  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_DOCK),
120  MKEND()
121 };
122 
123 static const LegendAndColour _legend_vegetation[] = {
124  MK(PC_ROUGH_LAND, STR_SMALLMAP_LEGENDA_ROUGH_LAND),
125  MK(PC_GRASS_LAND, STR_SMALLMAP_LEGENDA_GRASS_LAND),
126  MK(PC_BARE_LAND, STR_SMALLMAP_LEGENDA_BARE_LAND),
127  MK(PC_FIELDS, STR_SMALLMAP_LEGENDA_FIELDS),
128  MK(PC_TREES, STR_SMALLMAP_LEGENDA_TREES),
129  MK(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST),
130 
131  MS(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS),
132  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_DESERT),
133  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SNOW),
134  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
135  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
136  MKEND()
137 };
138 
139 static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
140  MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER),
141  MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings.
142  MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS),
143  MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES),
144  /* The legend will be terminated the first time it is used. */
145  MOEND(),
146 };
147 
148 #undef MK
149 #undef MC
150 #undef MS
151 #undef MO
152 #undef MOEND
153 #undef MKEND
154 
165 static bool _smallmap_show_heightmap = false;
172 
177 {
178  uint j = 0;
179 
180  /* Add each name */
181  for (uint i = 0; i < NUM_INDUSTRYTYPES; i++) {
182  IndustryType ind = _sorted_industry_types[i];
183  const IndustrySpec *indsp = GetIndustrySpec(ind);
184  if (indsp->enabled) {
185  _legend_from_industries[j].legend = indsp->name;
186  _legend_from_industries[j].colour = indsp->map_colour;
187  _legend_from_industries[j].type = ind;
188  _legend_from_industries[j].show_on_map = true;
189  _legend_from_industries[j].col_break = false;
190  _legend_from_industries[j].end = false;
191 
192  /* Store widget number for this industry type. */
193  _industry_to_list_pos[ind] = j;
194  j++;
195  }
196  }
197  /* Terminate the list */
198  _legend_from_industries[j].end = true;
199 
200  /* Store number of enabled industries */
202 }
203 
208 {
209  /* Clear the legend */
210  memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
211 
212  uint i = 0;
213  for (; i < _sorted_cargo_specs_size; ++i) {
214  const CargoSpec *cs = _sorted_cargo_specs[i];
215 
216  _legend_linkstats[i].legend = cs->name;
217  _legend_linkstats[i].colour = cs->legend_colour;
218  _legend_linkstats[i].type = cs->Index();
219  _legend_linkstats[i].show_on_map = true;
220  }
221 
222  _legend_linkstats[i].col_break = true;
224 
226  _legend_linkstats[i].legend = STR_EMPTY;
228  _legend_linkstats[i].show_on_map = true;
229  }
230 
231  _legend_linkstats[_smallmap_cargo_count].legend = STR_LINKGRAPH_LEGEND_UNUSED;
232  _legend_linkstats[i - 1].legend = STR_LINKGRAPH_LEGEND_OVERLOADED;
233  _legend_linkstats[(_smallmap_cargo_count + i - 1) / 2].legend = STR_LINKGRAPH_LEGEND_SATURATED;
234  _legend_linkstats[i].end = true;
235 }
236 
237 static const LegendAndColour * const _legend_table[] = {
239  _legend_vehicles,
242  _legend_routes,
243  _legend_vegetation,
244  _legend_land_owners,
245 };
246 
247 #define MKCOLOUR(x) TO_LE32X(x)
248 
249 #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x))
250 #define MKCOLOUR_X0X0(x) (MKCOLOUR(0x01000100) * (uint)(x))
251 #define MKCOLOUR_0X0X(x) (MKCOLOUR(0x00010001) * (uint)(x))
252 #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x))
253 #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x))
254 
255 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
256 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
257 
258 #define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00)
259 #define MKCOLOUR_0FF0 MKCOLOUR_0XX0(0xFF)
260 #define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF)
261 #define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF)
262 
263 #include "table/heightmap_colours.h"
264 
267  uint32 *height_colours;
268  const uint32 *height_colours_base;
269  size_t colour_count;
270  uint32 default_colour;
271 };
272 
275  {NULL, _green_map_heights, lengthof(_green_map_heights), MKCOLOUR_XXXX(0x54)},
276  {NULL, _dark_green_map_heights, lengthof(_dark_green_map_heights), MKCOLOUR_XXXX(0x62)},
277  {NULL, _violet_map_heights, lengthof(_violet_map_heights), MKCOLOUR_XXXX(0x82)},
278 };
279 
284 {
285  /* The smallmap window has never been initialized, so no need to change the legend. */
286  if (_heightmap_schemes[0].height_colours == NULL) return;
287 
288  /*
289  * The general idea of this function is to fill the legend with an appropriate evenly spaced
290  * selection of height levels. All entries with STR_TINY_BLACK_HEIGHT are reserved for this.
291  * At the moment there are twelve of these.
292  *
293  * The table below defines up to which height level a particular delta in the legend should be
294  * used. One could opt for just dividing the maximum height and use that as delta, but that
295  * creates many "ugly" legend labels, e.g. once every 950 meter. As a result, this table will
296  * reduce the number of deltas to 7: every 100m, 200m, 300m, 500m, 750m, 1000m and 1250m. The
297  * deltas are closer together at the lower numbers because going from 12 entries to just 4, as
298  * would happen when replacing 200m and 300m by 250m, would mean the legend would be short and
299  * that might not be considered appropriate.
300  *
301  * The current method yields at least 7 legend entries and at most 12. It can be increased to
302  * 8 by adding a 150m and 400m option, but especially 150m creates ugly heights.
303  *
304  * It tries to evenly space the legend items over the two columns that are there for the legend.
305  */
306 
307  /* Table for delta; if max_height is less than the first column, use the second column as value. */
308  uint deltas[][2] = { { 24, 2 }, { 48, 4 }, { 72, 6 }, { 120, 10 }, { 180, 15 }, { 240, 20 }, { MAX_TILE_HEIGHT + 1, 25 }};
309  uint i = 0;
310  for (; _settings_game.construction.max_heightlevel >= deltas[i][0]; i++) {
311  /* Nothing to do here. */
312  }
313  uint delta = deltas[i][1];
314 
315  int total_entries = (_settings_game.construction.max_heightlevel / delta) + 1;
316  int rows = CeilDiv(total_entries, 2);
317  int j = 0;
318 
319  for (i = 0; i < lengthof(_legend_land_contours) - 1 && j < total_entries; i++) {
320  if (_legend_land_contours[i].legend != STR_TINY_BLACK_HEIGHT) continue;
321 
322  _legend_land_contours[i].col_break = j % rows == 0;
323  _legend_land_contours[i].end = false;
324  _legend_land_contours[i].height = j * delta;
325  _legend_land_contours[i].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[j * delta];
326  j++;
327  }
328  _legend_land_contours[i].end = true;
329 }
330 
335 {
336  _legend_land_owners[1].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour;
337 
338  int i = NUM_NO_COMPANY_ENTRIES;
339  const Company *c;
340  FOR_ALL_COMPANIES(c) {
341  _legend_land_owners[i].colour = _colour_gradient[c->colour][5];
342  _legend_land_owners[i].company = c->index;
343  _legend_land_owners[i].show_on_map = true;
344  _legend_land_owners[i].col_break = false;
345  _legend_land_owners[i].end = false;
346  _company_to_list_pos[c->index] = i;
347  i++;
348  }
349 
350  /* Terminate the list */
351  _legend_land_owners[i].end = true;
352 
353  /* Store maximum amount of owner legend entries. */
355 }
356 
357 struct AndOr {
358  uint32 mor;
359  uint32 mand;
360 };
361 
362 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
363 {
364  return (colour & mask->mand) | mask->mor;
365 }
366 
367 
369 static const AndOr _smallmap_contours_andor[] = {
370  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
371  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F}, // MP_RAILWAY
372  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
373  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
374  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
375  {MKCOLOUR_XXXX(PC_LIGHT_BLUE), MKCOLOUR_0000}, // MP_STATION
376  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
377  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
378  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
379  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
380  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
381  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F},
382 };
383 
385 static const AndOr _smallmap_vehicles_andor[] = {
386  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
387  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_RAILWAY
388  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
389  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
390  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
391  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_STATION
392  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
393  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
394  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
395  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
396  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
397  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
398 };
399 
401 static const byte _tiletype_importance[] = {
402  2, // MP_CLEAR
403  8, // MP_RAILWAY
404  7, // MP_ROAD
405  5, // MP_HOUSE
406  2, // MP_TREES
407  9, // MP_STATION
408  2, // MP_WATER
409  1, // MP_VOID
410  6, // MP_INDUSTRY
411  8, // MP_TUNNELBRIDGE
412  2, // MP_OBJECT
413  0,
414 };
415 
416 
423 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
424 {
425  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
426  return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[t]);
427 }
428 
436 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
437 {
438  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
439  return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
440 }
441 
449 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
450 {
451  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
452  return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[t]);
453 }
454 
462 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
463 {
464  if (t == MP_STATION) {
465  switch (GetStationType(tile)) {
466  case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
467  case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
468  case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
469  case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
470  case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
471  default: return MKCOLOUR_FFFF;
472  }
473  } else if (t == MP_RAILWAY) {
474  AndOr andor = {
475  MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
476  _smallmap_contours_andor[t].mand
477  };
478 
479  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
480  return ApplyMask(cs->default_colour, &andor);
481  }
482 
483  /* Ground colour */
484  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
485  return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
486 }
487 
495 static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
496 {
498 }
499 
500 static const uint32 _vegetation_clear_bits[] = {
501  MKCOLOUR_XXXX(PC_GRASS_LAND),
502  MKCOLOUR_XXXX(PC_ROUGH_LAND),
503  MKCOLOUR_XXXX(PC_GREY),
504  MKCOLOUR_XXXX(PC_FIELDS),
505  MKCOLOUR_XXXX(PC_LIGHT_BLUE),
506  MKCOLOUR_XXXX(PC_ORANGE),
507  MKCOLOUR_XXXX(PC_GRASS_LAND),
508  MKCOLOUR_XXXX(PC_GRASS_LAND),
509 };
510 
518 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
519 {
520  switch (t) {
521  case MP_CLEAR:
522  return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR_XXXX(PC_BARE_LAND) : _vegetation_clear_bits[GetClearGround(tile)];
523 
524  case MP_INDUSTRY:
525  return IsTileForestIndustry(tile) ? MKCOLOUR_XXXX(PC_GREEN) : MKCOLOUR_XXXX(PC_DARK_RED);
526 
527  case MP_TREES:
529  return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
530  }
531  return MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
532 
533  default:
534  return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
535  }
536 }
537 
545 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
546 {
547  Owner o;
548 
549  switch (t) {
550  case MP_INDUSTRY: return MKCOLOUR_XXXX(PC_DARK_GREY);
551  case MP_HOUSE: return MKCOLOUR_XXXX(PC_DARK_RED);
552  default: o = GetTileOwner(tile); break;
553  /* FIXME: For MP_ROAD there are multiple owners.
554  * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
555  * even if there are no ROADTYPE_ROAD bits on the tile.
556  */
557  }
558 
559  if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
560  if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
561  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
563  } else if (o == OWNER_TOWN) {
564  return MKCOLOUR_XXXX(PC_DARK_RED);
565  }
566 
567  return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
568 }
569 
571 static const byte _vehicle_type_colours[6] = {
573 };
574 
575 
578 {
580 }
581 
582 inline Point SmallMapWindow::SmallmapRemapCoords(int x, int y) const
583 {
584  Point pt;
585  pt.x = (y - x) * 2;
586  pt.y = y + x;
587  return pt;
588 }
589 
596 inline Point SmallMapWindow::RemapTile(int tile_x, int tile_y) const
597 {
598  int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
599  int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
600 
601  if (this->zoom == 1) return SmallmapRemapCoords(x_offset, y_offset);
602 
603  /* For negative offsets, round towards -inf. */
604  if (x_offset < 0) x_offset -= this->zoom - 1;
605  if (y_offset < 0) y_offset -= this->zoom - 1;
606 
607  return SmallmapRemapCoords(x_offset / this->zoom, y_offset / this->zoom);
608 }
609 
620 inline Point SmallMapWindow::PixelToTile(int px, int py, int *sub, bool add_sub) const
621 {
622  if (add_sub) px += this->subscroll; // Total horizontal offset.
623 
624  /* For each two rows down, add a x and a y tile, and
625  * For each four pixels to the right, move a tile to the right. */
626  Point pt = {((py >> 1) - (px >> 2)) * this->zoom, ((py >> 1) + (px >> 2)) * this->zoom};
627  px &= 3;
628 
629  if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
630  if (px < 2) {
631  pt.x += this->zoom;
632  px += 2;
633  } else {
634  pt.y += this->zoom;
635  px -= 2;
636  }
637  }
638 
639  *sub = px;
640  return pt;
641 }
642 
652 Point SmallMapWindow::ComputeScroll(int tx, int ty, int x, int y, int *sub)
653 {
654  assert(x >= 0 && y >= 0);
655 
656  int new_sub;
657  Point tile_xy = PixelToTile(x, y, &new_sub, false);
658  tx -= tile_xy.x;
659  ty -= tile_xy.y;
660 
661  Point scroll;
662  if (new_sub == 0) {
663  *sub = 0;
664  scroll.x = (tx + this->zoom) * TILE_SIZE;
665  scroll.y = (ty - this->zoom) * TILE_SIZE;
666  } else {
667  *sub = 4 - new_sub;
668  scroll.x = (tx + 2 * this->zoom) * TILE_SIZE;
669  scroll.y = (ty - 2 * this->zoom) * TILE_SIZE;
670  }
671  return scroll;
672 }
673 
681 {
682  static const int zoomlevels[] = {1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
683  static const int MIN_ZOOM_INDEX = 0;
684  static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
685 
686  int new_index, cur_index, sub;
687  Point tile;
688  switch (change) {
689  case ZLC_INITIALIZE:
690  cur_index = - 1; // Definitely different from new_index.
691  new_index = MIN_ZOOM_INDEX;
692  tile.x = tile.y = 0;
693  break;
694 
695  case ZLC_ZOOM_IN:
696  case ZLC_ZOOM_OUT:
697  for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
698  if (this->zoom == zoomlevels[cur_index]) break;
699  }
700  assert(cur_index <= MAX_ZOOM_INDEX);
701 
702  tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
703  new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
704  break;
705 
706  default: NOT_REACHED();
707  }
708 
709  if (new_index != cur_index) {
710  this->zoom = zoomlevels[new_index];
711  if (cur_index >= 0) {
712  Point new_tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
713  this->SetNewScroll(this->scroll_x + (tile.x - new_tile.x) * TILE_SIZE,
714  this->scroll_y + (tile.y - new_tile.y) * TILE_SIZE, sub);
715  } else if (this->map_type == SMT_LINKSTATS) {
716  this->overlay->RebuildCache();
717  }
718  this->SetWidgetDisabledState(WID_SM_ZOOM_IN, this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
719  this->SetWidgetDisabledState(WID_SM_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
720  this->SetDirty();
721  }
722 }
723 
729 inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
730 {
731  int importance = 0;
732  TileIndex tile = INVALID_TILE; // Position of the most important tile.
733  TileType et = MP_VOID; // Effective tile type at that position.
734 
735  TILE_AREA_LOOP(ti, ta) {
736  TileType ttype = GetTileType(ti);
737 
738  switch (ttype) {
739  case MP_TUNNELBRIDGE: {
741 
742  switch (tt) {
743  case TRANSPORT_RAIL: ttype = MP_RAILWAY; break;
744  case TRANSPORT_ROAD: ttype = MP_ROAD; break;
745  default: ttype = MP_WATER; break;
746  }
747  break;
748  }
749 
750  case MP_INDUSTRY:
751  /* Special handling of industries while in "Industries" smallmap view. */
752  if (this->map_type == SMT_INDUSTRY) {
753  /* If industry is allowed to be seen, use its colour on the map.
754  * This has the highest priority above any value in _tiletype_importance. */
755  IndustryType type = Industry::GetByTile(ti)->type;
756  if (_legend_from_industries[_industry_to_list_pos[type]].show_on_map) {
757  if (type == _smallmap_industry_highlight) {
758  if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE);
759  } else {
760  return GetIndustrySpec(type)->map_colour * 0x01010101;
761  }
762  }
763  /* Otherwise make it disappear */
764  ttype = IsTileOnWater(ti) ? MP_WATER : MP_CLEAR;
765  }
766  break;
767 
768  default:
769  break;
770  }
771 
772  if (_tiletype_importance[ttype] > importance) {
773  importance = _tiletype_importance[ttype];
774  tile = ti;
775  et = ttype;
776  }
777  }
778 
779  switch (this->map_type) {
780  case SMT_CONTOUR:
781  return GetSmallMapContoursPixels(tile, et);
782 
783  case SMT_VEHICLES:
784  return GetSmallMapVehiclesPixels(tile, et);
785 
786  case SMT_INDUSTRY:
787  return GetSmallMapIndustriesPixels(tile, et);
788 
789  case SMT_LINKSTATS:
790  return GetSmallMapLinkStatsPixels(tile, et);
791 
792  case SMT_ROUTES:
793  return GetSmallMapRoutesPixels(tile, et);
794 
795  case SMT_VEGETATION:
796  return GetSmallMapVegetationPixels(tile, et);
797 
798  case SMT_OWNER:
799  return GetSmallMapOwnerPixels(tile, et);
800 
801  default: NOT_REACHED();
802  }
803 }
804 
818 void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
819 {
820  void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
821  uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
822 
823  do {
824  /* Check if the tile (xc,yc) is within the map range */
825  if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
826 
827  /* Check if the dst pointer points to a pixel inside the screen buffer */
828  if (dst < _screen.dst_ptr) continue;
829  if (dst >= dst_ptr_abs_end) continue;
830 
831  /* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
832  TileArea ta;
833  if (min_xy == 1 && (xc == 0 || yc == 0)) {
834  if (this->zoom == 1) continue; // The tile area is empty, don't draw anything.
835 
836  ta = TileArea(TileXY(max(min_xy, xc), max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
837  } else {
838  ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
839  }
840  ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
841 
842  uint32 val = this->GetTileColours(ta);
843  uint8 *val8 = (uint8 *)&val;
844  int idx = max(0, -start_pos);
845  for (int pos = max(0, start_pos); pos < end_pos; pos++) {
846  blitter->SetPixel(dst, idx, 0, val8[idx]);
847  idx++;
848  }
849  /* Switch to next tile in the column */
850  } while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
851 }
852 
858 void SmallMapWindow::DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
859 {
860  const Vehicle *v;
861  FOR_ALL_VEHICLES(v) {
862  if (v->type == VEH_EFFECT) continue;
863  if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
864 
865  /* Remap into flat coordinates. */
866  Point pt = this->RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
867 
868  int y = pt.y - dpi->top;
869  if (!IsInsideMM(y, 0, dpi->height)) continue; // y is out of bounds.
870 
871  bool skip = false; // Default is to draw both pixels.
872  int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
873  if (x < 0) {
874  /* if x+1 is 0, that means we're on the very left edge,
875  * and should thus only draw a single pixel */
876  if (++x != 0) continue;
877  skip = true;
878  } else if (x >= dpi->width - 1) {
879  /* Check if we're at the very right edge, and if so draw only a single pixel */
880  if (x != dpi->width - 1) continue;
881  skip = true;
882  }
883 
884  /* Calculate pointer to pixel and the colour */
885  byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
886 
887  /* And draw either one or two pixels depending on clipping */
888  blitter->SetPixel(dpi->dst_ptr, x, y, colour);
889  if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
890  }
891 }
892 
898 {
899  const Town *t;
900  FOR_ALL_TOWNS(t) {
901  /* Remap the town coordinate */
902  Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
903  int x = pt.x - this->subscroll - (t->cache.sign.width_small >> 1);
904  int y = pt.y;
905 
906  /* Check if the town sign is within bounds */
907  if (x + t->cache.sign.width_small > dpi->left &&
908  x < dpi->left + dpi->width &&
909  y + FONT_HEIGHT_SMALL > dpi->top &&
910  y < dpi->top + dpi->height) {
911  /* And draw it. */
912  SetDParam(0, t->index);
913  DrawString(x, x + t->cache.sign.width_small, y, STR_SMALLMAP_TOWN);
914  }
915  }
916 }
917 
922 {
923  /* Find main viewport. */
925 
926  Point upper_left_smallmap_coord = InverseRemapCoords2(vp->virtual_left, vp->virtual_top);
927  Point lower_right_smallmap_coord = InverseRemapCoords2(vp->virtual_left + vp->virtual_width - 1, vp->virtual_top + vp->virtual_height - 1);
928 
929  Point upper_left = this->RemapTile(upper_left_smallmap_coord.x / (int)TILE_SIZE, upper_left_smallmap_coord.y / (int)TILE_SIZE);
930  upper_left.x -= this->subscroll;
931 
932  Point lower_right = this->RemapTile(lower_right_smallmap_coord.x / (int)TILE_SIZE, lower_right_smallmap_coord.y / (int)TILE_SIZE);
933  lower_right.x -= this->subscroll;
934 
935  SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
936  SmallMapWindow::DrawVertMapIndicator(lower_right.x, upper_left.y, lower_right.y);
937 
938  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, upper_left.y);
939  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, lower_right.y);
940 }
941 
954 {
956  DrawPixelInfo *old_dpi;
957 
958  old_dpi = _cur_dpi;
959  _cur_dpi = dpi;
960 
961  /* Clear it */
962  GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
963 
964  /* Which tile is displayed at (dpi->left, dpi->top)? */
965  int dx;
966  Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
967  int tile_x = this->scroll_x / (int)TILE_SIZE + tile.x;
968  int tile_y = this->scroll_y / (int)TILE_SIZE + tile.y;
969 
970  void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
971  int x = - dx - 4;
972  int y = 0;
973 
974  for (;;) {
975  /* Distance from left edge */
976  if (x >= -3) {
977  if (x >= dpi->width) break; // Exit the loop.
978 
979  int end_pos = min(dpi->width, x + 4);
980  int reps = (dpi->height - y + 1) / 2; // Number of lines.
981  if (reps > 0) {
982  this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
983  }
984  }
985 
986  if (y == 0) {
987  tile_y += this->zoom;
988  y++;
989  ptr = blitter->MoveTo(ptr, 0, 1);
990  } else {
991  tile_x -= this->zoom;
992  y--;
993  ptr = blitter->MoveTo(ptr, 0, -1);
994  }
995  ptr = blitter->MoveTo(ptr, 2, 0);
996  x += 2;
997  }
998 
999  /* Draw vehicles */
1000  if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
1001 
1002  /* Draw link stat overlay */
1003  if (this->map_type == SMT_LINKSTATS) this->overlay->Draw(dpi);
1004 
1005  /* Draw town names */
1006  if (this->show_towns) this->DrawTowns(dpi);
1007 
1008  /* Draw map indicators */
1009  this->DrawMapIndicators();
1010 
1011  _cur_dpi = old_dpi;
1012 }
1013 
1018 {
1019  StringID legend_tooltip;
1020  StringID enable_all_tooltip;
1021  StringID disable_all_tooltip;
1022  int plane;
1023  switch (this->map_type) {
1024  case SMT_INDUSTRY:
1025  legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
1026  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
1027  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
1028  plane = 0;
1029  break;
1030 
1031  case SMT_OWNER:
1032  legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
1033  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
1034  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
1035  plane = 0;
1036  break;
1037 
1038  case SMT_LINKSTATS:
1039  legend_tooltip = STR_SMALLMAP_TOOLTIP_CARGO_SELECTION;
1040  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS;
1041  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_CARGOS;
1042  plane = 0;
1043  break;
1044 
1045  default:
1046  legend_tooltip = STR_NULL;
1047  enable_all_tooltip = STR_NULL;
1048  disable_all_tooltip = STR_NULL;
1049  plane = 1;
1050  break;
1051  }
1052 
1053  this->GetWidget<NWidgetCore>(WID_SM_LEGEND)->SetDataTip(STR_NULL, legend_tooltip);
1054  this->GetWidget<NWidgetCore>(WID_SM_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip);
1055  this->GetWidget<NWidgetCore>(WID_SM_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip);
1056  this->GetWidget<NWidgetStacked>(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane);
1057 }
1058 
1059 SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(GUITimer(FORCE_REFRESH_PERIOD))
1060 {
1062  this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1);
1063  this->InitNested(window_number);
1064  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1065 
1066  this->RebuildColourIndexIfNecessary();
1067 
1068  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1069 
1070  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1071 
1072  this->SetupWidgetData();
1073 
1074  this->SetZoomLevel(ZLC_INITIALIZE, NULL);
1075  this->SmallMapCenterOnCurrentPos();
1076  this->SetOverlayCargoMask();
1077 }
1078 
1079 SmallMapWindow::~SmallMapWindow()
1080 {
1081  delete this->overlay;
1082  this->BreakIndustryChainLink();
1083 }
1084 
1089 {
1090  /* Rebuild colour indices if necessary. */
1092 
1093  for (uint n = 0; n < lengthof(_heightmap_schemes); n++) {
1094  /* The heights go from 0 up to and including maximum. */
1095  int heights = _settings_game.construction.max_heightlevel + 1;
1096  _heightmap_schemes[n].height_colours = ReallocT<uint32>(_heightmap_schemes[n].height_colours, heights);
1097 
1098  for (int z = 0; z < heights; z++) {
1099  size_t access_index = (_heightmap_schemes[n].colour_count * z) / heights;
1100 
1101  /* Choose colour by mapping the range (0..max heightlevel) on the complete colour table. */
1102  _heightmap_schemes[n].height_colours[z] = _heightmap_schemes[n].height_colours_base[access_index];
1103  }
1104  }
1105 
1107  BuildLandLegend();
1108 }
1109 
1110 /* virtual */ void SmallMapWindow::SetStringParameters(int widget) const
1111 {
1112  switch (widget) {
1113  case WID_SM_CAPTION:
1114  SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
1115  break;
1116  }
1117 }
1118 
1119 /* virtual */ void SmallMapWindow::OnInit()
1120 {
1121  uint min_width = 0;
1122  this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
1123  this->min_number_of_fixed_rows = lengthof(_linkstat_colours_in_legenda);
1124  for (uint i = 0; i < lengthof(_legend_table); i++) {
1125  uint height = 0;
1126  uint num_columns = 1;
1127  for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
1128  StringID str;
1129  if (i == SMT_INDUSTRY) {
1130  SetDParam(0, tbl->legend);
1132  str = STR_SMALLMAP_INDUSTRY;
1133  } else if (i == SMT_LINKSTATS) {
1134  SetDParam(0, tbl->legend);
1135  str = STR_SMALLMAP_LINKSTATS;
1136  } else if (i == SMT_OWNER) {
1137  if (tbl->company != INVALID_COMPANY) {
1138  if (!Company::IsValidID(tbl->company)) {
1139  /* Rebuild the owner legend. */
1140  BuildOwnerLegend();
1141  this->OnInit();
1142  return;
1143  }
1144  /* Non-fixed legend entries for the owner view. */
1145  SetDParam(0, tbl->company);
1146  str = STR_SMALLMAP_COMPANY;
1147  } else {
1148  str = tbl->legend;
1149  }
1150  } else {
1151  if (tbl->col_break) {
1152  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1153  height = 0;
1154  num_columns++;
1155  }
1156  height++;
1157  str = tbl->legend;
1158  }
1159  min_width = max(GetStringBoundingBox(str).width, min_width);
1160  }
1161  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1162  this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
1163  }
1164 
1165  /* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
1166  this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1167 }
1168 
1169 /* virtual */ void SmallMapWindow::OnPaint()
1170 {
1171  if (this->map_type == SMT_OWNER) {
1172  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1173  if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
1174  /* Rebuild the owner legend. */
1175  BuildOwnerLegend();
1176  this->InvalidateData(1);
1177  break;
1178  }
1179  }
1180  }
1181 
1182  this->DrawWidgets();
1183 }
1184 
1185 /* virtual */ void SmallMapWindow::DrawWidget(const Rect &r, int widget) const
1186 {
1187  switch (widget) {
1188  case WID_SM_MAP: {
1189  DrawPixelInfo new_dpi;
1190  if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
1191  this->DrawSmallMap(&new_dpi);
1192  break;
1193  }
1194 
1195  case WID_SM_LEGEND: {
1196  uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
1197  uint number_of_rows = this->GetNumberRowsLegend(columns);
1198  bool rtl = _current_text_dir == TD_RTL;
1199  uint y_org = r.top + WD_FRAMERECT_TOP;
1200  uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
1201  uint y = y_org;
1202  uint i = 0; // Row counter for industry legend.
1203  uint row_height = FONT_HEIGHT_SMALL;
1204 
1205  uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
1206  uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
1207  uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
1208  uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
1209 
1210  StringID string = STR_NULL;
1211  switch (this->map_type) {
1212  case SMT_INDUSTRY:
1213  string = STR_SMALLMAP_INDUSTRY;
1214  break;
1215  case SMT_LINKSTATS:
1216  string = STR_SMALLMAP_LINKSTATS;
1217  break;
1218  case SMT_OWNER:
1219  string = STR_SMALLMAP_COMPANY;
1220  break;
1221  default:
1222  break;
1223  }
1224 
1225  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1226  if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_LINKSTATS) && i++ >= number_of_rows)) {
1227  /* Column break needed, continue at top, COLUMN_WIDTH pixels
1228  * (one "row") to the right. */
1229  x += rtl ? -(int)this->column_width : this->column_width;
1230  y = y_org;
1231  i = 1;
1232  }
1233 
1234  uint8 legend_colour = tbl->colour;
1235 
1236  switch (this->map_type) {
1237  case SMT_INDUSTRY:
1238  /* Industry name must be formatted, since it's not in tiny font in the specs.
1239  * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font */
1240  SetDParam(0, tbl->legend);
1242  if (tbl->show_on_map && tbl->type == _smallmap_industry_highlight) {
1244  }
1245  FALLTHROUGH;
1246 
1247  case SMT_LINKSTATS:
1248  SetDParam(0, tbl->legend);
1249  FALLTHROUGH;
1250 
1251  case SMT_OWNER:
1252  if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
1253  if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
1254  if (!tbl->show_on_map) {
1255  /* Simply draw the string, not the black border of the legend colour.
1256  * This will enforce the idea of the disabled item */
1257  DrawString(x + text_left, x + text_right, y, string, TC_GREY);
1258  } else {
1259  DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
1260  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
1261  }
1262  break;
1263  }
1264  FALLTHROUGH;
1265 
1266  default:
1267  if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
1268  /* Anything that is not an industry or a company is using normal process */
1269  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
1270  DrawString(x + text_left, x + text_right, y, tbl->legend);
1271  break;
1272  }
1273  GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour
1274 
1275  y += row_height;
1276  }
1277  }
1278  }
1279 }
1280 
1286 {
1287  this->RaiseWidget(this->map_type + WID_SM_CONTOUR);
1288  this->map_type = map_type;
1289  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1290 
1291  this->SetupWidgetData();
1292 
1293  if (map_type == SMT_LINKSTATS) this->overlay->RebuildCache();
1294  if (map_type != SMT_INDUSTRY) this->BreakIndustryChainLink();
1295  this->SetDirty();
1296 }
1297 
1306 inline uint SmallMapWindow::GetNumberRowsLegend(uint columns) const
1307 {
1308  /* Reserve one column for link colours */
1309  uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
1310  uint num_rows_others = CeilDiv(max(_smallmap_industry_count, _smallmap_company_count), columns);
1311  return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
1312 }
1313 
1325 void SmallMapWindow::SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item)
1326 {
1327  if (_ctrl_pressed) {
1328  /* Disable all, except the clicked one */
1329  bool changes = false;
1330  for (int i = begin_legend_item; i != end_legend_item; i++) {
1331  bool new_state = (i == click_pos);
1332  if (legend[i].show_on_map != new_state) {
1333  changes = true;
1334  legend[i].show_on_map = new_state;
1335  }
1336  }
1337  if (!changes) {
1338  /* Nothing changed? Then show all (again). */
1339  for (int i = begin_legend_item; i != end_legend_item; i++) {
1340  legend[i].show_on_map = true;
1341  }
1342  }
1343  } else {
1344  legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
1345  }
1346 
1347  if (this->map_type == SMT_INDUSTRY) this->BreakIndustryChainLink();
1348 }
1349 
1354 {
1355  CargoTypes cargo_mask = 0;
1356  for (int i = 0; i != _smallmap_cargo_count; ++i) {
1357  if (_legend_linkstats[i].show_on_map) SetBit(cargo_mask, _legend_linkstats[i].type);
1358  }
1359  this->overlay->SetCargoMask(cargo_mask);
1360 }
1361 
1368 {
1369  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_LEGEND);
1370  uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
1371  uint columns = this->GetNumberColumnsLegend(wi->current_x);
1372  uint number_of_rows = this->GetNumberRowsLegend(columns);
1373  if (line >= number_of_rows) return -1;
1374 
1375  bool rtl = _current_text_dir == TD_RTL;
1376  int x = pt.x - wi->pos_x;
1377  if (rtl) x = wi->current_x - x;
1378  uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
1379 
1380  return (column * number_of_rows) + line;
1381 }
1382 
1383 /* virtual */ void SmallMapWindow::OnMouseOver(Point pt, int widget)
1384 {
1385  IndustryType new_highlight = INVALID_INDUSTRYTYPE;
1386  if (widget == WID_SM_LEGEND && this->map_type == SMT_INDUSTRY) {
1387  int industry_pos = GetPositionOnLegend(pt);
1388  if (industry_pos >= 0 && industry_pos < _smallmap_industry_count) {
1389  new_highlight = _legend_from_industries[industry_pos].type;
1390  }
1391  }
1392  if (new_highlight != _smallmap_industry_highlight) {
1393  _smallmap_industry_highlight = new_highlight;
1394  this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD);
1396  this->SetDirty();
1397  }
1398 }
1399 
1400 /* virtual */ void SmallMapWindow::OnClick(Point pt, int widget, int click_count)
1401 {
1402  switch (widget) {
1403  case WID_SM_MAP: { // Map window
1404  /*
1405  * XXX: scrolling with the left mouse button is done by subsequently
1406  * clicking with the left mouse button; clicking once centers the
1407  * large map at the selected point. So by unclicking the left mouse
1408  * button here, it gets reclicked during the next inputloop, which
1409  * would make it look like the mouse is being dragged, while it is
1410  * actually being (virtually) clicked every inputloop.
1411  */
1412  _left_button_clicked = false;
1413 
1414  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1416  int sub;
1417  pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
1418  ScrollWindowTo(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, -1, w);
1419 
1420  this->SetDirty();
1421  break;
1422  }
1423 
1424  case WID_SM_ZOOM_IN:
1425  case WID_SM_ZOOM_OUT: {
1426  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1427  Point pt = { (int)wid->current_x / 2, (int)wid->current_y / 2};
1428  this->SetZoomLevel((widget == WID_SM_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1429  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1430  break;
1431  }
1432 
1433  case WID_SM_CONTOUR: // Show land contours
1434  case WID_SM_VEHICLES: // Show vehicles
1435  case WID_SM_INDUSTRIES: // Show industries
1436  case WID_SM_LINKSTATS: // Show route map
1437  case WID_SM_ROUTES: // Show transport routes
1438  case WID_SM_VEGETATION: // Show vegetation
1439  case WID_SM_OWNERS: // Show land owners
1440  this->SwitchMapType((SmallMapType)(widget - WID_SM_CONTOUR));
1441  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1442  break;
1443 
1444  case WID_SM_CENTERMAP: // Center the smallmap again
1445  this->SmallMapCenterOnCurrentPos();
1446  this->HandleButtonClick(WID_SM_CENTERMAP);
1447  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1448  break;
1449 
1450  case WID_SM_TOGGLETOWNNAME: // Toggle town names
1451  this->show_towns = !this->show_towns;
1452  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1453 
1454  this->SetDirty();
1455  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1456  break;
1457 
1458  case WID_SM_LEGEND: // Legend
1459  if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
1460  int click_pos = this->GetPositionOnLegend(pt);
1461  if (click_pos < 0) break;
1462 
1463  /* If industry type small map*/
1464  if (this->map_type == SMT_INDUSTRY) {
1465  /* If click on industries label, find right industry type and enable/disable it. */
1466  if (click_pos < _smallmap_industry_count) {
1467  this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
1468  }
1469  } else if (this->map_type == SMT_LINKSTATS) {
1470  if (click_pos < _smallmap_cargo_count) {
1471  this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
1472  this->SetOverlayCargoMask();
1473  }
1474  } else if (this->map_type == SMT_OWNER) {
1475  if (click_pos < _smallmap_company_count) {
1476  this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
1477  }
1478  }
1479  this->SetDirty();
1480  }
1481  break;
1482 
1483  case WID_SM_ENABLE_ALL:
1484  case WID_SM_DISABLE_ALL: {
1485  LegendAndColour *tbl = NULL;
1486  switch (this->map_type) {
1487  case SMT_INDUSTRY:
1489  this->BreakIndustryChainLink();
1490  break;
1491  case SMT_OWNER:
1492  tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
1493  break;
1494  case SMT_LINKSTATS:
1495  tbl = _legend_linkstats;
1496  break;
1497  default:
1498  NOT_REACHED();
1499  }
1500  for (;!tbl->end && tbl->legend != STR_LINKGRAPH_LEGEND_UNUSED; ++tbl) {
1501  tbl->show_on_map = (widget == WID_SM_ENABLE_ALL);
1502  }
1503  if (this->map_type == SMT_LINKSTATS) this->SetOverlayCargoMask();
1504  this->SetDirty();
1505  break;
1506  }
1507 
1508  case WID_SM_SHOW_HEIGHT: // Enable/disable showing of heightmap.
1510  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1511  this->SetDirty();
1512  break;
1513  }
1514 }
1515 
1524 /* virtual */ void SmallMapWindow::OnInvalidateData(int data, bool gui_scope)
1525 {
1526  if (!gui_scope) return;
1527 
1528  switch (data) {
1529  case 1:
1530  /* The owner legend has already been rebuilt. */
1531  this->ReInit();
1532  break;
1533 
1534  case 0: {
1535  extern std::bitset<NUM_INDUSTRYTYPES> _displayed_industries;
1536  if (this->map_type != SMT_INDUSTRY) this->SwitchMapType(SMT_INDUSTRY);
1537 
1538  for (int i = 0; i != _smallmap_industry_count; i++) {
1539  _legend_from_industries[i].show_on_map = _displayed_industries.test(_legend_from_industries[i].type);
1540  }
1541  break;
1542  }
1543 
1544  case 2:
1545  this->RebuildColourIndexIfNecessary();
1546  break;
1547 
1548  default: NOT_REACHED();
1549  }
1550  this->SetDirty();
1551 }
1552 
1553 /* virtual */ bool SmallMapWindow::OnRightClick(Point pt, int widget)
1554 {
1555  if (widget != WID_SM_MAP || _scrolling_viewport) return false;
1556 
1557  _scrolling_viewport = true;
1558  return true;
1559 }
1560 
1561 /* virtual */ void SmallMapWindow::OnMouseWheel(int wheel)
1562 {
1564  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1565  int cursor_x = _cursor.pos.x - this->left - wid->pos_x;
1566  int cursor_y = _cursor.pos.y - this->top - wid->pos_y;
1567  if (IsInsideMM(cursor_x, 0, wid->current_x) && IsInsideMM(cursor_y, 0, wid->current_y)) {
1568  Point pt = {cursor_x, cursor_y};
1569  this->SetZoomLevel((wheel < 0) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1570  }
1571  }
1572 }
1573 
1574 /* virtual */ void SmallMapWindow::OnRealtimeTick(uint delta_ms)
1575 {
1576  /* Update the window every now and then */
1577  if (!this->refresh.Elapsed(delta_ms)) return;
1578 
1579  if (this->map_type == SMT_LINKSTATS) {
1580  uint32 company_mask = this->GetOverlayCompanyMask();
1581  if (this->overlay->GetCompanyMask() != company_mask) {
1582  this->overlay->SetCompanyMask(company_mask);
1583  } else {
1584  this->overlay->RebuildCache();
1585  }
1586  }
1588 
1589  this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD);
1590  this->SetDirty();
1591 }
1592 
1600 void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
1601 {
1602  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1603  Point hv = InverseRemapCoords(wi->current_x * ZOOM_LVL_BASE * TILE_SIZE / 2, wi->current_y * ZOOM_LVL_BASE * TILE_SIZE / 2);
1604  hv.x *= this->zoom;
1605  hv.y *= this->zoom;
1606 
1607  if (sx < -hv.x) {
1608  sx = -hv.x;
1609  sub = 0;
1610  }
1611  if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
1612  sx = MapMaxX() * TILE_SIZE - hv.x;
1613  sub = 0;
1614  }
1615  if (sy < -hv.y) {
1616  sy = -hv.y;
1617  sub = 0;
1618  }
1619  if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
1620  sy = MapMaxY() * TILE_SIZE - hv.y;
1621  sub = 0;
1622  }
1623 
1624  this->scroll_x = sx;
1625  this->scroll_y = sy;
1626  this->subscroll = sub;
1627  if (this->map_type == SMT_LINKSTATS) this->overlay->RebuildCache();
1628 }
1629 
1630 /* virtual */ void SmallMapWindow::OnScroll(Point delta)
1631 {
1633 
1634  /* While tile is at (delta.x, delta.y)? */
1635  int sub;
1636  Point pt = this->PixelToTile(delta.x, delta.y, &sub);
1637  this->SetNewScroll(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, sub);
1638 
1639  this->SetDirty();
1640 }
1641 
1646 {
1648  Point viewport_center = InverseRemapCoords2(vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2);
1649 
1650  int sub;
1651  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1652  Point sxy = this->ComputeScroll(viewport_center.x / (int)TILE_SIZE, viewport_center.y / (int)TILE_SIZE,
1653  max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
1654  this->SetNewScroll(sxy.x, sxy.y, sub);
1655  this->SetDirty();
1656 }
1657 
1664 {
1665  int x = (st->rect.right + st->rect.left + 1) / 2;
1666  int y = (st->rect.bottom + st->rect.top + 1) / 2;
1667  Point ret = this->RemapTile(x, y);
1668 
1669  /* Same magic 3 as in DrawVehicles; that's where I got it from.
1670  * No idea what it is, but without it the result looks bad.
1671  */
1672  ret.x -= 3 + this->subscroll;
1673  return ret;
1674 }
1675 
1677 bool SmallMapWindow::show_towns = true;
1679 
1690 public:
1692  {
1693  this->smallmap_window = NULL;
1694  }
1695 
1696  virtual void SetupSmallestSize(Window *w, bool init_array)
1697  {
1698  NWidgetBase *display = this->head;
1699  NWidgetBase *bar = display->next;
1700 
1701  display->SetupSmallestSize(w, init_array);
1702  bar->SetupSmallestSize(w, init_array);
1703 
1704  this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
1705  assert(this->smallmap_window != NULL);
1706  this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
1707  this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
1708  this->fill_x = max(display->fill_x, bar->fill_x);
1709  this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
1710  this->resize_x = max(display->resize_x, bar->resize_x);
1711  this->resize_y = min(display->resize_y, bar->resize_y);
1712  }
1713 
1714  virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1715  {
1716  this->pos_x = x;
1717  this->pos_y = y;
1718  this->current_x = given_width;
1719  this->current_y = given_height;
1720 
1721  NWidgetBase *display = this->head;
1722  NWidgetBase *bar = display->next;
1723 
1724  if (sizing == ST_SMALLEST) {
1725  this->smallest_x = given_width;
1726  this->smallest_y = given_height;
1727  /* Make display and bar exactly equal to their minimal size. */
1728  display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
1729  bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
1730  }
1731 
1732  uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
1733  uint display_height = given_height - bar_height;
1734  display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
1735  bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
1736  }
1737 
1738  virtual NWidgetCore *GetWidgetFromPos(int x, int y)
1739  {
1740  if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1741  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1742  NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
1743  if (widget != NULL) return widget;
1744  }
1745  return NULL;
1746  }
1747 
1748  virtual void Draw(const Window *w)
1749  {
1750  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
1751  }
1752 };
1753 
1756  NWidget(WWT_PANEL, COLOUR_BROWN, WID_SM_MAP_BORDER),
1757  NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
1758  EndContainer(),
1759 };
1760 
1763  NWidget(WWT_PANEL, COLOUR_BROWN),
1765  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1),
1767  /* Top button row. */
1769  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_IN),
1770  SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
1771  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_CENTERMAP),
1772  SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
1773  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_BLANK),
1774  SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
1775  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_CONTOUR),
1776  SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
1777  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEHICLES),
1778  SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
1779  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_INDUSTRIES),
1780  SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
1781  EndContainer(),
1782  /* Bottom button row. */
1784  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_OUT),
1785  SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
1786  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_TOGGLETOWNNAME),
1787  SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
1788  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_LINKSTATS),
1789  SetDataTip(SPR_IMG_CARGOFLOW, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
1790  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_ROUTES),
1791  SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
1792  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEGETATION),
1793  SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
1794  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_OWNERS),
1795  SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
1796  EndContainer(),
1797  NWidget(NWID_SPACER), SetResize(0, 1),
1798  EndContainer(),
1799  EndContainer(),
1800  EndContainer(),
1801 };
1802 
1803 static NWidgetBase *SmallMapDisplay(int *biggest_index)
1804 {
1805  NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
1806 
1807  MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
1808  MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
1809  return map_display;
1810 }
1811 
1812 
1813 static const NWidgetPart _nested_smallmap_widgets[] = {
1815  NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1816  NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SM_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1817  NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1818  NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
1819  NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1820  EndContainer(),
1821  NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons.
1822  /* Bottom button row and resize box. */
1824  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SM_SELECT_BUTTONS),
1826  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL),
1827  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_DISABLE_ALL), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_NULL),
1828  NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_SM_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
1829  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1830  EndContainer(),
1831  EndContainer(),
1832  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1833  EndContainer(),
1834  EndContainer(),
1835  NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
1836  EndContainer(),
1837 };
1838 
1839 static WindowDesc _smallmap_desc(
1840  WDP_AUTO, "smallmap", 484, 314,
1842  0,
1843  _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
1844 );
1845 
1850 {
1851  AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
1852 }
1853 
1862 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
1863 {
1864  bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
1865 
1866  /* If a user scrolls to a tile (via what way what so ever) and already is on
1867  * that tile (e.g.: pressed twice), move the smallmap to that location,
1868  * so you directly see where you are on the smallmap. */
1869 
1870  if (res) return res;
1871 
1872  SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
1873  if (w != NULL) w->SmallMapCenterOnCurrentPos();
1874 
1875  return res;
1876 }
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
Definition: tile_map.h:98
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:48
SizingType
Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() ...
Definition: widget_type.h:111
void ClampToMap()
Clamp the tile area to map borders.
Definition: tilearea.cpp:123
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:105
uint8 max_heightlevel
maximum allowed heightlevel
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
Definition of stuff that is very close to a company, like the company struct itself.
virtual void OnPaint()
The window must be repainted.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition: industrytype.h:137
int virtual_left
Virtual left coordinate.
Definition: viewport_type.h:30
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:298
static TransportType GetTunnelBridgeTransportType(TileIndex t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
Data about how and where to blit pixels.
Definition: gfx_type.h:156
static const uint8 PC_WHITE
White palette colour.
Definition: gfx_func.h:210
uint8 colour
Colour of the item on the map.
Definition: smallmap_gui.h:34
Empty button as placeholder.
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:112
Button to zoom in one step.
Point pos
logical mouse position
Definition: gfx_type.h:119
The colour tables for heightmaps.
byte landscape
the landscape we&#39;re currently in
static NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
Definition: widget_type.h:1146
uint resize_x
Horizontal resize step (0 means not resizable).
Definition: widget_type.h:166
Maps accessors for stations.
void BuildOwnerLegend()
Completes the array for the owned property legend.
static const uint MAX_TILE_HEIGHT
Maximum allowed tile height.
Definition: tile_type.h:24
High level window description.
Definition: window_gui.h:168
byte map_colour
colour used for the small map
Definition: industrytype.h:123
uint32 default_colour
Default colour of the land.
void SwitchMapType(SmallMapType map_type)
Select a new map type.
Part of an industry.
Definition: tile_type.h:51
Button to select the industries view.
Baseclass for container widgets.
Definition: widget_type.h:368
static bool IsInsideMM(const T x, const uint min, const uint max)
Checks if a value is in an interval.
Definition: math_func.hpp:266
static uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the smallmap in mode "Vegetation".
TileType
The different types of tiles.
Definition: tile_type.h:42
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
static void DrawVertMapIndicator(int x, int y, int y2)
Draws vertical part of map indicator.
Definition: smallmap_gui.h:95
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Horizontal container.
Definition: widget_type.h:75
void ShowSmallMap()
Show the smallmap window.
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1111
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:53
A tile with road (or tram tracks)
Definition: tile_type.h:45
Button to select the vehicles view.
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
void DrawMapIndicators() const
Adds map indicators to the smallmap.
void RebuildColourIndexIfNecessary()
Rebuilds the colour indices used for fast access to the smallmap contour colours based on the heightl...
Specification of a cargo type.
Definition: cargotype.h:56
static const uint8 PC_TREES
Green palette colour for trees.
virtual void SetPixel(void *video, int x, int y, uint8 colour)=0
Draw a pixel with a given colour on the video-buffer.
static uint _company_to_list_pos[MAX_COMPANIES]
For connecting company ID to position in owner list (small map legend)
A snow tile that is rough underneath.
Definition: tree_map.h:58
uint GetMinLegendWidth() const
Compute minimal required width of the legends.
Definition: smallmap_gui.h:117
static const uint8 LINK_COLOURS[]
Colours for the various "load" states of links.
Definition: linkgraph_gui.h:45
IndustryType _sorted_industry_types[NUM_INDUSTRYTYPES]
Industry types sorted by name.
Panel containing the smallmap.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
int virtual_height
height << zoom
Definition: viewport_type.h:33
Pressed (inset) panel, most commonly used as combo box text area.
Definition: widget_type.h:51
static uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "Owner".
uint8 _sorted_cargo_specs_size
Number of cargo specifications stored at the _sorted_cargo_specs array (including special cargoes)...
Definition: cargotype.cpp:136
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:207
Button to disable display of all legend entries.
ZoomLevelChange
Available kinds of zoomlevel changes.
Definition: smallmap_gui.h:59
Vehicle data structure.
Definition: vehicle_base.h:212
static bool _smallmap_industry_highlight_state
State of highlight blinking.
static const uint32 _green_map_heights[]
Height map colours for the green colour scheme, ordered by height.
static bool IsInsideBS(const T x, const uint base, const uint size)
Checks if a value is between a window started at some base point.
Definition: math_func.hpp:250
Button to zoom out one step.
int GetPositionOnLegend(Point pt)
Determines the mouse position on the legend.
StationRect rect
NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions.
static SmallMapColourScheme _heightmap_schemes[]
Available colour schemes for height maps.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
#define MK(a, b)
Macro for ordinary entry of LegendAndColour.
Structure for holding relevant data for legends in small map.
Definition: smallmap_gui.h:33
static const uint8 PC_LIGHT_BLUE
Light blue palette colour.
Definition: gfx_func.h:227
Close box (at top-left of a window)
Definition: widget_type.h:69
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
static IndustryType _smallmap_industry_highlight
Highlight a specific industry type.
uint GetLegendHeight(uint num_columns) const
Compute height given a number of columns.
Definition: smallmap_gui.h:136
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Function to handling different endian machines.
A railway.
Definition: tile_type.h:44
Map accessors for tree tiles.
uint8 height
Height in tiles. Only valid for height legend entries.
Definition: smallmap_gui.h:37
Button to select the link stats view.
Caption of the window.
Colour scheme of the smallmap.
How all blitters should look like.
Definition: base.hpp:30
uint smallest_x
Smallest horizontal size of the widget in a filled window.
Definition: widget_type.h:171
virtual bool OnRightClick(Point pt, int widget)
A click with the right mouse button has been made on the window.
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
byte vehstatus
Status.
Definition: vehicle_base.h:317
static bool IsClearGround(TileIndex t, ClearGround ct)
Set the type of clear tile.
Definition: clear_map.h:73
Map moves with mouse movement on holding right mouse button, cursor position is fixed.
Definition: settings_type.h:77
bool show_on_map
For filtering industries, if true, industry is shown on the map in colour.
Definition: smallmap_gui.h:39
static const uint8 PC_FIELDS
Light brown palette colour for fields.
NWidgetContainer * MakeNWidgets(const NWidgetPart *parts, int count, int *biggest_index, NWidgetContainer *container)
Construct a nested widget tree from an array of parts.
Definition: widget.cpp:2792
static int _smallmap_industry_count
Number of used industries.
const uint32 * height_colours_base
Base table for determining the colours.
static StationType GetStationType(TileIndex t)
Get the station type of this tile.
Definition: station_map.h:45
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
StringID name
Name of this type of cargo.
Definition: cargotype.h:71
StringID name
Displayed name of the industry.
Definition: industrytype.h:124
virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
Assign size and position to the widget.
Button to enable display of all legend entries.
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition: gfx.cpp:1480
static const AndOr _smallmap_contours_andor[]
Colour masks for "Contour" and "Routes" modes.
bool _left_button_clicked
Is left mouse button clicked?
Definition: gfx.cpp:40
static const NWidgetPart _nested_smallmap_display[]
Widget parts of the smallmap display.
void SmallMapCenterOnCurrentPos()
Center the small map on the current center of the viewport.
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Functions related to (drawing on) viewports.
static void DrawHorizMapIndicator(int x, int x2, int y)
Draws horizontal part of map indicator.
Definition: smallmap_gui.h:107
bool freeform_edges
allow terraforming the tiles at the map edges
Data structure for an opened window.
Definition: window_gui.h:271
static SmallMapType map_type
Currently displayed legends.
Definition: smallmap_gui.h:65
#define MOEND()
Macro used for forcing a rebuild of the owner legend the first time it is used.
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
NWidgetBase * next
Pointer to next widget in container. Managed by parent container widget.
Definition: widget_type.h:180
static const size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:87
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3297
static const uint8 PC_GREEN
Green palette colour.
Definition: gfx_func.h:224
static const byte _vehicle_type_colours[6]
Vehicle colours in #SMT_VEHICLES mode.
static const uint32 _dark_green_map_heights[]
Height map colours for the dark green colour scheme, ordered by height.
Main window; Window numbers:
Definition: window_type.h:46
static const int NUM_NO_COMPANY_ENTRIES
Number of entries in the owner legend that are not companies.
uint8 scroll_mode
viewport scroll mode
Definition: settings_type.h:98
SmallMapType
Types of legends in the WID_SM_LEGEND widget.
Definition: smallmap_gui.h:48
Button to select the owners view.
Button to select the contour view (height map).
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition: tilearea_type.h:96
uint32 * height_colours
Cached colours for each level in a map.
bool end
This is the end of the list.
Definition: smallmap_gui.h:40
TileIndex xy
town center tile
Definition: town.h:56
Invisible widget that takes some space.
Definition: widget_type.h:79
static const uint8 PC_DARK_GREY
Dark grey palette colour.
Definition: gfx_func.h:208
static const AndOr _smallmap_vehicles_andor[]
Colour masks for "Vehicles", "Industry", and "Vegetation" modes.
Button to move smallmap center to main window center.
ViewportSign sign
Location of name sign, UpdateVirtCoord updates this.
Definition: town.h:48
GUI Timers.
IndustryType type
Type of industry. Only valid for industry entries.
Definition: smallmap_gui.h:36
#define FONT_HEIGHT_SMALL
Height of characters in the small (FS_SMALL) font.
Definition: gfx_func.h:177
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
Class managing the smallmap window.
Definition: smallmap_gui.h:45
void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
Draws one column of tiles of the small map in a certain mode onto the screen buffer, skipping the shifted rows in between.
virtual void OnRealtimeTick(uint delta_ms)
Called periodically.
size_t colour_count
The number of colours.
SoundSettings sound
sound effect settings
bool IsTileForestIndustry(TileIndex tile)
Check whether the tile is a forest.
uint smallest_y
Smallest vertical size of the widget in a filled window.
Definition: widget_type.h:172
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:175
Small map; Window numbers:
Definition: window_type.h:99
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
uint8 scrollwheel_scrolling
scrolling using the scroll wheel?
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
#define TILE_AREA_LOOP(var, ta)
A loop which iterates over the tiles of a TileArea.
Definition of base types and functions in a cross-platform compatible way.
uint min_number_of_columns
Minimal number of columns in legends.
Definition: smallmap_gui.h:74
A number of safeguards to prevent using unsafe methods.
void SetupWidgetData()
Function to set up widgets depending on the information being shown on the smallmap.
static LegendAndColour _legend_land_contours[]
Legend text giving the colours to look for on the minimap.
IndustryType type
type of industry.
Definition: industry.h:57
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
Water tile.
Definition: tile_type.h:49
uint fill_y
Vertical fill stepsize (from initial size, 0 means not resizable).
Definition: widget_type.h:165
virtual void OnMouseWheel(int wheel)
The mouse wheel has been turned.
Simple depressed panel.
Definition: widget_type.h:50
void DrawSmallMap(DrawPixelInfo *dpi) const
Draws the small map.
static uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition: math_func.hpp:316
#define MKEND()
Macro for end of list marker in arrays of LegendAndColour.
Point GetStationMiddle(const Station *st) const
Get the center of the given station as point on the screen in the smallmap window.
void SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
Initialize or change the zoom level.
#define MO(a, b)
Macro for non-company owned property entry of LegendAndColour.
uint32 GetTileColours(const TileArea &ta) const
Decide which colours to show to the user for a group of tiles.
static int _smallmap_company_count
Number of entries in the owner legend.
void SetOverlayCargoMask()
Set the link graph overlay cargo mask from the legend.
CompanyID company
Company to display. Only valid for company entries of the owner legend.
Definition: smallmap_gui.h:38
virtual void OnScroll(Point delta)
Handle the request for (viewport) scrolling.
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition: vehicle_type.h:33
Represents the covered area of e.g.
Definition: tilearea_type.h:18
Point ComputeScroll(int tx, int ty, int x, int y, int *sub)
Compute base parameters of the smallmap such that tile (tx, ty) starts at pixel (x, y).
Point RemapTile(int tile_x, int tile_y) const
Remap tile to location on this smallmap.
virtual void OnMouseOver(Point pt, int widget)
The mouse is currently moving over the window or has just moved outside of the window.
bool fix_at
mouse is moving, but cursor is not (used for scrolling)
Definition: gfx_type.h:122
Defines the data structure for constructing industry.
Definition: industrytype.h:103
static uint16 GetIndustryTypeCount(IndustryType type)
Get the count of industries for this type.
Definition: industry.h:147
int virtual_width
width << zoom
Definition: viewport_type.h:32
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
The tile has no ownership.
Definition: company_type.h:27
Baseclass for nested widgets.
Definition: widget_type.h:126
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:499
virtual void OnInit()
Notification that the nested widget tree gets initialized.
static uint _industry_to_list_pos[NUM_INDUSTRYTYPES]
For connecting industry type to position in industries list(small map legend)
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
static uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "Vehicles".
static bool show_towns
Display town names in the smallmap.
Definition: smallmap_gui.h:66
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition: factory.hpp:147
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:167
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
static ClearGround GetClearGround(TileIndex t)
Get the type of clear tile.
Definition: clear_map.h:61
Functions related to sound.
static uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "Industries".
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
a desert or snow tile, depend on landscape
Definition: tree_map.h:56
static const uint8 PC_BLACK
Black palette colour.
Definition: gfx_func.h:207
void BuildLinkStatsLegend()
Populate legend table for the link stat view.
Maximum number of companies.
Definition: company_type.h:25
Initialize nested widget tree to smallest size. Also updates current_x and current_y.
Definition: widget_type.h:112
virtual void SetupSmallestSize(Window *w, bool init_array)
Compute smallest size needed by the widget.
const SmallMapWindow * smallmap_window
Window manager instance.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
static int max_heightlevel
Currently used/cached maximum heightlevel.
Definition: smallmap_gui.h:67
static const uint8 PC_BARE_LAND
Brown palette colour for bare land.
static uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "Routes".
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
static const uint8 PC_WATER
Dark blue palette colour for water.
static uint GetClearDensity(TileIndex t)
Get the density of a non-field clear tile.
Definition: clear_map.h:85
static const int TILE_HEIGHT_STEP
One Z unit tile height difference is displayed as 50m.
Definition: viewport_func.h:21
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
uint GetNumberRowsLegend(uint columns) const
Get the number of rows in the legend from the number of columns.
void BuildLandLegend()
(Re)build the colour tables for the legends.
std::bitset< NUM_INDUSTRYTYPES > _displayed_industries
Communication from the industry chain window to the smallmap window about what industries to display...
static const uint8 PC_GREY
Grey palette colour.
Definition: gfx_func.h:209
void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
Adds vehicles to the smallmap.
Toggle button to display town names.
Transport by train.
static const uint8 PC_YELLOW
Yellow palette colour.
Definition: gfx_func.h:220
static const uint8 PC_DARK_RED
Dark red palette colour.
Definition: gfx_func.h:213
Smallmap GUI functions.
Tile got trees.
Definition: tile_type.h:47
bool ScrollMainWindowTo(int x, int y, int z, bool instant)
Scrolls the main window to given coordinates.
virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)=0
Assign size and position to the widget.
uint8 smallmap_land_colour
colour used for land and heightmap at the smallmap
Definition: settings_type.h:97
static const IndustryType INVALID_INDUSTRYTYPE
one above amount is considered invalid
Definition: industry_type.h:29
Border around the smallmap.
GUISettings gui
settings related to the GUI
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:52
void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item=0)
Select and toggle a legend item.
Invisible tiles at the SW and SE border.
Definition: tile_type.h:50
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
Base class for all vehicles.
Data structure for viewport, display of a part of the world.
Definition: viewport_type.h:24
Point InverseRemapCoords2(int x, int y, bool clamp_to_map, bool *clamped)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition: landscape.cpp:105
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
Map accessors for &#39;clear&#39; tiles.
virtual void Draw(const Window *w)
Draw the widgets of the tree.
A town owns the tile, or a town is expanding.
Definition: company_type.h:26
static const uint8 PC_ORANGE
Orange palette colour.
Definition: gfx_func.h:218
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
static TreeGround GetTreeGround(TileIndex t)
Returns the groundtype for tree tiles.
Definition: tree_map.h:89
byte colour
Company colour.
Definition: company_base.h:68
static const IndustryType NUM_INDUSTRYTYPES
total number of industry types, new and old; limited to 240 because we need some special ids like INV...
Definition: industry_type.h:28
Custom container class for displaying smallmap with a vertically resizing legend panel.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:217
static LegendAndColour _legend_linkstats[NUM_CARGO+lengthof(_linkstat_colours_in_legenda)+1]
Legend entries for the link stats view.
Vertical container.
Definition: widget_type.h:77
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
TransportType
Available types of transport.
static const uint8 PC_VERY_DARK_BROWN
Almost-black brown palette colour.
Definition: gfx_func.h:216
static const uint8 PC_RED
Red palette colour.
Definition: gfx_func.h:214
NWidgetCore * GetWidgetFromPos(int x, int y)
Retrieve a widget by its position.
Definition: widget.cpp:905
static const NWidgetPart _nested_smallmap_bar[]
Widget parts of the smallmap legend bar + image buttons.
Point PixelToTile(int px, int py, int *sub, bool add_sub=true) const
Determine the tile relative to the base tile of the smallmap, and the pixel position at that tile for...
static void BreakIndustryChainLink()
Notify the industry chain window to stop sending newly selected industries.
static uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "Contour".
static Point InverseRemapCoords(int x, int y)
Map 2D viewport or smallmap coordinate to 3D world or tile coordinate.
Definition: landscape.h:114
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
bool col_break
Perform a column break and go further at the next column.
Definition: smallmap_gui.h:41
A tile of a station.
Definition: tile_type.h:48
TownCache cache
Container for all cacheable data.
Definition: town.h:58
static uint MapMaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:113
Town data structure.
Definition: town.h:55
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Viewport moves with mouse movement on holding right mouse button, cursor position is fixed...
Definition: settings_type.h:76
#define MC(col_break)
Macro for a height legend entry with configurable colour.
Button to select the routes view.
Transport by road vehicle.
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
Functions related to OTTD&#39;s landscape.
Vehicle is not visible.
Definition: vehicle_base.h:32
static uint8 _linkstat_colours_in_legenda[]
Link stat colours shown in legenda.
Coordinates of a point in 2D.
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:89
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
static uint TileHeight(TileIndex tile)
Returns the height of a tile.
Definition: tile_map.h:31
StringID legend
String corresponding to the coloured item.
Definition: smallmap_gui.h:35
ConstructionSettings construction
construction of things in-game
Functions that have tunnels and bridges in common.
static const uint32 _violet_map_heights[]
Height map colours for the violet colour scheme, ordered by height.
virtual void SetupSmallestSize(Window *w, bool init_array)=0
Compute smallest size needed by the widget.
Base of all industries.
Button to select the vegetation view.
static const uint8 PC_ROUGH_LAND
Dark green palette colour for rough land.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES+1]
Allow room for all industries, plus a terminator entry This is required in order to have the industry...
int32 x_pos
x coordinate.
Definition: vehicle_base.h:268
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
#define FOR_ALL_VEHICLES(var)
Iterate over all vehicles.
Definition: vehicle_base.h:987
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
Base of the town class.
static const byte _tiletype_importance[]
Mapping of tile type to importance of the tile (higher number means more interesting to show)...
int virtual_top
Virtual top coordinate.
Definition: viewport_type.h:31
GameCreationSettings game_creation
settings used during the creation of a game (map)
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition: tile_type.h:43
Specification of a rectangle with absolute coordinates of all edges.
A house by a town.
Definition: tile_type.h:46
int32 y_pos
y coordinate.
Definition: vehicle_base.h:269
uint16 width_small
The width when zoomed out (small font)
Definition: viewport_type.h:52
Text is written right-to-left by default.
Definition: strings_type.h:26
static uint MapMaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:104
bool _scrolling_viewport
A viewport is being scrolled with the mouse.
Definition: window.cpp:78
static uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
Return the colour a tile would be displayed with in the small map in mode "link stats".
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition: industry.h:112
Owner
Enum for all companies/owners.
Definition: company_type.h:20
Window functions not directly related to making/drawing windows.
static bool _smallmap_show_heightmap
Show heightmap in industry and owner mode of smallmap window.
Resize the nested widget tree.
Definition: widget_type.h:113
Selection widget for the buttons present in some smallmap modes.
Find a place automatically.
Definition: window_gui.h:156
virtual NWidgetCore * GetWidgetFromPos(int x, int y)
Retrieve a widget by its position.
Show heightmap toggle button.
(Toggle) Button with image
Definition: widget_type.h:52
const CargoSpec * _sorted_cargo_specs[NUM_CARGO]
Cargo specifications sorted alphabetically by name.
Definition: cargotype.cpp:135
static bool IsTileOnWater(TileIndex t)
Tests if the tile was built on water.
Definition: water_map.h:130
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
void DrawTowns(const DrawPixelInfo *dpi) const
Adds town names to the smallmap.
ViewportData * viewport
Pointer to viewport data, if present.
Definition: window_gui.h:321
#define MS(a, b)
Macro for break marker in arrays of LegendAndColour.
static const uint8 PC_GRASS_LAND
Dark green palette colour for grass land.
An invalid company.
Definition: company_type.h:32
Industry cargoes chain; Window numbers:
Definition: window_type.h:506
Bottom panel to display smallmap legends.
The tile/execution is done by "water".
Definition: company_type.h:28
uint fill_x
Horizontal fill stepsize (from initial size, 0 means not resizable).
Definition: widget_type.h:164
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:56
void SetNewScroll(int sx, int sy, int sub)
Set new scroll_x, scroll_y, and subscroll values after limiting them such that the center of the smal...
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant)
Scrolls the viewport in a window to a given location.
Definition: viewport.cpp:2087
bool click_beep
Beep on a random selection of buttons.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
Station data structure.
Definition: station_base.h:446
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Definition: map_func.h:165
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:116
Handles drawing of links into some window.
Definition: linkgraph_gui.h:39
(Toggle) Button with text
Definition: widget_type.h:55
Vehicle is not clickable by the user (shadow vehicles).
Definition: vehicle_base.h:34
static int _smallmap_cargo_count
Number of cargos in the link stats legend.
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:284
void BuildIndustriesLegend()
Fills an array for the industries legends.