OpenTTD
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 
43 static const uint8 PC_ROUGH_LAND = 0x52;
44 static const uint8 PC_GRASS_LAND = 0x54;
45 static const uint8 PC_BARE_LAND = 0x37;
46 static const uint8 PC_FIELDS = 0x25;
47 static const uint8 PC_TREES = 0x57;
48 static const uint8 PC_WATER = 0xC9;
49 
51 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
52 
54 #define MC(col_break) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, col_break}
55 
57 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
58 
60 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
61 
63 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
64 
69 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
70 
73  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
74  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
75  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
76  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
77  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_VEHICLES),
78 
79  /* Placeholders for the colours and heights of the legend.
80  * The following values are set at BuildLandLegend() based
81  * on each colour scheme and the maximum map height. */
82  MC(true),
83  MC(false),
84  MC(false),
85  MC(false),
86  MC(false),
87  MC(false),
88  MC(true),
89  MC(false),
90  MC(false),
91  MC(false),
92  MC(false),
93  MC(false),
94  MKEND()
95 };
96 
97 static const LegendAndColour _legend_vehicles[] = {
98  MK(PC_RED, STR_SMALLMAP_LEGENDA_TRAINS),
99  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
100  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SHIPS),
101  MK(PC_WHITE, STR_SMALLMAP_LEGENDA_AIRCRAFT),
102 
103  MS(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
104  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
105  MKEND()
106 };
107 
108 static const LegendAndColour _legend_routes[] = {
109  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
110  MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
111  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
112 
113  MS(PC_VERY_DARK_BROWN, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
114  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
115  MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_BUS_STATION),
116  MK(PC_RED, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
117  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_DOCK),
118  MKEND()
119 };
120 
121 static const LegendAndColour _legend_vegetation[] = {
122  MK(PC_ROUGH_LAND, STR_SMALLMAP_LEGENDA_ROUGH_LAND),
123  MK(PC_GRASS_LAND, STR_SMALLMAP_LEGENDA_GRASS_LAND),
124  MK(PC_BARE_LAND, STR_SMALLMAP_LEGENDA_BARE_LAND),
125  MK(PC_FIELDS, STR_SMALLMAP_LEGENDA_FIELDS),
126  MK(PC_TREES, STR_SMALLMAP_LEGENDA_TREES),
127  MK(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST),
128 
129  MS(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS),
130  MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_DESERT),
131  MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SNOW),
132  MK(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
133  MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
134  MKEND()
135 };
136 
137 static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
138  MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER),
139  MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER), // This colour will vary depending on settings.
140  MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS),
141  MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES),
142  /* The legend will be terminated the first time it is used. */
143  MOEND(),
144 };
145 
146 #undef MK
147 #undef MC
148 #undef MS
149 #undef MO
150 #undef MOEND
151 #undef MKEND
152 
163 static bool _smallmap_show_heightmap = false;
170 
175 {
176  uint j = 0;
177 
178  /* Add each name */
179  for (IndustryType ind : _sorted_industry_types) {
180  const IndustrySpec *indsp = GetIndustrySpec(ind);
181  if (indsp->enabled) {
182  _legend_from_industries[j].legend = indsp->name;
183  _legend_from_industries[j].colour = indsp->map_colour;
184  _legend_from_industries[j].type = ind;
185  _legend_from_industries[j].show_on_map = true;
186  _legend_from_industries[j].col_break = false;
187  _legend_from_industries[j].end = false;
188 
189  /* Store widget number for this industry type. */
190  _industry_to_list_pos[ind] = j;
191  j++;
192  }
193  }
194  /* Terminate the list */
195  _legend_from_industries[j].end = true;
196 
197  /* Store number of enabled industries */
199 }
200 
205 {
206  /* Clear the legend */
207  memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
208 
209  uint i = 0;
210  for (; i < _sorted_cargo_specs.size(); ++i) {
211  const CargoSpec *cs = _sorted_cargo_specs[i];
212 
213  _legend_linkstats[i].legend = cs->name;
214  _legend_linkstats[i].colour = cs->legend_colour;
215  _legend_linkstats[i].type = cs->Index();
216  _legend_linkstats[i].show_on_map = true;
217  }
218 
219  _legend_linkstats[i].col_break = true;
221 
223  _legend_linkstats[i].legend = STR_EMPTY;
225  _legend_linkstats[i].show_on_map = true;
226  }
227 
228  _legend_linkstats[_smallmap_cargo_count].legend = STR_LINKGRAPH_LEGEND_UNUSED;
229  _legend_linkstats[i - 1].legend = STR_LINKGRAPH_LEGEND_OVERLOADED;
230  _legend_linkstats[(_smallmap_cargo_count + i - 1) / 2].legend = STR_LINKGRAPH_LEGEND_SATURATED;
231  _legend_linkstats[i].end = true;
232 }
233 
234 static const LegendAndColour * const _legend_table[] = {
236  _legend_vehicles,
239  _legend_routes,
240  _legend_vegetation,
241  _legend_land_owners,
242 };
243 
244 #define MKCOLOUR(x) TO_LE32X(x)
245 
246 #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x))
247 #define MKCOLOUR_X0X0(x) (MKCOLOUR(0x01000100) * (uint)(x))
248 #define MKCOLOUR_0X0X(x) (MKCOLOUR(0x00010001) * (uint)(x))
249 #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x))
250 #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x))
251 
252 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
253 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
254 
255 #define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00)
256 #define MKCOLOUR_0FF0 MKCOLOUR_0XX0(0xFF)
257 #define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF)
258 #define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF)
259 
260 #include "table/heightmap_colours.h"
261 
264  uint32 *height_colours;
265  const uint32 *height_colours_base;
266  size_t colour_count;
267  uint32 default_colour;
268 };
269 
272  {nullptr, _green_map_heights, lengthof(_green_map_heights), MKCOLOUR_XXXX(0x54)},
273  {nullptr, _dark_green_map_heights, lengthof(_dark_green_map_heights), MKCOLOUR_XXXX(0x62)},
274  {nullptr, _violet_map_heights, lengthof(_violet_map_heights), MKCOLOUR_XXXX(0x81)},
275 };
276 
281 {
282  /* The smallmap window has never been initialized, so no need to change the legend. */
283  if (_heightmap_schemes[0].height_colours == nullptr) return;
284 
285  /*
286  * The general idea of this function is to fill the legend with an appropriate evenly spaced
287  * selection of height levels. All entries with STR_TINY_BLACK_HEIGHT are reserved for this.
288  * At the moment there are twelve of these.
289  *
290  * The table below defines up to which height level a particular delta in the legend should be
291  * used. One could opt for just dividing the maximum height and use that as delta, but that
292  * creates many "ugly" legend labels, e.g. once every 950 meter. As a result, this table will
293  * reduce the number of deltas to 7: every 100m, 200m, 300m, 500m, 750m, 1000m and 1250m. The
294  * deltas are closer together at the lower numbers because going from 12 entries to just 4, as
295  * would happen when replacing 200m and 300m by 250m, would mean the legend would be short and
296  * that might not be considered appropriate.
297  *
298  * The current method yields at least 7 legend entries and at most 12. It can be increased to
299  * 8 by adding a 150m and 400m option, but especially 150m creates ugly heights.
300  *
301  * It tries to evenly space the legend items over the two columns that are there for the legend.
302  */
303 
304  /* Table for delta; if max_height is less than the first column, use the second column as value. */
305  uint deltas[][2] = { { 24, 2 }, { 48, 4 }, { 72, 6 }, { 120, 10 }, { 180, 15 }, { 240, 20 }, { MAX_TILE_HEIGHT + 1, 25 }};
306  uint i = 0;
307  for (; _settings_game.construction.max_heightlevel >= deltas[i][0]; i++) {
308  /* Nothing to do here. */
309  }
310  uint delta = deltas[i][1];
311 
312  int total_entries = (_settings_game.construction.max_heightlevel / delta) + 1;
313  int rows = CeilDiv(total_entries, 2);
314  int j = 0;
315 
316  for (i = 0; i < lengthof(_legend_land_contours) - 1 && j < total_entries; i++) {
317  if (_legend_land_contours[i].legend != STR_TINY_BLACK_HEIGHT) continue;
318 
319  _legend_land_contours[i].col_break = j % rows == 0;
320  _legend_land_contours[i].end = false;
321  _legend_land_contours[i].height = j * delta;
322  _legend_land_contours[i].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[j * delta];
323  j++;
324  }
325  _legend_land_contours[i].end = true;
326 }
327 
332 {
333  _legend_land_owners[1].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour;
334 
335  int i = NUM_NO_COMPANY_ENTRIES;
336  for (const Company *c : Company::Iterate()) {
337  _legend_land_owners[i].colour = _colour_gradient[c->colour][5];
338  _legend_land_owners[i].company = c->index;
339  _legend_land_owners[i].show_on_map = true;
340  _legend_land_owners[i].col_break = false;
341  _legend_land_owners[i].end = false;
342  _company_to_list_pos[c->index] = i;
343  i++;
344  }
345 
346  /* Terminate the list */
347  _legend_land_owners[i].end = true;
348 
349  /* Store maximum amount of owner legend entries. */
351 }
352 
353 struct AndOr {
354  uint32 mor;
355  uint32 mand;
356 };
357 
358 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
359 {
360  return (colour & mask->mand) | mask->mor;
361 }
362 
363 
365 static const AndOr _smallmap_contours_andor[] = {
366  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
367  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F}, // MP_RAILWAY
368  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
369  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
370  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
371  {MKCOLOUR_XXXX(PC_LIGHT_BLUE), MKCOLOUR_0000}, // MP_STATION
372  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
373  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
374  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
375  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
376  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
377  {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F},
378 };
379 
381 static const AndOr _smallmap_vehicles_andor[] = {
382  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_CLEAR
383  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_RAILWAY
384  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_ROAD
385  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_HOUSE
386  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TREES
387  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F}, // MP_STATION
388  {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000}, // MP_WATER
389  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_VOID
390  {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000}, // MP_INDUSTRY
391  {MKCOLOUR_0000 , MKCOLOUR_FFFF}, // MP_TUNNELBRIDGE
392  {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F}, // MP_OBJECT
393  {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
394 };
395 
397 static const byte _tiletype_importance[] = {
398  2, // MP_CLEAR
399  8, // MP_RAILWAY
400  7, // MP_ROAD
401  5, // MP_HOUSE
402  2, // MP_TREES
403  9, // MP_STATION
404  2, // MP_WATER
405  1, // MP_VOID
406  6, // MP_INDUSTRY
407  8, // MP_TUNNELBRIDGE
408  2, // MP_OBJECT
409  0,
410 };
411 
412 
419 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
420 {
421  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
422  return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[t]);
423 }
424 
432 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
433 {
434  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
435  return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
436 }
437 
445 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
446 {
447  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
448  return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[t]);
449 }
450 
458 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
459 {
460  switch (t) {
461  case MP_STATION:
462  switch (GetStationType(tile)) {
463  case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
464  case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
465  case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
466  case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
467  case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
468  default: return MKCOLOUR_FFFF;
469  }
470 
471  case MP_RAILWAY: {
472  AndOr andor = {
473  MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
474  _smallmap_contours_andor[t].mand
475  };
476 
477  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
478  return ApplyMask(cs->default_colour, &andor);
479  }
480 
481  case MP_ROAD: {
482  const RoadTypeInfo *rti = nullptr;
483  if (GetRoadTypeRoad(tile) != INVALID_ROADTYPE) {
484  rti = GetRoadTypeInfo(GetRoadTypeRoad(tile));
485  } else {
486  rti = GetRoadTypeInfo(GetRoadTypeTram(tile));
487  }
488  if (rti != nullptr) {
489  AndOr andor = {
490  MKCOLOUR_0XX0(rti->map_colour),
491  _smallmap_contours_andor[t].mand
492  };
493 
494  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
495  return ApplyMask(cs->default_colour, &andor);
496  }
497  FALLTHROUGH;
498  }
499 
500  default:
501  /* Ground colour */
502  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
503  return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
504  }
505 }
506 
514 static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
515 {
517 }
518 
519 static const uint32 _vegetation_clear_bits[] = {
520  MKCOLOUR_XXXX(PC_GRASS_LAND),
521  MKCOLOUR_XXXX(PC_ROUGH_LAND),
522  MKCOLOUR_XXXX(PC_GREY),
523  MKCOLOUR_XXXX(PC_FIELDS),
524  MKCOLOUR_XXXX(PC_LIGHT_BLUE),
525  MKCOLOUR_XXXX(PC_ORANGE),
526  MKCOLOUR_XXXX(PC_GRASS_LAND),
527  MKCOLOUR_XXXX(PC_GRASS_LAND),
528 };
529 
537 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
538 {
539  switch (t) {
540  case MP_CLEAR:
541  return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR_XXXX(PC_BARE_LAND) : _vegetation_clear_bits[GetClearGround(tile)];
542 
543  case MP_INDUSTRY:
544  return IsTileForestIndustry(tile) ? MKCOLOUR_XXXX(PC_GREEN) : MKCOLOUR_XXXX(PC_DARK_RED);
545 
546  case MP_TREES:
548  return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
549  }
550  return MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
551 
552  default:
553  return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
554  }
555 }
556 
564 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
565 {
566  Owner o;
567 
568  switch (t) {
569  case MP_INDUSTRY: return MKCOLOUR_XXXX(PC_DARK_GREY);
570  case MP_HOUSE: return MKCOLOUR_XXXX(PC_DARK_RED);
571  default: o = GetTileOwner(tile); break;
572  /* FIXME: For MP_ROAD there are multiple owners.
573  * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road),
574  * even if there are no ROADTYPE_ROAD bits on the tile.
575  */
576  }
577 
578  if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
579  if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
580  const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
582  } else if (o == OWNER_TOWN) {
583  return MKCOLOUR_XXXX(PC_DARK_RED);
584  }
585 
586  return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
587 }
588 
590 static const byte _vehicle_type_colours[6] = {
592 };
593 
594 
597 {
599 }
600 
601 inline Point SmallMapWindow::SmallmapRemapCoords(int x, int y) const
602 {
603  Point pt;
604  pt.x = (y - x) * 2;
605  pt.y = y + x;
606  return pt;
607 }
608 
615 inline Point SmallMapWindow::RemapTile(int tile_x, int tile_y) const
616 {
617  int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
618  int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
619 
620  if (this->zoom == 1) return SmallmapRemapCoords(x_offset, y_offset);
621 
622  /* For negative offsets, round towards -inf. */
623  if (x_offset < 0) x_offset -= this->zoom - 1;
624  if (y_offset < 0) y_offset -= this->zoom - 1;
625 
626  return SmallmapRemapCoords(x_offset / this->zoom, y_offset / this->zoom);
627 }
628 
639 inline Point SmallMapWindow::PixelToTile(int px, int py, int *sub, bool add_sub) const
640 {
641  if (add_sub) px += this->subscroll; // Total horizontal offset.
642 
643  /* For each two rows down, add a x and a y tile, and
644  * For each four pixels to the right, move a tile to the right. */
645  Point pt = {((py >> 1) - (px >> 2)) * this->zoom, ((py >> 1) + (px >> 2)) * this->zoom};
646  px &= 3;
647 
648  if (py & 1) { // Odd number of rows, handle the 2 pixel shift.
649  if (px < 2) {
650  pt.x += this->zoom;
651  px += 2;
652  } else {
653  pt.y += this->zoom;
654  px -= 2;
655  }
656  }
657 
658  *sub = px;
659  return pt;
660 }
661 
671 Point SmallMapWindow::ComputeScroll(int tx, int ty, int x, int y, int *sub)
672 {
673  assert(x >= 0 && y >= 0);
674 
675  int new_sub;
676  Point tile_xy = PixelToTile(x, y, &new_sub, false);
677  tx -= tile_xy.x;
678  ty -= tile_xy.y;
679 
680  Point scroll;
681  if (new_sub == 0) {
682  *sub = 0;
683  scroll.x = (tx + this->zoom) * TILE_SIZE;
684  scroll.y = (ty - this->zoom) * TILE_SIZE;
685  } else {
686  *sub = 4 - new_sub;
687  scroll.x = (tx + 2 * this->zoom) * TILE_SIZE;
688  scroll.y = (ty - 2 * this->zoom) * TILE_SIZE;
689  }
690  return scroll;
691 }
692 
700 {
701  static const int zoomlevels[] = {1, 2, 4, 6, 8}; // Available zoom levels. Bigger number means more zoom-out (further away).
702  static const int MIN_ZOOM_INDEX = 0;
703  static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
704 
705  int new_index, cur_index, sub;
706  Point tile;
707  switch (change) {
708  case ZLC_INITIALIZE:
709  cur_index = - 1; // Definitely different from new_index.
710  new_index = MIN_ZOOM_INDEX;
711  tile.x = tile.y = 0;
712  break;
713 
714  case ZLC_ZOOM_IN:
715  case ZLC_ZOOM_OUT:
716  for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
717  if (this->zoom == zoomlevels[cur_index]) break;
718  }
719  assert(cur_index <= MAX_ZOOM_INDEX);
720 
721  tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
722  new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
723  break;
724 
725  default: NOT_REACHED();
726  }
727 
728  if (new_index != cur_index) {
729  this->zoom = zoomlevels[new_index];
730  if (cur_index >= 0) {
731  Point new_tile = this->PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
732  this->SetNewScroll(this->scroll_x + (tile.x - new_tile.x) * TILE_SIZE,
733  this->scroll_y + (tile.y - new_tile.y) * TILE_SIZE, sub);
734  } else if (this->map_type == SMT_LINKSTATS) {
735  this->overlay->SetDirty();
736  }
737  this->SetWidgetDisabledState(WID_SM_ZOOM_IN, this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
738  this->SetWidgetDisabledState(WID_SM_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
739  this->SetDirty();
740  }
741 }
742 
748 inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
749 {
750  int importance = 0;
751  TileIndex tile = INVALID_TILE; // Position of the most important tile.
752  TileType et = MP_VOID; // Effective tile type at that position.
753 
754  TILE_AREA_LOOP(ti, ta) {
755  TileType ttype = GetTileType(ti);
756 
757  switch (ttype) {
758  case MP_TUNNELBRIDGE: {
760 
761  switch (tt) {
762  case TRANSPORT_RAIL: ttype = MP_RAILWAY; break;
763  case TRANSPORT_ROAD: ttype = MP_ROAD; break;
764  default: ttype = MP_WATER; break;
765  }
766  break;
767  }
768 
769  case MP_INDUSTRY:
770  /* Special handling of industries while in "Industries" smallmap view. */
771  if (this->map_type == SMT_INDUSTRY) {
772  /* If industry is allowed to be seen, use its colour on the map.
773  * This has the highest priority above any value in _tiletype_importance. */
774  IndustryType type = Industry::GetByTile(ti)->type;
775  if (_legend_from_industries[_industry_to_list_pos[type]].show_on_map) {
776  if (type == _smallmap_industry_highlight) {
777  if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE);
778  } else {
779  return GetIndustrySpec(type)->map_colour * 0x01010101;
780  }
781  }
782  /* Otherwise make it disappear */
783  ttype = IsTileOnWater(ti) ? MP_WATER : MP_CLEAR;
784  }
785  break;
786 
787  default:
788  break;
789  }
790 
791  if (_tiletype_importance[ttype] > importance) {
792  importance = _tiletype_importance[ttype];
793  tile = ti;
794  et = ttype;
795  }
796  }
797 
798  switch (this->map_type) {
799  case SMT_CONTOUR:
800  return GetSmallMapContoursPixels(tile, et);
801 
802  case SMT_VEHICLES:
803  return GetSmallMapVehiclesPixels(tile, et);
804 
805  case SMT_INDUSTRY:
806  return GetSmallMapIndustriesPixels(tile, et);
807 
808  case SMT_LINKSTATS:
809  return GetSmallMapLinkStatsPixels(tile, et);
810 
811  case SMT_ROUTES:
812  return GetSmallMapRoutesPixels(tile, et);
813 
814  case SMT_VEGETATION:
815  return GetSmallMapVegetationPixels(tile, et);
816 
817  case SMT_OWNER:
818  return GetSmallMapOwnerPixels(tile, et);
819 
820  default: NOT_REACHED();
821  }
822 }
823 
837 void SmallMapWindow::DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
838 {
839  void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
840  uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
841 
842  do {
843  /* Check if the tile (xc,yc) is within the map range */
844  if (xc >= MapMaxX() || yc >= MapMaxY()) continue;
845 
846  /* Check if the dst pointer points to a pixel inside the screen buffer */
847  if (dst < _screen.dst_ptr) continue;
848  if (dst >= dst_ptr_abs_end) continue;
849 
850  /* Construct tilearea covered by (xc, yc, xc + this->zoom, yc + this->zoom) such that it is within min_xy limits. */
851  TileArea ta;
852  if (min_xy == 1 && (xc == 0 || yc == 0)) {
853  if (this->zoom == 1) continue; // The tile area is empty, don't draw anything.
854 
855  ta = TileArea(TileXY(max(min_xy, xc), max(min_xy, yc)), this->zoom - (xc == 0), this->zoom - (yc == 0));
856  } else {
857  ta = TileArea(TileXY(xc, yc), this->zoom, this->zoom);
858  }
859  ta.ClampToMap(); // Clamp to map boundaries (may contain MP_VOID tiles!).
860 
861  uint32 val = this->GetTileColours(ta);
862  uint8 *val8 = (uint8 *)&val;
863  int idx = max(0, -start_pos);
864  for (int pos = max(0, start_pos); pos < end_pos; pos++) {
865  blitter->SetPixel(dst, idx, 0, val8[idx]);
866  idx++;
867  }
868  /* Switch to next tile in the column */
869  } while (xc += this->zoom, yc += this->zoom, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
870 }
871 
877 void SmallMapWindow::DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
878 {
879  for (const Vehicle *v : Vehicle::Iterate()) {
880  if (v->type == VEH_EFFECT) continue;
881  if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
882 
883  /* Remap into flat coordinates. */
884  Point pt = this->RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
885 
886  int y = pt.y - dpi->top;
887  if (!IsInsideMM(y, 0, dpi->height)) continue; // y is out of bounds.
888 
889  bool skip = false; // Default is to draw both pixels.
890  int x = pt.x - this->subscroll - 3 - dpi->left; // Offset X coordinate.
891  if (x < 0) {
892  /* if x+1 is 0, that means we're on the very left edge,
893  * and should thus only draw a single pixel */
894  if (++x != 0) continue;
895  skip = true;
896  } else if (x >= dpi->width - 1) {
897  /* Check if we're at the very right edge, and if so draw only a single pixel */
898  if (x != dpi->width - 1) continue;
899  skip = true;
900  }
901 
902  /* Calculate pointer to pixel and the colour */
903  byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
904 
905  /* And draw either one or two pixels depending on clipping */
906  blitter->SetPixel(dpi->dst_ptr, x, y, colour);
907  if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
908  }
909 }
910 
916 {
917  for (const Town *t : Town::Iterate()) {
918  /* Remap the town coordinate */
919  Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
920  int x = pt.x - this->subscroll - (t->cache.sign.width_small >> 1);
921  int y = pt.y;
922 
923  /* Check if the town sign is within bounds */
924  if (x + t->cache.sign.width_small > dpi->left &&
925  x < dpi->left + dpi->width &&
926  y + FONT_HEIGHT_SMALL > dpi->top &&
927  y < dpi->top + dpi->height) {
928  /* And draw it. */
929  SetDParam(0, t->index);
930  DrawString(x, x + t->cache.sign.width_small, y, STR_SMALLMAP_TOWN);
931  }
932  }
933 }
934 
939 {
940  /* Find main viewport. */
942 
943  Point upper_left_smallmap_coord = InverseRemapCoords2(vp->virtual_left, vp->virtual_top);
944  Point lower_right_smallmap_coord = InverseRemapCoords2(vp->virtual_left + vp->virtual_width - 1, vp->virtual_top + vp->virtual_height - 1);
945 
946  Point upper_left = this->RemapTile(upper_left_smallmap_coord.x / (int)TILE_SIZE, upper_left_smallmap_coord.y / (int)TILE_SIZE);
947  upper_left.x -= this->subscroll;
948 
949  Point lower_right = this->RemapTile(lower_right_smallmap_coord.x / (int)TILE_SIZE, lower_right_smallmap_coord.y / (int)TILE_SIZE);
950  lower_right.x -= this->subscroll;
951 
952  SmallMapWindow::DrawVertMapIndicator(upper_left.x, upper_left.y, lower_right.y);
953  SmallMapWindow::DrawVertMapIndicator(lower_right.x, upper_left.y, lower_right.y);
954 
955  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, upper_left.y);
956  SmallMapWindow::DrawHorizMapIndicator(upper_left.x, lower_right.x, lower_right.y);
957 }
958 
971 {
973  DrawPixelInfo *old_dpi;
974 
975  old_dpi = _cur_dpi;
976  _cur_dpi = dpi;
977 
978  /* Clear it */
979  GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
980 
981  /* Which tile is displayed at (dpi->left, dpi->top)? */
982  int dx;
983  Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
984  int tile_x = this->scroll_x / (int)TILE_SIZE + tile.x;
985  int tile_y = this->scroll_y / (int)TILE_SIZE + tile.y;
986 
987  void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
988  int x = - dx - 4;
989  int y = 0;
990 
991  for (;;) {
992  /* Distance from left edge */
993  if (x >= -3) {
994  if (x >= dpi->width) break; // Exit the loop.
995 
996  int end_pos = min(dpi->width, x + 4);
997  int reps = (dpi->height - y + 1) / 2; // Number of lines.
998  if (reps > 0) {
999  this->DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
1000  }
1001  }
1002 
1003  if (y == 0) {
1004  tile_y += this->zoom;
1005  y++;
1006  ptr = blitter->MoveTo(ptr, 0, 1);
1007  } else {
1008  tile_x -= this->zoom;
1009  y--;
1010  ptr = blitter->MoveTo(ptr, 0, -1);
1011  }
1012  ptr = blitter->MoveTo(ptr, 2, 0);
1013  x += 2;
1014  }
1015 
1016  /* Draw vehicles */
1017  if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
1018 
1019  /* Draw link stat overlay */
1020  if (this->map_type == SMT_LINKSTATS) this->overlay->Draw(dpi);
1021 
1022  /* Draw town names */
1023  if (this->show_towns) this->DrawTowns(dpi);
1024 
1025  /* Draw map indicators */
1026  this->DrawMapIndicators();
1027 
1028  _cur_dpi = old_dpi;
1029 }
1030 
1035 {
1036  StringID legend_tooltip;
1037  StringID enable_all_tooltip;
1038  StringID disable_all_tooltip;
1039  int plane;
1040  switch (this->map_type) {
1041  case SMT_INDUSTRY:
1042  legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
1043  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
1044  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
1045  plane = 0;
1046  break;
1047 
1048  case SMT_OWNER:
1049  legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
1050  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
1051  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
1052  plane = 0;
1053  break;
1054 
1055  case SMT_LINKSTATS:
1056  legend_tooltip = STR_SMALLMAP_TOOLTIP_CARGO_SELECTION;
1057  enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS;
1058  disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_CARGOS;
1059  plane = 0;
1060  break;
1061 
1062  default:
1063  legend_tooltip = STR_NULL;
1064  enable_all_tooltip = STR_NULL;
1065  disable_all_tooltip = STR_NULL;
1066  plane = 1;
1067  break;
1068  }
1069 
1070  this->GetWidget<NWidgetCore>(WID_SM_LEGEND)->SetDataTip(STR_NULL, legend_tooltip);
1071  this->GetWidget<NWidgetCore>(WID_SM_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip);
1072  this->GetWidget<NWidgetCore>(WID_SM_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip);
1073  this->GetWidget<NWidgetStacked>(WID_SM_SELECT_BUTTONS)->SetDisplayedPlane(plane);
1074 }
1075 
1076 SmallMapWindow::SmallMapWindow(WindowDesc *desc, int window_number) : Window(desc), refresh(GUITimer(FORCE_REFRESH_PERIOD))
1077 {
1079  this->overlay = new LinkGraphOverlay(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1);
1080  this->InitNested(window_number);
1081  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1082 
1083  this->RebuildColourIndexIfNecessary();
1084 
1085  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1086 
1087  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1088 
1089  this->SetupWidgetData();
1090 
1091  this->SetZoomLevel(ZLC_INITIALIZE, nullptr);
1092  this->SmallMapCenterOnCurrentPos();
1093  this->SetOverlayCargoMask();
1094 }
1095 
1096 SmallMapWindow::~SmallMapWindow()
1097 {
1098  delete this->overlay;
1099  this->BreakIndustryChainLink();
1100 }
1101 
1106 {
1107  /* Rebuild colour indices if necessary. */
1109 
1110  for (uint n = 0; n < lengthof(_heightmap_schemes); n++) {
1111  /* The heights go from 0 up to and including maximum. */
1112  int heights = _settings_game.construction.max_heightlevel + 1;
1113  _heightmap_schemes[n].height_colours = ReallocT<uint32>(_heightmap_schemes[n].height_colours, heights);
1114 
1115  for (int z = 0; z < heights; z++) {
1116  size_t access_index = (_heightmap_schemes[n].colour_count * z) / heights;
1117 
1118  /* Choose colour by mapping the range (0..max heightlevel) on the complete colour table. */
1119  _heightmap_schemes[n].height_colours[z] = _heightmap_schemes[n].height_colours_base[access_index];
1120  }
1121  }
1122 
1124  BuildLandLegend();
1125 }
1126 
1127 /* virtual */ void SmallMapWindow::SetStringParameters(int widget) const
1128 {
1129  switch (widget) {
1130  case WID_SM_CAPTION:
1131  SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
1132  break;
1133  }
1134 }
1135 
1136 /* virtual */ void SmallMapWindow::OnInit()
1137 {
1138  uint min_width = 0;
1139  this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
1140  this->min_number_of_fixed_rows = lengthof(_linkstat_colours_in_legenda);
1141  for (uint i = 0; i < lengthof(_legend_table); i++) {
1142  uint height = 0;
1143  uint num_columns = 1;
1144  for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
1145  StringID str;
1146  if (i == SMT_INDUSTRY) {
1147  SetDParam(0, tbl->legend);
1149  str = STR_SMALLMAP_INDUSTRY;
1150  } else if (i == SMT_LINKSTATS) {
1151  SetDParam(0, tbl->legend);
1152  str = STR_SMALLMAP_LINKSTATS;
1153  } else if (i == SMT_OWNER) {
1154  if (tbl->company != INVALID_COMPANY) {
1155  if (!Company::IsValidID(tbl->company)) {
1156  /* Rebuild the owner legend. */
1157  BuildOwnerLegend();
1158  this->OnInit();
1159  return;
1160  }
1161  /* Non-fixed legend entries for the owner view. */
1162  SetDParam(0, tbl->company);
1163  str = STR_SMALLMAP_COMPANY;
1164  } else {
1165  str = tbl->legend;
1166  }
1167  } else {
1168  if (tbl->col_break) {
1169  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1170  height = 0;
1171  num_columns++;
1172  }
1173  height++;
1174  str = tbl->legend;
1175  }
1176  min_width = max(GetStringBoundingBox(str).width, min_width);
1177  }
1178  this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
1179  this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
1180  }
1181 
1182  /* The width of a column is the minimum width of all texts + the size of the blob + some spacing */
1183  this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1184 }
1185 
1186 /* virtual */ void SmallMapWindow::OnPaint()
1187 {
1188  if (this->map_type == SMT_OWNER) {
1189  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1190  if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
1191  /* Rebuild the owner legend. */
1192  BuildOwnerLegend();
1193  this->InvalidateData(1);
1194  break;
1195  }
1196  }
1197  }
1198 
1199  this->DrawWidgets();
1200 }
1201 
1202 /* virtual */ void SmallMapWindow::DrawWidget(const Rect &r, int widget) const
1203 {
1204  switch (widget) {
1205  case WID_SM_MAP: {
1206  DrawPixelInfo new_dpi;
1207  if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
1208  this->DrawSmallMap(&new_dpi);
1209  break;
1210  }
1211 
1212  case WID_SM_LEGEND: {
1213  uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
1214  uint number_of_rows = this->GetNumberRowsLegend(columns);
1215  bool rtl = _current_text_dir == TD_RTL;
1216  uint y_org = r.top + WD_FRAMERECT_TOP;
1217  uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
1218  uint y = y_org;
1219  uint i = 0; // Row counter for industry legend.
1220  uint row_height = FONT_HEIGHT_SMALL;
1221 
1222  uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
1223  uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
1224  uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
1225  uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
1226 
1227  StringID string = STR_NULL;
1228  switch (this->map_type) {
1229  case SMT_INDUSTRY:
1230  string = STR_SMALLMAP_INDUSTRY;
1231  break;
1232  case SMT_LINKSTATS:
1233  string = STR_SMALLMAP_LINKSTATS;
1234  break;
1235  case SMT_OWNER:
1236  string = STR_SMALLMAP_COMPANY;
1237  break;
1238  default:
1239  break;
1240  }
1241 
1242  for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
1243  if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_LINKSTATS) && i++ >= number_of_rows)) {
1244  /* Column break needed, continue at top, COLUMN_WIDTH pixels
1245  * (one "row") to the right. */
1246  x += rtl ? -(int)this->column_width : this->column_width;
1247  y = y_org;
1248  i = 1;
1249  }
1250 
1251  uint8 legend_colour = tbl->colour;
1252 
1253  switch (this->map_type) {
1254  case SMT_INDUSTRY:
1255  /* Industry name must be formatted, since it's not in tiny font in the specs.
1256  * So, draw with a parameter and use the STR_SMALLMAP_INDUSTRY string, which is tiny font */
1257  SetDParam(0, tbl->legend);
1259  if (tbl->show_on_map && tbl->type == _smallmap_industry_highlight) {
1261  }
1262  FALLTHROUGH;
1263 
1264  case SMT_LINKSTATS:
1265  SetDParam(0, tbl->legend);
1266  FALLTHROUGH;
1267 
1268  case SMT_OWNER:
1269  if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
1270  if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
1271  if (!tbl->show_on_map) {
1272  /* Simply draw the string, not the black border of the legend colour.
1273  * This will enforce the idea of the disabled item */
1274  DrawString(x + text_left, x + text_right, y, string, TC_GREY);
1275  } else {
1276  DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
1277  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour
1278  }
1279  break;
1280  }
1281  FALLTHROUGH;
1282 
1283  default:
1284  if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
1285  /* Anything that is not an industry or a company is using normal process */
1286  GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
1287  DrawString(x + text_left, x + text_right, y, tbl->legend);
1288  break;
1289  }
1290  GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); // Legend colour
1291 
1292  y += row_height;
1293  }
1294  }
1295  }
1296 }
1297 
1303 {
1304  this->RaiseWidget(this->map_type + WID_SM_CONTOUR);
1305  this->map_type = map_type;
1306  this->LowerWidget(this->map_type + WID_SM_CONTOUR);
1307 
1308  this->SetupWidgetData();
1309 
1310  if (map_type == SMT_LINKSTATS) this->overlay->SetDirty();
1311  if (map_type != SMT_INDUSTRY) this->BreakIndustryChainLink();
1312  this->SetDirty();
1313 }
1314 
1323 inline uint SmallMapWindow::GetNumberRowsLegend(uint columns) const
1324 {
1325  /* Reserve one column for link colours */
1326  uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
1327  uint num_rows_others = CeilDiv(max(_smallmap_industry_count, _smallmap_company_count), columns);
1328  return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
1329 }
1330 
1342 void SmallMapWindow::SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item)
1343 {
1344  if (_ctrl_pressed) {
1345  /* Disable all, except the clicked one */
1346  bool changes = false;
1347  for (int i = begin_legend_item; i != end_legend_item; i++) {
1348  bool new_state = (i == click_pos);
1349  if (legend[i].show_on_map != new_state) {
1350  changes = true;
1351  legend[i].show_on_map = new_state;
1352  }
1353  }
1354  if (!changes) {
1355  /* Nothing changed? Then show all (again). */
1356  for (int i = begin_legend_item; i != end_legend_item; i++) {
1357  legend[i].show_on_map = true;
1358  }
1359  }
1360  } else {
1361  legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
1362  }
1363 
1364  if (this->map_type == SMT_INDUSTRY) this->BreakIndustryChainLink();
1365 }
1366 
1371 {
1372  CargoTypes cargo_mask = 0;
1373  for (int i = 0; i != _smallmap_cargo_count; ++i) {
1374  if (_legend_linkstats[i].show_on_map) SetBit(cargo_mask, _legend_linkstats[i].type);
1375  }
1376  this->overlay->SetCargoMask(cargo_mask);
1377 }
1378 
1385 {
1386  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_LEGEND);
1387  uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
1388  uint columns = this->GetNumberColumnsLegend(wi->current_x);
1389  uint number_of_rows = this->GetNumberRowsLegend(columns);
1390  if (line >= number_of_rows) return -1;
1391 
1392  bool rtl = _current_text_dir == TD_RTL;
1393  int x = pt.x - wi->pos_x;
1394  if (rtl) x = wi->current_x - x;
1395  uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
1396 
1397  return (column * number_of_rows) + line;
1398 }
1399 
1400 /* virtual */ void SmallMapWindow::OnMouseOver(Point pt, int widget)
1401 {
1402  IndustryType new_highlight = INVALID_INDUSTRYTYPE;
1403  if (widget == WID_SM_LEGEND && this->map_type == SMT_INDUSTRY) {
1404  int industry_pos = GetPositionOnLegend(pt);
1405  if (industry_pos >= 0 && industry_pos < _smallmap_industry_count) {
1406  new_highlight = _legend_from_industries[industry_pos].type;
1407  }
1408  }
1409  if (new_highlight != _smallmap_industry_highlight) {
1410  _smallmap_industry_highlight = new_highlight;
1411  this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD);
1413  this->SetDirty();
1414  }
1415 }
1416 
1417 /* virtual */ void SmallMapWindow::OnClick(Point pt, int widget, int click_count)
1418 {
1419  switch (widget) {
1420  case WID_SM_MAP: { // Map window
1421  if (click_count > 0) this->mouse_capture_widget = widget;
1422 
1423  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1425  int sub;
1426  pt = this->PixelToTile(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
1427  ScrollWindowTo(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, -1, w);
1428 
1429  this->SetDirty();
1430  break;
1431  }
1432 
1433  case WID_SM_ZOOM_IN:
1434  case WID_SM_ZOOM_OUT: {
1435  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1436  Point pt = { (int)wid->current_x / 2, (int)wid->current_y / 2};
1437  this->SetZoomLevel((widget == WID_SM_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1438  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1439  break;
1440  }
1441 
1442  case WID_SM_CONTOUR: // Show land contours
1443  case WID_SM_VEHICLES: // Show vehicles
1444  case WID_SM_INDUSTRIES: // Show industries
1445  case WID_SM_LINKSTATS: // Show route map
1446  case WID_SM_ROUTES: // Show transport routes
1447  case WID_SM_VEGETATION: // Show vegetation
1448  case WID_SM_OWNERS: // Show land owners
1449  this->SwitchMapType((SmallMapType)(widget - WID_SM_CONTOUR));
1450  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1451  break;
1452 
1453  case WID_SM_CENTERMAP: // Center the smallmap again
1454  this->SmallMapCenterOnCurrentPos();
1455  this->HandleButtonClick(WID_SM_CENTERMAP);
1456  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1457  break;
1458 
1459  case WID_SM_TOGGLETOWNNAME: // Toggle town names
1460  this->show_towns = !this->show_towns;
1461  this->SetWidgetLoweredState(WID_SM_TOGGLETOWNNAME, this->show_towns);
1462 
1463  this->SetDirty();
1464  if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1465  break;
1466 
1467  case WID_SM_LEGEND: // Legend
1468  if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
1469  int click_pos = this->GetPositionOnLegend(pt);
1470  if (click_pos < 0) break;
1471 
1472  /* If industry type small map*/
1473  if (this->map_type == SMT_INDUSTRY) {
1474  /* If click on industries label, find right industry type and enable/disable it. */
1475  if (click_pos < _smallmap_industry_count) {
1476  this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
1477  }
1478  } else if (this->map_type == SMT_LINKSTATS) {
1479  if (click_pos < _smallmap_cargo_count) {
1480  this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
1481  this->SetOverlayCargoMask();
1482  }
1483  } else if (this->map_type == SMT_OWNER) {
1484  if (click_pos < _smallmap_company_count) {
1485  this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
1486  }
1487  }
1488  this->SetDirty();
1489  }
1490  break;
1491 
1492  case WID_SM_ENABLE_ALL:
1493  case WID_SM_DISABLE_ALL: {
1494  LegendAndColour *tbl = nullptr;
1495  switch (this->map_type) {
1496  case SMT_INDUSTRY:
1498  this->BreakIndustryChainLink();
1499  break;
1500  case SMT_OWNER:
1501  tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
1502  break;
1503  case SMT_LINKSTATS:
1504  tbl = _legend_linkstats;
1505  break;
1506  default:
1507  NOT_REACHED();
1508  }
1509  for (;!tbl->end && tbl->legend != STR_LINKGRAPH_LEGEND_UNUSED; ++tbl) {
1510  tbl->show_on_map = (widget == WID_SM_ENABLE_ALL);
1511  }
1512  if (this->map_type == SMT_LINKSTATS) this->SetOverlayCargoMask();
1513  this->SetDirty();
1514  break;
1515  }
1516 
1517  case WID_SM_SHOW_HEIGHT: // Enable/disable showing of heightmap.
1519  this->SetWidgetLoweredState(WID_SM_SHOW_HEIGHT, _smallmap_show_heightmap);
1520  this->SetDirty();
1521  break;
1522  }
1523 }
1524 
1533 /* virtual */ void SmallMapWindow::OnInvalidateData(int data, bool gui_scope)
1534 {
1535  if (!gui_scope) return;
1536 
1537  switch (data) {
1538  case 1:
1539  /* The owner legend has already been rebuilt. */
1540  this->ReInit();
1541  break;
1542 
1543  case 0: {
1544  extern std::bitset<NUM_INDUSTRYTYPES> _displayed_industries;
1545  if (this->map_type != SMT_INDUSTRY) this->SwitchMapType(SMT_INDUSTRY);
1546 
1547  for (int i = 0; i != _smallmap_industry_count; i++) {
1548  _legend_from_industries[i].show_on_map = _displayed_industries.test(_legend_from_industries[i].type);
1549  }
1550  break;
1551  }
1552 
1553  case 2:
1554  this->RebuildColourIndexIfNecessary();
1555  break;
1556 
1557  default: NOT_REACHED();
1558  }
1559  this->SetDirty();
1560 }
1561 
1562 /* virtual */ bool SmallMapWindow::OnRightClick(Point pt, int widget)
1563 {
1564  if (widget != WID_SM_MAP || _scrolling_viewport) return false;
1565 
1566  _scrolling_viewport = true;
1567  return true;
1568 }
1569 
1570 /* virtual */ void SmallMapWindow::OnMouseWheel(int wheel)
1571 {
1573  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1574  int cursor_x = _cursor.pos.x - this->left - wid->pos_x;
1575  int cursor_y = _cursor.pos.y - this->top - wid->pos_y;
1576  if (IsInsideMM(cursor_x, 0, wid->current_x) && IsInsideMM(cursor_y, 0, wid->current_y)) {
1577  Point pt = {cursor_x, cursor_y};
1578  this->SetZoomLevel((wheel < 0) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
1579  }
1580  }
1581 }
1582 
1583 /* virtual */ void SmallMapWindow::OnRealtimeTick(uint delta_ms)
1584 {
1585  /* Update the window every now and then */
1586  if (!this->refresh.Elapsed(delta_ms)) return;
1587 
1588  if (this->map_type == SMT_LINKSTATS) {
1589  uint32 company_mask = this->GetOverlayCompanyMask();
1590  if (this->overlay->GetCompanyMask() != company_mask) {
1591  this->overlay->SetCompanyMask(company_mask);
1592  } else {
1593  this->overlay->SetDirty();
1594  }
1595  }
1597 
1598  this->refresh.SetInterval(_smallmap_industry_highlight != INVALID_INDUSTRYTYPE ? BLINK_PERIOD : FORCE_REFRESH_PERIOD);
1599  this->SetDirty();
1600 }
1601 
1609 void SmallMapWindow::SetNewScroll(int sx, int sy, int sub)
1610 {
1611  const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1612  Point hv = InverseRemapCoords(wi->current_x * ZOOM_LVL_BASE * TILE_SIZE / 2, wi->current_y * ZOOM_LVL_BASE * TILE_SIZE / 2);
1613  hv.x *= this->zoom;
1614  hv.y *= this->zoom;
1615 
1616  if (sx < -hv.x) {
1617  sx = -hv.x;
1618  sub = 0;
1619  }
1620  if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
1621  sx = MapMaxX() * TILE_SIZE - hv.x;
1622  sub = 0;
1623  }
1624  if (sy < -hv.y) {
1625  sy = -hv.y;
1626  sub = 0;
1627  }
1628  if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
1629  sy = MapMaxY() * TILE_SIZE - hv.y;
1630  sub = 0;
1631  }
1632 
1633  this->scroll_x = sx;
1634  this->scroll_y = sy;
1635  this->subscroll = sub;
1636  if (this->map_type == SMT_LINKSTATS) this->overlay->SetDirty();
1637 }
1638 
1639 /* virtual */ void SmallMapWindow::OnScroll(Point delta)
1640 {
1642 
1643  /* While tile is at (delta.x, delta.y)? */
1644  int sub;
1645  Point pt = this->PixelToTile(delta.x, delta.y, &sub);
1646  this->SetNewScroll(this->scroll_x + pt.x * TILE_SIZE, this->scroll_y + pt.y * TILE_SIZE, sub);
1647 
1648  this->SetDirty();
1649 }
1650 
1655 {
1657  Point viewport_center = InverseRemapCoords2(vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2);
1658 
1659  int sub;
1660  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_SM_MAP);
1661  Point sxy = this->ComputeScroll(viewport_center.x / (int)TILE_SIZE, viewport_center.y / (int)TILE_SIZE,
1662  max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
1663  this->SetNewScroll(sxy.x, sxy.y, sub);
1664  this->SetDirty();
1665 }
1666 
1673 {
1674  int x = (st->rect.right + st->rect.left + 1) / 2;
1675  int y = (st->rect.bottom + st->rect.top + 1) / 2;
1676  Point ret = this->RemapTile(x, y);
1677 
1678  /* Same magic 3 as in DrawVehicles; that's where I got it from.
1679  * No idea what it is, but without it the result looks bad.
1680  */
1681  ret.x -= 3 + this->subscroll;
1682  return ret;
1683 }
1684 
1686 bool SmallMapWindow::show_towns = true;
1688 
1699 public:
1701  {
1702  this->smallmap_window = nullptr;
1703  }
1704 
1705  void SetupSmallestSize(Window *w, bool init_array) override
1706  {
1707  NWidgetBase *display = this->head;
1708  NWidgetBase *bar = display->next;
1709 
1710  display->SetupSmallestSize(w, init_array);
1711  bar->SetupSmallestSize(w, init_array);
1712 
1713  this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
1714  assert(this->smallmap_window != nullptr);
1715  this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
1716  this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
1717  this->fill_x = max(display->fill_x, bar->fill_x);
1718  this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
1719  this->resize_x = max(display->resize_x, bar->resize_x);
1720  this->resize_y = min(display->resize_y, bar->resize_y);
1721  }
1722 
1723  void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override
1724  {
1725  this->pos_x = x;
1726  this->pos_y = y;
1727  this->current_x = given_width;
1728  this->current_y = given_height;
1729 
1730  NWidgetBase *display = this->head;
1731  NWidgetBase *bar = display->next;
1732 
1733  if (sizing == ST_SMALLEST) {
1734  this->smallest_x = given_width;
1735  this->smallest_y = given_height;
1736  /* Make display and bar exactly equal to their minimal size. */
1737  display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
1738  bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
1739  }
1740 
1741  uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->smallest_x)));
1742  uint display_height = given_height - bar_height;
1743  display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
1744  bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
1745  }
1746 
1747  NWidgetCore *GetWidgetFromPos(int x, int y) override
1748  {
1749  if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return nullptr;
1750  for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) {
1751  NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
1752  if (widget != nullptr) return widget;
1753  }
1754  return nullptr;
1755  }
1756 
1757  void Draw(const Window *w) override
1758  {
1759  for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) child_wid->Draw(w);
1760  }
1761 };
1762 
1765  NWidget(WWT_PANEL, COLOUR_BROWN, WID_SM_MAP_BORDER),
1766  NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
1767  EndContainer(),
1768 };
1769 
1772  NWidget(WWT_PANEL, COLOUR_BROWN),
1774  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1),
1776  /* Top button row. */
1778  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_IN),
1779  SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
1780  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_CENTERMAP),
1781  SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
1782  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_BLANK),
1783  SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
1784  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_CONTOUR),
1785  SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
1786  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEHICLES),
1787  SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
1788  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_INDUSTRIES),
1789  SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
1790  EndContainer(),
1791  /* Bottom button row. */
1793  NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_ZOOM_OUT),
1794  SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
1795  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_TOGGLETOWNNAME),
1796  SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
1797  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_LINKSTATS),
1798  SetDataTip(SPR_IMG_CARGOFLOW, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
1799  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_ROUTES),
1800  SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
1801  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEGETATION),
1802  SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
1803  NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_OWNERS),
1804  SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
1805  EndContainer(),
1806  NWidget(NWID_SPACER), SetResize(0, 1),
1807  EndContainer(),
1808  EndContainer(),
1809  EndContainer(),
1810 };
1811 
1812 static NWidgetBase *SmallMapDisplay(int *biggest_index)
1813 {
1814  NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
1815 
1816  MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
1817  MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
1818  return map_display;
1819 }
1820 
1821 
1822 static const NWidgetPart _nested_smallmap_widgets[] = {
1824  NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1825  NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SM_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1826  NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1827  NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
1828  NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1829  EndContainer(),
1830  NWidgetFunction(SmallMapDisplay), // Smallmap display and legend bar + image buttons.
1831  /* Bottom button row and resize box. */
1833  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SM_SELECT_BUTTONS),
1835  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL),
1836  NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SM_DISABLE_ALL), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_NULL),
1837  NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_SM_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
1838  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1839  EndContainer(),
1840  EndContainer(),
1841  NWidget(WWT_PANEL, COLOUR_BROWN), SetFill(1, 0), SetResize(1, 0),
1842  EndContainer(),
1843  EndContainer(),
1844  NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
1845  EndContainer(),
1846 };
1847 
1848 static WindowDesc _smallmap_desc(
1849  WDP_AUTO, "smallmap", 484, 314,
1851  0,
1852  _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
1853 );
1854 
1859 {
1860  AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
1861 }
1862 
1871 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
1872 {
1873  bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
1874 
1875  /* If a user scrolls to a tile (via what way what so ever) and already is on
1876  * that tile (e.g.: pressed twice), move the smallmap to that location,
1877  * so you directly see where you are on the smallmap. */
1878 
1879  if (res) return res;
1880 
1881  SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
1882  if (w != nullptr) w->SmallMapCenterOnCurrentPos();
1883 
1884  return res;
1885 }
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:79
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:206
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:1130
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
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: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:223
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.
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
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: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
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:1481
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
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:86
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:3334
static const uint8 PC_GREEN
Green palette colour.
Definition: gfx_func.h:220
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:204
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:173
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:78
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
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:148
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:498
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:203
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 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:700
static const uint8 PC_WATER
Dark blue palette colour for water.
static uint GetClearDensity(TileIndex t)
Get the density of a non-field clear tile.
Definition: clear_map.h: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:205
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:216
static const uint8 PC_DARK_RED
Dark red palette colour.
Definition: gfx_func.h:209
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:340
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:214
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:212
static const uint8 PC_RED
Red palette colour.
Definition: gfx_func.h:210
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.
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:280
static uint TileHeight(TileIndex tile)
Returns the height of a tile.
Definition: tile_map.h:29
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.
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: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:113
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.
static const uint8 PC_GRASS_LAND
Dark green palette colour for grass land.
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.