OpenTTD
smallmap_gui.cpp
Go to the documentation of this file.
1 /* $Id: smallmap_gui.cpp 27905 2017-08-31 06:48:55Z adf88 $ */
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 
27 #include "smallmap_gui.h"
28 
29 #include "table/strings.h"
30 
31 #include <bitset>
32 
33 #include "safeguards.h"
34 
38 
40 static uint8 _linkstat_colours_in_legenda[] = {0, 1, 3, 5, 7, 9, 11};
41 
42 static const int NUM_NO_COMPANY_ENTRIES = 4;
43 
44 static const uint8 PC_ROUGH_LAND = 0x52;
45 static const uint8 PC_GRASS_LAND = 0x54;
46 static const uint8 PC_BARE_LAND = 0x37;
47 static const uint8 PC_FIELDS = 0x25;
48 static const uint8 PC_TREES = 0x57;
49 static const uint8 PC_WATER = 0xCA;
50 
52 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
53 
55 #define MC(col_break) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, col_break}
56 
58 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
59 
61 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
62 
64 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
65 
70 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
71 
74  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
75  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
76  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
77  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
78  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_VEHICLES),
79 
80  /* Placeholders for the colours and heights of the legend.
81  * The following values are set at BuildLandLegend() based
82  * on each colour scheme and the maximum map height. */
83  MC(true),
84  MC(false),
85  MC(false),
86  MC(false),
87  MC(false),
88  MC(false),
89  MC(true),
90  MC(false),
91  MC(false),
92  MC(false),
93  MC(false),
94  MC(false),
95  MKEND()
96 };
97 
98 static const LegendAndColour _legend_vehicles[] = {
99  MK(PC_RED, STR_SMALLMAP_LEGENDA_TRAINS),
100  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
101  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SHIPS),
102  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_AIRCRAFT),
103 
104  MS(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
105  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
106  MKEND()
107 };
108 
109 static const LegendAndColour _legend_routes[] = {
110  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
111  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
112  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
113 
114  MS(PC_VERY_DARK_BROWN, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
115  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
116  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_BUS_STATION),
117  MK(PC_RED, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
118  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_DOCK),
119  MKEND()
120 };
121 
122 static const LegendAndColour _legend_vegetation[] = {
123  MK(PC_ROUGH_LAND, STR_SMALLMAP_LEGENDA_ROUGH_LAND),
124  MK(PC_GRASS_LAND, STR_SMALLMAP_LEGENDA_GRASS_LAND),
125  MK(PC_BARE_LAND, STR_SMALLMAP_LEGENDA_BARE_LAND),
126  MK(PC_FIELDS, STR_SMALLMAP_LEGENDA_FIELDS),
127  MK(PC_TREES, STR_SMALLMAP_LEGENDA_TREES),
128  MK(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST),
129 
130  MS(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS),
131  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_DESERT),
132  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SNOW),
133  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
134  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
135  MKEND()
136 };
137 
138 static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
139  MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER),
140  MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings.
141  MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS),
142  MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES),
143  /* The legend will be terminated the first time it is used. */
144  MOEND(),
145 };
146 
147 #undef MK
148 #undef MC
149 #undef MS
150 #undef MO
151 #undef MOEND
152 #undef MKEND
153 
164 static bool _smallmap_show_heightmap = false;
171 
176 {
177  uint j = 0;
178 
179  /* Add each name */
180  for (uint i = 0; i < NUM_INDUSTRYTYPES; i++) {
181  IndustryType ind = _sorted_industry_types[i];
182  const IndustrySpec *indsp = GetIndustrySpec(ind);
183  if (indsp->enabled) {
184  _legend_from_industries[j].legend = indsp->name;
185  _legend_from_industries[j].colour = indsp->map_colour;
186  _legend_from_industries[j].type = ind;
187  _legend_from_industries[j].show_on_map = true;
188  _legend_from_industries[j].col_break = false;
189  _legend_from_industries[j].end = false;
190 
191  /* Store widget number for this industry type. */
192  _industry_to_list_pos[ind] = j;
193  j++;
194  }
195  }
196  /* Terminate the list */
197  _legend_from_industries[j].end = true;
198 
199  /* Store number of enabled industries */
201 }
202 
207 {
208  /* Clear the legend */
209  memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
210 
211  uint i = 0;
212  for (; i < _sorted_cargo_specs_size; ++i) {
213  const CargoSpec *cs = _sorted_cargo_specs[i];
214 
215  _legend_linkstats[i].legend = cs->name;
216  _legend_linkstats[i].colour = cs->legend_colour;
217  _legend_linkstats[i].type = cs->Index();
218  _legend_linkstats[i].show_on_map = true;
219  }
220 
221  _legend_linkstats[i].col_break = true;
223 
225  _legend_linkstats[i].legend = STR_EMPTY;
227  _legend_linkstats[i].show_on_map = true;
228  }
229 
230  _legend_linkstats[_smallmap_cargo_count].legend = STR_LINKGRAPH_LEGEND_UNUSED;
231  _legend_linkstats[i - 1].legend = STR_LINKGRAPH_LEGEND_OVERLOADED;
232  _legend_linkstats[(_smallmap_cargo_count + i - 1) / 2].legend = STR_LINKGRAPH_LEGEND_SATURATED;
233  _legend_linkstats[i].end = true;
234 }
235 
236 static const LegendAndColour * const _legend_table[] = {
238  _legend_vehicles,
241  _legend_routes,
242  _legend_vegetation,
243  _legend_land_owners,
244 };
245 
246 #define MKCOLOUR(x) TO_LE32X(x)
247 
248 #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x))
249 #define MKCOLOUR_X0X0(x) (MKCOLOUR(0x01000100) * (uint)(x))
250 #define MKCOLOUR_0X0X(x) (MKCOLOUR(0x00010001) * (uint)(x))
251 #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x))
252 #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x))
253 
254 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
255 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
256 
257 #define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00)
258 #define MKCOLOUR_0FF0 MKCOLOUR_0XX0(0xFF)
259 #define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF)
260 #define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF)
261 
262 #include "table/heightmap_colours.h"
263 
266  uint32 *height_colours;
267  const uint32 *height_colours_base;
268  size_t colour_count;
269  uint32 default_colour;
270 };
271 
274  {NULL, _green_map_heights, lengthof(_green_map_heights), MKCOLOUR_XXXX(0x54)},
275  {NULL, _dark_green_map_heights, lengthof(_dark_green_map_heights), MKCOLOUR_XXXX(0x62)},
276  {NULL, _violet_map_heights, lengthof(_violet_map_heights), MKCOLOUR_XXXX(0x82)},
277 };
278 
283 {
284  /* The smallmap window has never been initialized, so no need to change the legend. */
285  if (_heightmap_schemes[0].height_colours == NULL) return;
286 
287  /*
288  * The general idea of this function is to fill the legend with an appropriate evenly spaced
289  * selection of height levels. All entries with STR_TINY_BLACK_HEIGHT are reserved for this.
290  * At the moment there are twelve of these.
291  *
292  * The table below defines up to which height level a particular delta in the legend should be
293  * used. One could opt for just dividing the maximum height and use that as delta, but that
294  * creates many "ugly" legend labels, e.g. once every 950 meter. As a result, this table will
295  * reduce the number of deltas to 7: every 100m, 200m, 300m, 500m, 750m, 1000m and 1250m. The
296  * deltas are closer together at the lower numbers because going from 12 entries to just 4, as
297  * would happen when replacing 200m and 300m by 250m, would mean the legend would be short and
298  * that might not be considered appropriate.
299  *
300  * The current method yields at least 7 legend entries and at most 12. It can be increased to
301  * 8 by adding a 150m and 400m option, but especially 150m creates ugly heights.
302  *
303  * It tries to evenly space the legend items over the two columns that are there for the legend.
304  */
305 
306  /* Table for delta; if max_height is less than the first column, use the second column as value. */
307  uint deltas[][2] = { { 24, 2 }, { 48, 4 }, { 72, 6 }, { 120, 10 }, { 180, 15 }, { 240, 20 }, { MAX_TILE_HEIGHT + 1, 25 }};
308  uint i = 0;
309  for (; _settings_game.construction.max_heightlevel >= deltas[i][0]; i++) {
310  /* Nothing to do here. */
311  }
312  uint delta = deltas[i][1];
313 
314  int total_entries = (_settings_game.construction.max_heightlevel / delta) + 1;
315  int rows = CeilDiv(total_entries, 2);
316  int j = 0;
317 
318  for (i = 0; i < lengthof(_legend_land_contours) - 1 && j < total_entries; i++) {
319  if (_legend_land_contours[i].legend != STR_TINY_BLACK_HEIGHT) continue;
320 
321  _legend_land_contours[i].col_break = j % rows == 0;
322  _legend_land_contours[i].end = false;
323  _legend_land_contours[i].height = j * delta;
324  _legend_land_contours[i].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[j * delta];
325  j++;
326  }
327  _legend_land_contours[i].end = true;
328 }
329 
334 {
335  _legend_land_owners[1].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour;
336 
337  int i = NUM_NO_COMPANY_ENTRIES;
338  const Company *c;
339  FOR_ALL_COMPANIES(c) {
340  _legend_land_owners[i].colour = _colour_gradient[c->colour][5];
341  _legend_land_owners[i].company = c->index;
342  _legend_land_owners[i].show_on_map = true;
343  _legend_land_owners[i].col_break = false;
344  _legend_land_owners[i].end = false;
345  _company_to_list_pos[c->index] = i;
346  i++;
347  }
348 
349  /* Terminate the list */
350  _legend_land_owners[i].end = true;
351 
352  /* Store maximum amount of owner legend entries. */
354 }
355 
356 struct AndOr {
357  uint32 mor;
358  uint32 mand;
359 };
360 
361 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
362 {
363  return (colour & mask->mand) | mask->mor;
364 }
365 
366 
368 static const AndOr _smallmap_contours_andor[] = {
369  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
370  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F}, // MP_RAILWAY
371  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
372  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
373  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
374  {MKCOLOUR_XXXX(PC_LIGHT_BLUE), MKCOLOUR_0000}, // MP_STATION
375  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
376  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
377  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
378  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
379  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
380  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F},
381 };
382 
384 static const AndOr _smallmap_vehicles_andor[] = {
385  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
386  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_RAILWAY
387  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
388  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
389  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
390  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_STATION
391  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
392  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
393  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
394  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
395  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
396  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
397 };
398 
400 static const byte _tiletype_importance[] = {
401  2, // MP_CLEAR
402  8, // MP_RAILWAY
403  7, // MP_ROAD
404  5, // MP_HOUSE
405  2, // MP_TREES
406  9, // MP_STATION
407  2, // MP_WATER
408  1, // MP_VOID
409  6, // MP_INDUSTRY
410  8, // MP_TUNNELBRIDGE
411  2, // MP_OBJECT
412  0,
413 };
414 
415 
422 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
423 {
424  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
425  return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[t]);
426 }
427 
435 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
436 {
437  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
438  return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
439 }
440 
448 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
449 {
450  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
451  return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[t]);
452 }
453 
461 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
462 {
463  if (t == MP_STATION) {
464  switch (GetStationType(tile)) {
465  case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
466  case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
467  case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
468  case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
469  case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
470  default: return MKCOLOUR_FFFF;
471  }
472  } else if (t == MP_RAILWAY) {
473  AndOr andor = {
474  MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
475  _smallmap_contours_andor[t].mand
476  };
477 
478  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
479  return ApplyMask(cs->default_colour, &andor);
480  }
481 
482  /* Ground colour */
483  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
484  return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
485 }
486 
494 static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
495 {
497 }
498 
499 static const uint32 _vegetation_clear_bits[] = {
500  MKCOLOUR_XXXX(PC_GRASS_LAND),
501  MKCOLOUR_XXXX(PC_ROUGH_LAND),
502  MKCOLOUR_XXXX(PC_GREY),
503  MKCOLOUR_XXXX(PC_FIELDS),
504  MKCOLOUR_XXXX(PC_LIGHT_BLUE),
505  MKCOLOUR_XXXX(PC_ORANGE),
506  MKCOLOUR_XXXX(PC_GRASS_LAND),
507  MKCOLOUR_XXXX(PC_GRASS_LAND),
508 };
509 
517 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
518 {
519  switch (t) {
520  case MP_CLEAR:
521  return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR_XXXX(PC_BARE_LAND) : _vegetation_clear_bits[GetClearGround(tile)];
522 
523  case MP_INDUSTRY:
524  return IsTileForestIndustry(tile) ? MKCOLOUR_XXXX(PC_GREEN) : MKCOLOUR_XXXX(PC_DARK_RED);
525 
526  case MP_TREES:
528  return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
529  }
530  return MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
531 
532  default:
533  return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
534  }
535 }
536 
544 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
545 {
546  Owner o;
547 
548  switch (t) {
549  case MP_INDUSTRY: return MKCOLOUR_XXXX(PC_DARK_GREY);
550  case MP_HOUSE: return MKCOLOUR_XXXX(PC_DARK_RED);
551  default: o = GetTileOwner(tile); break;
552  /* FIXME: For MP_ROAD there are multiple owners.
553  * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
554  * even if there are no ROADTYPE_ROAD bits on the tile.
555  */
556  }
557 
558  if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
559  if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
560  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
562  } else if (o == OWNER_TOWN) {
563  return MKCOLOUR_XXXX(PC_DARK_RED);
564  }
565 
566  return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
567 }
568 
570 static const byte _vehicle_type_colours[6] = {
572 };
573 
574 
577 {
579 }
580 
581 inline Point SmallMapWindow::SmallmapRemapCoords(int x, int y) const
582 {
583  Point pt;
584  pt.x = (y - x) * 2;
585  pt.y = y + x;
586  return pt;
587 }
588 
595 inline Point SmallMapWindow::RemapTile(int tile_x, int tile_y) const
596 {
597  int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
598  int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
599 
600  if (this->zoom == 1) return SmallmapRemapCoords(x_offset, y_offset);
601 
602  /* For negative offsets, round towards -inf. */
603  if (x_offset < 0) x_offset -= this->zoom - 1;
604  if (y_offset < 0) y_offset -= this->zoom - 1;
605 
606  return SmallmapRemapCoords(x_offset / this->zoom, y_offset / this->zoom);
607 }
608 
619 inline Point SmallMapWindow::PixelToTile(int px, int py, int *sub, bool add_sub) const
620 {
621  if (add_sub) px += this->subscroll; // Total horizontal offset.
622 
623  /* For each two rows down, add a x and a y tile, and
624  * For each four pixels to the right, move a tile to the right. */
625  Point pt = {((py >> 1) - (px >> 2)) * this->zoom, ((py >> 1) + (px >> 2)) * this->zoom};
626  px &= 3;
627 
628  if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
629  if (px < 2) {
630  pt.x += this->zoom;
631  px += 2;
632  } else {
633  pt.y += this->zoom;
634  px -= 2;
635  }
636  }
637 
638  *sub = px;
639  return pt;
640 }
641 
651 Point SmallMapWindow::ComputeScroll(int tx, int ty, int x, int y, int *sub)
652 {
653  assert(x >= 0 && y >= 0);
654 
655  int new_sub;
656  Point tile_xy = PixelToTile(x, y, &new_sub, false);
657  tx -= tile_xy.x;
658  ty -= tile_xy.y;
659 
660  Point scroll;
661  if (new_sub == 0) {
662  *sub = 0;
663  scroll.x = (tx + this->zoom) * TILE_SIZE;
664  scroll.y = (ty - this->zoom) * TILE_SIZE;
665  } else {
666  *sub = 4 - new_sub;
667  scroll.x = (tx + 2 * this->zoom) * TILE_SIZE;
668  scroll.y = (ty - 2 * this->zoom) * TILE_SIZE;
669  }
670  return scroll;
671 }
672 
680 {
681  static const int zoomlevels[] = {1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
682  static const int MIN_ZOOM_INDEX = 0;
683  static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
684 
685  int new_index, cur_index, sub;
686  Point tile;
687  switch (change) {
688  case ZLC_INITIALIZE:
689  cur_index = - 1; // Definitely different from new_index.
690  new_index = MIN_ZOOM_INDEX;
691  tile.x = tile.y = 0;
692  break;
693 
694  case ZLC_ZOOM_IN:
695  case ZLC_ZOOM_OUT:
696  for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
697  if (this->zoom == zoomlevels[cur_index]) break;
698  }
699  assert(cur_index <= MAX_ZOOM_INDEX);
700 
701  tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
702  new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
703  break;
704 
705  default: NOT_REACHED();
706  }
707 
708  if (new_index != cur_index) {
709  this->zoom = zoomlevels[new_index];
710  if (cur_index >= 0) {
711  Point new_tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
712  this->SetNewScroll(this->scroll_x + (tile.x - new_tile.x) * TILE_SIZE,
713  this->scroll_y + (tile.y - new_tile.y) * TILE_SIZE, sub);
714  } else if (this->map_type == SMT_LINKSTATS) {
715  this->overlay->RebuildCache();
716  }
717  this->SetWidgetDisabledState(WID_SM_ZOOM_IN, this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
718  this->SetWidgetDisabledState(WID_SM_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
719  this->SetDirty();
720  }
721 }
722 
728 inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
729 {
730  int importance = 0;
731  TileIndex tile = INVALID_TILE; // Position of the most important tile.
732  TileType et = MP_VOID; // Effective tile type at that position.
733 
734  TILE_AREA_LOOP(ti, ta) {
735  TileType ttype = GetTileType(ti);
736 
737  switch (ttype) {
738  case MP_TUNNELBRIDGE: {
740 
741  switch (tt) {
742  case TRANSPORT_RAIL: ttype = MP_RAILWAY; break;
743  case TRANSPORT_ROAD: ttype = MP_ROAD; break;
744  default: ttype = MP_WATER; break;
745  }
746  break;
747  }
748 
749  case MP_INDUSTRY:
750  /* Special handling of industries while in "Industries" smallmap view. */
751  if (this->map_type == SMT_INDUSTRY) {
752  /* If industry is allowed to be seen, use its colour on the map.
753  * This has the highest priority above any value in _tiletype_importance. */
754  IndustryType type = Industry::GetByTile(ti)->type;
755  if (_legend_from_industries[_industry_to_list_pos[type]].show_on_map) {
756  if (type == _smallmap_industry_highlight) {
757  if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE);
758  } else {
759  return GetIndustrySpec(type)->map_colour * 0x01010101;
760  }
761  }
762  /* Otherwise make it disappear */
763  ttype = IsTileOnWater(ti) ? MP_WATER : MP_CLEAR;
764  }
765  break;
766 
767  default:
768  break;
769  }
770 
771  if (_tiletype_importance[ttype] > importance) {
772  importance = _tiletype_importance[ttype];
773  tile = ti;
774  et = ttype;
775  }
776  }
777 
778  switch (this->map_type) {
779  case SMT_CONTOUR:
780  return GetSmallMapContoursPixels(tile, et);
781 
782  case SMT_VEHICLES:
783  return GetSmallMapVehiclesPixels(tile, et);
784 
785  case SMT_INDUSTRY:
786  return GetSmallMapIndustriesPixels(tile, et);
787 
788  case SMT_LINKSTATS:
789  return GetSmallMapLinkStatsPixels(tile, et);
790 
791  case SMT_ROUTES:
792  return GetSmallMapRoutesPixels(tile, et);
793 
794  case SMT_VEGETATION:
795  return GetSmallMapVegetationPixels(tile, et);
796 
797  case SMT_OWNER:
798  return GetSmallMapOwnerPixels(tile, et);
799 
800  default: NOT_REACHED();
801  }
802 }
803 
817 void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
818 {
819  void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
820  uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
821 
822  do {
823  /* Check if the tile (xc,yc) is within the map range */
824  if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
825 
826  /* Check if the dst pointer points to a pixel inside the screen buffer */
827  if (dst < _screen.dst_ptr) continue;
828  if (dst >= dst_ptr_abs_end) continue;
829 
830  /* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
831  TileArea ta;
832  if (min_xy == 1 && (xc == 0 || yc == 0)) {
833  if (this->zoom == 1) continue; // The tile area is empty, don't draw anything.
834 
835  ta = TileArea(TileXY(max(min_xy, xc), max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
836  } else {
837  ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
838  }
839  ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
840 
841  uint32 val = this->GetTileColours(ta);
842  uint8 *val8 = (uint8 *)&val;
843  int idx = max(0, -start_pos);
844  for (int pos = max(0, start_pos); pos < end_pos; pos++) {
845  blitter->SetPixel(dst, idx, 0, val8[idx]);
846  idx++;
847  }
848  /* Switch to next tile in the column */
849  } while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
850 }
851 
857 void SmallMapWindow::DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
858 {
859  const Vehicle *v;
860  FOR_ALL_VEHICLES(v) {
861  if (v->type == VEH_EFFECT) continue;
862  if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
863 
864  /* Remap into flat coordinates. */
865  Point pt = this->RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
866 
867  int y = pt.y - dpi->top;
868  if (!IsInsideMM(y, 0, dpi->height)) continue; // y is out of bounds.
869 
870  bool skip = false; // Default is to draw both pixels.
871  int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
872  if (x < 0) {
873  /* if x+1 is 0, that means we're on the very left edge,
874  * and should thus only draw a single pixel */
875  if (++x != 0) continue;
876  skip = true;
877  } else if (x >= dpi->width - 1) {
878  /* Check if we're at the very right edge, and if so draw only a single pixel */
879  if (x != dpi->width - 1) continue;
880  skip = true;
881  }
882 
883  /* Calculate pointer to pixel and the colour */
884  byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
885 
886  /* And draw either one or two pixels depending on clipping */
887  blitter->SetPixel(dpi->dst_ptr, x, y, colour);
888  if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
889  }
890 }
891 
897 {
898  const Town *t;
899  FOR_ALL_TOWNS(t) {
900  /* Remap the town coordinate */
901  Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
902  int x = pt.x - this->subscroll - (t->cache.sign.width_small >> 1);
903  int y = pt.y;
904 
905  /* Check if the town sign is within bounds */
906  if (x + t->cache.sign.width_small > dpi->left &&
907  x < dpi->left + dpi->width &&
908  y + FONT_HEIGHT_SMALL > dpi->top &&
909  y < dpi->top + dpi->height) {
910  /* And draw it. */
911  SetDParam(0, t->index);
912  DrawString(x, x + t->cache.sign.width_small, y, STR_SMALLMAP_TOWN);
913  }
914  }
915 }
916 
921 {
922  /* Find main viewport. */
924 
925  Point upper_left_smallmap_coord = TranslateXYToTileCoord(vp, vp->left, vp->top, false);
926  Point lower_right_smallmap_coord = TranslateXYToTileCoord(vp, vp->left + vp->width - 1, vp->top + vp->height - 1, false);
927 
928  Point upper_left = this->RemapTile(upper_left_smallmap_coord.x / (int)TILE_SIZE, upper_left_smallmap_coord.y / (int)TILE_SIZE);
929  upper_left.x -= this->subscroll;
930 
931  Point lower_right = this->RemapTile(lower_right_smallmap_coord.x / (int)TILE_SIZE, lower_right_smallmap_coord.y / (int)TILE_SIZE);
932  lower_right.x -= this->subscroll;
933 
934  SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
935  SmallMapWindow::DrawVertMapIndicator(lower_right.x, upper_left.y, lower_right.y);
936 
937  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, upper_left.y);
938  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, lower_right.y);
939 }
940 
953 {
955  DrawPixelInfo *old_dpi;
956 
957  old_dpi = _cur_dpi;
958  _cur_dpi = dpi;
959 
960  /* Clear it */
961  GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
962 
963  /* Which tile is displayed at (dpi->left, dpi->top)? */
964  int dx;
965  Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
966  int tile_x = this->scroll_x / (int)TILE_SIZE + tile.x;
967  int tile_y = this->scroll_y / (int)TILE_SIZE + tile.y;
968 
969  void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
970  int x = - dx - 4;
971  int y = 0;
972 
973  for (;;) {
974  /* Distance from left edge */
975  if (x >= -3) {
976  if (x >= dpi->width) break; // Exit the loop.
977 
978  int end_pos = min(dpi->width, x + 4);
979  int reps = (dpi->height - y + 1) / 2; // Number of lines.
980  if (reps > 0) {
981  this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
982  }
983  }
984 
985  if (y == 0) {
986  tile_y += this->zoom;
987  y++;
988  ptr = blitter->MoveTo(ptr, 0, 1);
989  } else {
990  tile_x -= this->zoom;
991  y--;
992  ptr = blitter->MoveTo(ptr, 0, -1);
993  }
994  ptr = blitter->MoveTo(ptr, 2, 0);
995  x += 2;
996  }
997 
998  /* Draw vehicles */
999  if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
1000 
1001  /* Draw link stat overlay */
1002  if (this->map_type == SMT_LINKSTATS) this->overlay->Draw(dpi);
1003 
1004  /* Draw town names */
1005  if (this->show_towns) this->DrawTowns(dpi);
1006 
1007  /* Draw map indicators */
1008  this->DrawMapIndicators();
1009 
1010  _cur_dpi = old_dpi;
1011 }
1012 
1017 {
1018  StringID legend_tooltip;
1019  StringID enable_all_tooltip;
1020  StringID disable_all_tooltip;
1021  int plane;
1022  switch (this->map_type) {
1023  case SMT_INDUSTRY:
1024  legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
1025  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
1026  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
1027  plane = 0;
1028  break;
1029 
1030  case SMT_OWNER:
1031  legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
1032  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
1033  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
1034  plane = 0;
1035  break;
1036 
1037  case SMT_LINKSTATS:
1038  legend_tooltip = STR_SMALLMAP_TOOLTIP_CARGO_SELECTION;
1039  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS;
1040  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_CARGOS;
1041  plane = 0;
1042  break;
1043 
1044  default:
1045  legend_tooltip = STR_NULL;
1046  enable_all_tooltip = STR_NULL;
1047  disable_all_tooltip = STR_NULL;
1048  plane = 1;
1049  break;
1050  }
1051 
1052  this->GetWidget<NWidgetCore>(WID_SM_LEGEND)->SetDataTip(STR_NULL, legend_tooltip);
1053  this->GetWidget<NWidgetCore>(WID_SM_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip);
1054  this->GetWidget<NWidgetCore>(WID_SM_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip);
1055  this->GetWidget<NWidgetStacked>(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane);
1056 }
1057 
1058 SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(FORCE_REFRESH_PERIOD)
1059 {
1061  this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1);
1062  this->InitNested(window_number);
1063  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1064 
1065  this->RebuildColourIndexIfNecessary();
1066 
1067  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1068 
1069  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1070 
1071  this->SetupWidgetData();
1072 
1073  this->SetZoomLevel(ZLC_INITIALIZE, NULL);
1074  this->SmallMapCenterOnCurrentPos();
1075  this->SetOverlayCargoMask();
1076 }
1077 
1078 SmallMapWindow::~SmallMapWindow()
1079 {
1080  delete this->overlay;
1081  this->BreakIndustryChainLink();
1082 }
1083 
1088 {
1089  /* Rebuild colour indices if necessary. */
1091 
1092  for (uint n = 0; n < lengthof(_heightmap_schemes); n++) {
1093  /* The heights go from 0 up to and including maximum. */
1094  int heights = _settings_game.construction.max_heightlevel + 1;
1095  _heightmap_schemes[n].height_colours = ReallocT<uint32>(_heightmap_schemes[n].height_colours, heights);
1096 
1097  for (int z = 0; z < heights; z++) {
1098  size_t access_index = (_heightmap_schemes[n].colour_count * z) / heights;
1099 
1100  /* Choose colour by mapping the range (0..max heightlevel) on the complete colour table. */
1101  _heightmap_schemes[n].height_colours[z] = _heightmap_schemes[n].height_colours_base[access_index];
1102  }
1103  }
1104 
1106  BuildLandLegend();
1107 }
1108 
1109 /* virtual */ void SmallMapWindow::SetStringParameters(int widget) const
1110 {
1111  switch (widget) {
1112  case WID_SM_CAPTION:
1113  SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
1114  break;
1115  }
1116 }
1117 
1118 /* virtual */ void SmallMapWindow::OnInit()
1119 {
1120  uint min_width = 0;
1121  this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
1122  this->min_number_of_fixed_rows = lengthof(_linkstat_colours_in_legenda);
1123  for (uint i = 0; i < lengthof(_legend_table); i++) {
1124  uint height = 0;
1125  uint num_columns = 1;
1126  for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
1127  StringID str;
1128  if (i == SMT_INDUSTRY) {
1129  SetDParam(0, tbl->legend);
1131  str = STR_SMALLMAP_INDUSTRY;
1132  } else if (i == SMT_LINKSTATS) {
1133  SetDParam(0, tbl->legend);
1134  str = STR_SMALLMAP_LINKSTATS;
1135  } else if (i == SMT_OWNER) {
1136  if (tbl->company != INVALID_COMPANY) {
1137  if (!Company::IsValidID(tbl->company)) {
1138  /* Rebuild the owner legend. */
1139  BuildOwnerLegend();
1140  this->OnInit();
1141  return;
1142  }
1143  /* Non-fixed legend entries for the owner view. */
1144  SetDParam(0, tbl->company);
1145  str = STR_SMALLMAP_COMPANY;
1146  } else {
1147  str = tbl->legend;
1148  }
1149  } else {
1150  if (tbl->col_break) {
1151  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1152  height = 0;
1153  num_columns++;
1154  }
1155  height++;
1156  str = tbl->legend;
1157  }
1158  min_width = max(GetStringBoundingBox(str).width, min_width);
1159  }
1160  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1161  this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
1162  }
1163 
1164  /* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
1165  this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1166 }
1167 
1168 /* virtual */ void SmallMapWindow::OnPaint()
1169 {
1170  if (this->map_type == SMT_OWNER) {
1171  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1172  if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
1173  /* Rebuild the owner legend. */
1174  BuildOwnerLegend();
1175  this->InvalidateData(1);
1176  break;
1177  }
1178  }
1179  }
1180 
1181  this->DrawWidgets();
1182 }
1183 
1184 /* virtual */ void SmallMapWindow::DrawWidget(const Rect &r, int widget) const
1185 {
1186  switch (widget) {
1187  case WID_SM_MAP: {
1188  DrawPixelInfo new_dpi;
1189  if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
1190  this->DrawSmallMap(&new_dpi);
1191  break;
1192  }
1193 
1194  case WID_SM_LEGEND: {
1195  uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
1196  uint number_of_rows = this->GetNumberRowsLegend(columns);
1197  bool rtl = _current_text_dir == TD_RTL;
1198  uint y_org = r.top + WD_FRAMERECT_TOP;
1199  uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
1200  uint y = y_org;
1201  uint i = 0; // Row counter for industry legend.
1202  uint row_height = FONT_HEIGHT_SMALL;
1203 
1204  uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
1205  uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
1206  uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
1207  uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
1208 
1209  StringID string = STR_NULL;
1210  switch (this->map_type) {
1211  case SMT_INDUSTRY:
1212  string = STR_SMALLMAP_INDUSTRY;
1213  break;
1214  case SMT_LINKSTATS:
1215  string = STR_SMALLMAP_LINKSTATS;
1216  break;
1217  case SMT_OWNER:
1218  string = STR_SMALLMAP_COMPANY;
1219  break;
1220  default:
1221  break;
1222  }
1223 
1224  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1225  if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_LINKSTATS) && i++ >= number_of_rows)) {
1226  /* Column break needed, continue at top, COLUMN_WIDTH pixels
1227  * (one "row") to the right. */
1228  x += rtl ? -(int)this->column_width : this->column_width;
1229  y = y_org;
1230  i = 1;
1231  }
1232 
1233  uint8 legend_colour = tbl->colour;
1234 
1235  switch (this->map_type) {
1236  case SMT_INDUSTRY:
1237  /* Industry name must be formatted, since it's not in tiny font in the specs.
1238  * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font */
1239  SetDParam(0, tbl->legend);
1241  if (tbl->show_on_map && tbl->type == _smallmap_industry_highlight) {
1243  }
1244  FALLTHROUGH;
1245 
1246  case SMT_LINKSTATS:
1247  SetDParam(0, tbl->legend);
1248  FALLTHROUGH;
1249 
1250  case SMT_OWNER:
1251  if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
1252  if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
1253  if (!tbl->show_on_map) {
1254  /* Simply draw the string, not the black border of the legend colour.
1255  * This will enforce the idea of the disabled item */
1256  DrawString(x + text_left, x + text_right, y, string, TC_GREY);
1257  } else {
1258  DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
1259  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
1260  }
1261  break;
1262  }
1263  FALLTHROUGH;
1264 
1265  default:
1266  if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
1267  /* Anything that is not an industry or a company is using normal process */
1268  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
1269  DrawString(x + text_left, x + text_right, y, tbl->legend);
1270  break;
1271  }
1272  GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour
1273 
1274  y += row_height;
1275  }
1276  }
1277  }
1278 }
1279 
1285 {
1286  this->RaiseWidget(this->map_type + WID_SM_CONTOUR);
1287  this->map_type = map_type;
1288  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1289 
1290  this->SetupWidgetData();
1291 
1292  if (map_type == SMT_LINKSTATS) this->overlay->RebuildCache();
1293  if (map_type != SMT_INDUSTRY) this->BreakIndustryChainLink();
1294  this->SetDirty();
1295 }
1296 
1305 inline uint SmallMapWindow::GetNumberRowsLegend(uint columns) const
1306 {
1307  /* Reserve one column for link colours */
1308  uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
1309  uint num_rows_others = CeilDiv(max(_smallmap_industry_count, _smallmap_company_count), columns);
1310  return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
1311 }
1312 
1324 void SmallMapWindow::SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item)
1325 {
1326  if (_ctrl_pressed) {
1327  /* Disable all, except the clicked one */
1328  bool changes = false;
1329  for (int i = begin_legend_item; i != end_legend_item; i++) {
1330  bool new_state = (i == click_pos);
1331  if (legend[i].show_on_map != new_state) {
1332  changes = true;
1333  legend[i].show_on_map = new_state;
1334  }
1335  }
1336  if (!changes) {
1337  /* Nothing changed? Then show all (again). */
1338  for (int i = begin_legend_item; i != end_legend_item; i++) {
1339  legend[i].show_on_map = true;
1340  }
1341  }
1342  } else {
1343  legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
1344  }
1345 
1346  if (this->map_type == SMT_INDUSTRY) this->BreakIndustryChainLink();
1347 }
1348 
1353 {
1354  uint32 cargo_mask = 0;
1355  for (int i = 0; i != _smallmap_cargo_count; ++i) {
1356  if (_legend_linkstats[i].show_on_map) SetBit(cargo_mask, _legend_linkstats[i].type);
1357  }
1358  this->overlay->SetCargoMask(cargo_mask);
1359 }
1360 
1367 {
1368  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_LEGEND);
1369  uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
1370  uint columns = this->GetNumberColumnsLegend(wi->current_x);
1371  uint number_of_rows = this->GetNumberRowsLegend(columns);
1372  if (line >= number_of_rows) return -1;
1373 
1374  bool rtl = _current_text_dir == TD_RTL;
1375  int x = pt.x - wi->pos_x;
1376  if (rtl) x = wi->current_x - x;
1377  uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
1378 
1379  return (column * number_of_rows) + line;
1380 }
1381 
1382 /* virtual */ void SmallMapWindow::OnMouseOver(Point pt, int widget)
1383 {
1384  IndustryType new_highlight = INVALID_INDUSTRYTYPE;
1385  if (widget == WID_SM_LEGEND && this->map_type == SMT_INDUSTRY) {
1386  int industry_pos = GetPositionOnLegend(pt);
1387  if (industry_pos >= 0 && industry_pos < _smallmap_industry_count) {
1388  new_highlight = _legend_from_industries[industry_pos].type;
1389  }
1390  }
1391  if (new_highlight != _smallmap_industry_highlight) {
1392  _smallmap_industry_highlight = new_highlight;
1393  this->refresh = _smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD;
1395  this->SetDirty();
1396  }
1397 }
1398 
1399 /* virtual */ void SmallMapWindow::OnClick(Point pt, int widget, int click_count)
1400 {
1401  switch (widget) {
1402  case WID_SM_MAP: { // Map window
1403  /*
1404  * XXX: scrolling with the left mouse button is done by subsequently
1405  * clicking with the left mouse button; clicking once centers the
1406  * large map at the selected point. So by unclicking the left mouse
1407  * button here, it gets reclicked during the next inputloop, which
1408  * would make it look like the mouse is being dragged, while it is
1409  * actually being (virtually) clicked every inputloop.
1410  */
1411  _left_button_clicked = false;
1412 
1413  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1415  int sub;
1416  pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
1417  ScrollWindowTo(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, -1, w);
1418 
1419  this->SetDirty();
1420  break;
1421  }
1422 
1423  case WID_SM_ZOOM_IN:
1424  case WID_SM_ZOOM_OUT: {
1425  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1426  Point pt = { (int)wid->current_x / 2, (int)wid->current_y / 2};
1427  this->SetZoomLevel((widget == WID_SM_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1428  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1429  break;
1430  }
1431 
1432  case WID_SM_CONTOUR: // Show land contours
1433  case WID_SM_VEHICLES: // Show vehicles
1434  case WID_SM_INDUSTRIES: // Show industries
1435  case WID_SM_LINKSTATS: // Show route map
1436  case WID_SM_ROUTES: // Show transport routes
1437  case WID_SM_VEGETATION: // Show vegetation
1438  case WID_SM_OWNERS: // Show land owners
1439  this->SwitchMapType((SmallMapType)(widget - WID_SM_CONTOUR));
1440  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1441  break;
1442 
1443  case WID_SM_CENTERMAP: // Center the smallmap again
1444  this->SmallMapCenterOnCurrentPos();
1445  this->HandleButtonClick(WID_SM_CENTERMAP);
1446  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1447  break;
1448 
1449  case WID_SM_TOGGLETOWNNAME: // Toggle town names
1450  this->show_towns = !this->show_towns;
1451  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1452 
1453  this->SetDirty();
1454  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1455  break;
1456 
1457  case WID_SM_LEGEND: // Legend
1458  if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
1459  int click_pos = this->GetPositionOnLegend(pt);
1460  if (click_pos < 0) break;
1461 
1462  /* If industry type small map*/
1463  if (this->map_type == SMT_INDUSTRY) {
1464  /* If click on industries label, find right industry type and enable/disable it. */
1465  if (click_pos < _smallmap_industry_count) {
1466  this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
1467  }
1468  } else if (this->map_type == SMT_LINKSTATS) {
1469  if (click_pos < _smallmap_cargo_count) {
1470  this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
1471  this->SetOverlayCargoMask();
1472  }
1473  } else if (this->map_type == SMT_OWNER) {
1474  if (click_pos < _smallmap_company_count) {
1475  this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
1476  }
1477  }
1478  this->SetDirty();
1479  }
1480  break;
1481 
1482  case WID_SM_ENABLE_ALL:
1483  case WID_SM_DISABLE_ALL: {
1484  LegendAndColour *tbl = NULL;
1485  switch (this->map_type) {
1486  case SMT_INDUSTRY:
1488  this->BreakIndustryChainLink();
1489  break;
1490  case SMT_OWNER:
1491  tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
1492  break;
1493  case SMT_LINKSTATS:
1494  tbl = _legend_linkstats;
1495  break;
1496  default:
1497  NOT_REACHED();
1498  }
1499  for (;!tbl->end && tbl->legend != STR_LINKGRAPH_LEGEND_UNUSED; ++tbl) {
1500  tbl->show_on_map = (widget == WID_SM_ENABLE_ALL);
1501  }
1502  if (this->map_type == SMT_LINKSTATS) this->SetOverlayCargoMask();
1503  this->SetDirty();
1504  break;
1505  }
1506 
1507  case WID_SM_SHOW_HEIGHT: // Enable/disable showing of heightmap.
1509  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1510  this->SetDirty();
1511  break;
1512  }
1513 }
1514 
1523 /* virtual */ void SmallMapWindow::OnInvalidateData(int data, bool gui_scope)
1524 {
1525  if (!gui_scope) return;
1526 
1527  switch (data) {
1528  case 1:
1529  /* The owner legend has already been rebuilt. */
1530  this->ReInit();
1531  break;
1532 
1533  case 0: {
1534  extern std::bitset<NUM_INDUSTRYTYPES> _displayed_industries;
1535  if (this->map_type != SMT_INDUSTRY) this->SwitchMapType(SMT_INDUSTRY);
1536 
1537  for (int i = 0; i != _smallmap_industry_count; i++) {
1538  _legend_from_industries[i].show_on_map = _displayed_industries.test(_legend_from_industries[i].type);
1539  }
1540  break;
1541  }
1542 
1543  case 2:
1544  this->RebuildColourIndexIfNecessary();
1545  break;
1546 
1547  default: NOT_REACHED();
1548  }
1549  this->SetDirty();
1550 }
1551 
1552 /* virtual */ bool SmallMapWindow::OnRightClick(Point pt, int widget)
1553 {
1554  if (widget != WID_SM_MAP || _scrolling_viewport) return false;
1555 
1556  _scrolling_viewport = true;
1557  return true;
1558 }
1559 
1560 /* virtual */ void SmallMapWindow::OnMouseWheel(int wheel)
1561 {
1563  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1564  int cursor_x = _cursor.pos.x - this->left - wid->pos_x;
1565  int cursor_y = _cursor.pos.y - this->top - wid->pos_y;
1566  if (IsInsideMM(cursor_x, 0, wid->current_x) && IsInsideMM(cursor_y, 0, wid->current_y)) {
1567  Point pt = {cursor_x, cursor_y};
1568  this->SetZoomLevel((wheel < 0) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1569  }
1570  }
1571 }
1572 
1573 /* virtual */ void SmallMapWindow::OnTick()
1574 {
1575  /* Update the window every now and then */
1576  if (--this->refresh != 0) return;
1577 
1578  if (this->map_type == SMT_LINKSTATS) {
1579  uint32 company_mask = this->GetOverlayCompanyMask();
1580  if (this->overlay->GetCompanyMask() != company_mask) {
1581  this->overlay->SetCompanyMask(company_mask);
1582  } else {
1583  this->overlay->RebuildCache();
1584  }
1585  }
1587 
1588  this->refresh = _smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD;
1589  this->SetDirty();
1590 }
1591 
1599 void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
1600 {
1601  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1602  Point hv = InverseRemapCoords(wi->current_x * ZOOM_LVL_BASE * TILE_SIZE / 2, wi->current_y * ZOOM_LVL_BASE * TILE_SIZE / 2);
1603  hv.x *= this->zoom;
1604  hv.y *= this->zoom;
1605 
1606  if (sx < -hv.x) {
1607  sx = -hv.x;
1608  sub = 0;
1609  }
1610  if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
1611  sx = MapMaxX() * TILE_SIZE - hv.x;
1612  sub = 0;
1613  }
1614  if (sy < -hv.y) {
1615  sy = -hv.y;
1616  sub = 0;
1617  }
1618  if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
1619  sy = MapMaxY() * TILE_SIZE - hv.y;
1620  sub = 0;
1621  }
1622 
1623  this->scroll_x = sx;
1624  this->scroll_y = sy;
1625  this->subscroll = sub;
1626  if (this->map_type == SMT_LINKSTATS) this->overlay->RebuildCache();
1627 }
1628 
1629 /* virtual */ void SmallMapWindow::OnScroll(Point delta)
1630 {
1631  _cursor.fix_at = true;
1632 
1633  /* While tile is at (delta.x, delta.y)? */
1634  int sub;
1635  Point pt = this->PixelToTile(delta.x, delta.y, &sub);
1636  this->SetNewScroll(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, sub);
1637 
1638  this->SetDirty();
1639 }
1640 
1645 {
1647  Point viewport_center = TranslateXYToTileCoord(vp, vp->left + vp->width / 2, vp->top + vp->height / 2);
1648 
1649  int sub;
1650  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1651  Point sxy = this->ComputeScroll(viewport_center.x / (int)TILE_SIZE, viewport_center.y / (int)TILE_SIZE,
1652  max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
1653  this->SetNewScroll(sxy.x, sxy.y, sub);
1654  this->SetDirty();
1655 }
1656 
1663 {
1664  int x = (st->rect.right + st->rect.left + 1) / 2;
1665  int y = (st->rect.bottom + st->rect.top + 1) / 2;
1666  Point ret = this->RemapTile(x, y);
1667 
1668  /* Same magic 3 as in DrawVehicles; that's where I got it from.
1669  * No idea what it is, but without it the result looks bad.
1670  */
1671  ret.x -= 3 + this->subscroll;
1672  return ret;
1673 }
1674 
1676 bool SmallMapWindow::show_towns = true;
1678 
1689 public:
1691  {
1692  this->smallmap_window = NULL;
1693  }
1694 
1695  virtual void SetupSmallestSize(Window *w, bool init_array)
1696  {
1697  NWidgetBase *display = this->head;
1698  NWidgetBase *bar = display->next;
1699 
1700  display->SetupSmallestSize(w, init_array);
1701  bar->SetupSmallestSize(w, init_array);
1702 
1703  this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
1704  assert(this->smallmap_window != NULL);
1705  this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
1706  this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
1707  this->fill_x = max(display->fill_x, bar->fill_x);
1708  this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
1709  this->resize_x = max(display->resize_x, bar->resize_x);
1710  this->resize_y = min(display->resize_y, bar->resize_y);
1711  }
1712 
1713  virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1714  {
1715  this->pos_x = x;
1716  this->pos_y = y;
1717  this->current_x = given_width;
1718  this->current_y = given_height;
1719 
1720  NWidgetBase *display = this->head;
1721  NWidgetBase *bar = display->next;
1722 
1723  if (sizing == ST_SMALLEST) {
1724  this->smallest_x = given_width;
1725  this->smallest_y = given_height;
1726  /* Make display and bar exactly equal to their minimal size. */
1727  display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
1728  bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
1729  }
1730 
1731  uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
1732  uint display_height = given_height - bar_height;
1733  display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
1734  bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
1735  }
1736 
1737  virtual NWidgetCore *GetWidgetFromPos(int x, int y)
1738  {
1739  if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1740  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1741  NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
1742  if (widget != NULL) return widget;
1743  }
1744  return NULL;
1745  }
1746 
1747  virtual void Draw(const Window *w)
1748  {
1749  for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
1750  }
1751 };
1752 
1755  NWidget(WWT_PANEL, COLOUR_BROWN, WID_SM_MAP_BORDER),
1756  NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
1757  EndContainer(),
1758 };
1759 
1762  NWidget(WWT_PANEL, COLOUR_BROWN),
1764  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1),
1766  /* Top button row. */
1768  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_IN),
1769  SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
1770  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_CENTERMAP),
1771  SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
1772  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_BLANK),
1773  SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
1774  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_CONTOUR),
1775  SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
1776  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEHICLES),
1777  SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
1778  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_INDUSTRIES),
1779  SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
1780  EndContainer(),
1781  /* Bottom button row. */
1783  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_OUT),
1784  SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
1785  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_TOGGLETOWNNAME),
1786  SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
1787  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_LINKSTATS),
1788  SetDataTip(SPR_IMG_CARGOFLOW, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
1789  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_ROUTES),
1790  SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
1791  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEGETATION),
1792  SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
1793  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_OWNERS),
1794  SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
1795  EndContainer(),
1796  NWidget(NWID_SPACER), SetResize(0, 1),
1797  EndContainer(),
1798  EndContainer(),
1799  EndContainer(),
1800 };
1801 
1802 static NWidgetBase *SmallMapDisplay(int *biggest_index)
1803 {
1804  NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
1805 
1806  MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
1807  MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
1808  return map_display;
1809 }
1810 
1811 
1812 static const NWidgetPart _nested_smallmap_widgets[] = {
1814  NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1815  NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SM_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1816  NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1817  NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
1818  NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1819  EndContainer(),
1820  NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons.
1821  /* Bottom button row and resize box. */
1823  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SM_SELECT_BUTTONS),
1825  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL),
1826  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_DISABLE_ALL), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_NULL),
1827  NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_SM_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
1828  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1829  EndContainer(),
1830  EndContainer(),
1831  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1832  EndContainer(),
1833  EndContainer(),
1834  NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
1835  EndContainer(),
1836 };
1837 
1838 static WindowDesc _smallmap_desc(
1839  WDP_AUTO, "smallmap", 484, 314,
1841  0,
1842  _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
1843 );
1844 
1849 {
1850  AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
1851 }
1852 
1861 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
1862 {
1863  bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
1864 
1865  /* If a user scrolls to a tile (via what way what so ever) and already is on
1866  * that tile (e.g.: pressed twice), move the smallmap to that location,
1867  * so you directly see where you are on the smallmap. */
1868 
1869  if (res) return res;
1870 
1871  SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
1872  if (w != NULL) w->SmallMapCenterOnCurrentPos();
1873 
1874  return res;
1875 }
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
Definition: tile_map.h:89
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:135
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:296
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:33
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:121
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.
int height
Screen height of the viewport.
Definition: viewport_type.h:28
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:94
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:1105
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.
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:116
static const uint8 LINK_COLOURS[]
Colours for the various "load" states of links.
Definition: linkgraph_gui.h:44
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
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:58
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:32
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:135
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:36
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 void OnTick()
Called once per (game) tick.
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
bool show_on_map
For filtering industries, if true, industry is shown on the map in colour.
Definition: smallmap_gui.h:38
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:122
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:106
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:64
#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:3238
static const uint8 PC_GREEN
Green palette colour.
Definition: gfx_func.h:224
Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y, bool clamp_to_map)
Translate screen coordinate in a viewport to a tile coordinate.
Definition: viewport.cpp:405
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.
SmallMapType
Types of legends in the WID_SM_LEGEND widget.
Definition: smallmap_gui.h:47
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:39
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
IndustryType type
Type of industry. Only valid for industry entries.
Definition: smallmap_gui.h:35
#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:44
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.
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:171
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:73
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:55
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:37
virtual void OnScroll(Point delta)
Handle the request for (viewport) scrolling.
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition: vehicle_type.h:31
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:101
static uint16 GetIndustryTypeCount(IndustryType type)
Get the count of industries for this type.
Definition: industry.h:129
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:65
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:66
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.
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
static uint GetClearDensity(TileIndex t)
Get the density of a non-field clear tile.
Definition: clear_map.h:85
int left
Screen coordinate left egde of the viewport.
Definition: viewport_type.h:25
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:88
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
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:112
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:40
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.
#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:34
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:986
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)...
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:75
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:94
Owner
Enum for all companies/owners.
Definition: company_type.h:20
Window functions not directly related to making/drawing windows.
int top
Screen coordinate top edge of the viewport.
Definition: viewport_type.h:26
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:54
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:2222
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:38
(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
int width
Screen width of the viewport.
Definition: viewport_type.h:27
void BuildIndustriesLegend()
Fills an array for the industries legends.