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