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