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