00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "clear_map.h"
00014 #include "industry.h"
00015 #include "station_map.h"
00016 #include "landscape.h"
00017 #include "window_gui.h"
00018 #include "tree_map.h"
00019 #include "viewport_func.h"
00020 #include "town.h"
00021 #include "blitter/factory.hpp"
00022 #include "tunnelbridge_map.h"
00023 #include "strings_func.h"
00024 #include "core/endian_func.hpp"
00025 #include "vehicle_base.h"
00026 #include "sound_func.h"
00027 #include "window_func.h"
00028 #include "company_base.h"
00029
00030 #include "table/strings.h"
00031 #include "table/sprites.h"
00032
00034 enum SmallMapWindowWidgets {
00035 SM_WIDGET_CAPTION,
00036 SM_WIDGET_MAP_BORDER,
00037 SM_WIDGET_MAP,
00038 SM_WIDGET_LEGEND,
00039 SM_WIDGET_CONTOUR,
00040 SM_WIDGET_VEHICLES,
00041 SM_WIDGET_INDUSTRIES,
00042 SM_WIDGET_ROUTES,
00043 SM_WIDGET_VEGETATION,
00044 SM_WIDGET_OWNERS,
00045 SM_WIDGET_CENTERMAP,
00046 SM_WIDGET_TOGGLETOWNNAME,
00047 SM_WIDGET_SELECTINDUSTRIES,
00048 SM_WIDGET_ENABLEINDUSTRIES,
00049 SM_WIDGET_DISABLEINDUSTRIES,
00050 SM_WIDGET_SHOW_HEIGHT,
00051 };
00052
00053 static int _smallmap_industry_count;
00054
00056 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, true, false, false}
00057
00058 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, true, true, false}
00059
00061 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, true, false, true}
00062
00064 struct LegendAndColour {
00065 uint8 colour;
00066 StringID legend;
00067 IndustryType type;
00068 bool show_on_map;
00069 bool end;
00070 bool col_break;
00071 };
00072
00074 static const LegendAndColour _legend_land_contours[] = {
00075 MK(0x5A, STR_SMALLMAP_LEGENDA_100M),
00076 MK(0x5C, STR_SMALLMAP_LEGENDA_200M),
00077 MK(0x5E, STR_SMALLMAP_LEGENDA_300M),
00078 MK(0x1F, STR_SMALLMAP_LEGENDA_400M),
00079 MK(0x27, STR_SMALLMAP_LEGENDA_500M),
00080
00081 MS(0xD7, STR_SMALLMAP_LEGENDA_ROADS),
00082 MK(0x0A, STR_SMALLMAP_LEGENDA_RAILROADS),
00083 MK(0x98, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
00084 MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00085 MK(0x0F, STR_SMALLMAP_LEGENDA_VEHICLES),
00086 MKEND()
00087 };
00088
00089 static const LegendAndColour _legend_vehicles[] = {
00090 MK(0xB8, STR_SMALLMAP_LEGENDA_TRAINS),
00091 MK(0xBF, STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
00092 MK(0x98, STR_SMALLMAP_LEGENDA_SHIPS),
00093 MK(0x0F, STR_SMALLMAP_LEGENDA_AIRCRAFT),
00094
00095 MS(0xD7, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
00096 MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00097 MKEND()
00098 };
00099
00100 static const LegendAndColour _legend_routes[] = {
00101 MK(0xD7, STR_SMALLMAP_LEGENDA_ROADS),
00102 MK(0x0A, STR_SMALLMAP_LEGENDA_RAILROADS),
00103 MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00104
00105 MS(0x56, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
00106 MK(0xC2, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
00107 MK(0xBF, STR_SMALLMAP_LEGENDA_BUS_STATION),
00108 MK(0xB8, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
00109 MK(0x98, STR_SMALLMAP_LEGENDA_DOCK),
00110 MKEND()
00111 };
00112
00113 static const LegendAndColour _legend_vegetation[] = {
00114 MK(0x52, STR_SMALLMAP_LEGENDA_ROUGH_LAND),
00115 MK(0x54, STR_SMALLMAP_LEGENDA_GRASS_LAND),
00116 MK(0x37, STR_SMALLMAP_LEGENDA_BARE_LAND),
00117 MK(0x25, STR_SMALLMAP_LEGENDA_FIELDS),
00118 MK(0x57, STR_SMALLMAP_LEGENDA_TREES),
00119 MK(0xD0, STR_SMALLMAP_LEGENDA_FOREST),
00120
00121 MS(0x0A, STR_SMALLMAP_LEGENDA_ROCKS),
00122 MK(0xC2, STR_SMALLMAP_LEGENDA_DESERT),
00123 MK(0x98, STR_SMALLMAP_LEGENDA_SNOW),
00124 MK(0xD7, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
00125 MK(0xB5, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00126 MKEND()
00127 };
00128
00129 static const LegendAndColour _legend_land_owners[] = {
00130 MK(0xCA, STR_SMALLMAP_LEGENDA_WATER),
00131 MK(0x54, STR_SMALLMAP_LEGENDA_NO_OWNER),
00132 MK(0xB4, STR_SMALLMAP_LEGENDA_TOWNS),
00133 MK(0x20, STR_SMALLMAP_LEGENDA_INDUSTRIES),
00134 MKEND()
00135 };
00136 #undef MK
00137 #undef MS
00138 #undef MKEND
00139
00142 static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES + 1];
00143
00144 static uint _industry_to_list_pos[NUM_INDUSTRYTYPES];
00146 static bool _smallmap_industry_show_heightmap;
00147
00151 void BuildIndustriesLegend()
00152 {
00153 uint j = 0;
00154
00155
00156 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
00157 const IndustrySpec *indsp = GetIndustrySpec(i);
00158 if (indsp->enabled) {
00159 _legend_from_industries[j].legend = indsp->name;
00160 _legend_from_industries[j].colour = indsp->map_colour;
00161 _legend_from_industries[j].type = i;
00162 _legend_from_industries[j].show_on_map = true;
00163 _legend_from_industries[j].col_break = false;
00164 _legend_from_industries[j].end = false;
00165
00166
00167 _industry_to_list_pos[i] = j;
00168 j++;
00169 }
00170 }
00171
00172 _legend_from_industries[j].end = true;
00173
00174
00175 _smallmap_industry_count = j;
00176 }
00177
00178 static const LegendAndColour * const _legend_table[] = {
00179 _legend_land_contours,
00180 _legend_vehicles,
00181 _legend_from_industries,
00182 _legend_routes,
00183 _legend_vegetation,
00184 _legend_land_owners,
00185 };
00186
00187 #define MKCOLOUR(x) TO_LE32X(x)
00188
00192 static const uint32 _map_height_bits[] = {
00193 MKCOLOUR(0x5A5A5A5A),
00194 MKCOLOUR(0x5A5B5A5B),
00195 MKCOLOUR(0x5B5B5B5B),
00196 MKCOLOUR(0x5B5C5B5C),
00197 MKCOLOUR(0x5C5C5C5C),
00198 MKCOLOUR(0x5C5D5C5D),
00199 MKCOLOUR(0x5D5D5D5D),
00200 MKCOLOUR(0x5D5E5D5E),
00201 MKCOLOUR(0x5E5E5E5E),
00202 MKCOLOUR(0x5E5F5E5F),
00203 MKCOLOUR(0x5F5F5F5F),
00204 MKCOLOUR(0x5F1F5F1F),
00205 MKCOLOUR(0x1F1F1F1F),
00206 MKCOLOUR(0x1F271F27),
00207 MKCOLOUR(0x27272727),
00208 MKCOLOUR(0x27272727),
00209 };
00210 assert_compile(lengthof(_map_height_bits) == MAX_TILE_HEIGHT + 1);
00211
00212 struct AndOr {
00213 uint32 mor;
00214 uint32 mand;
00215 };
00216
00217 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
00218 {
00219 return (colour & mask->mand) | mask->mor;
00220 }
00221
00222
00224 static const AndOr _smallmap_contours_andor[] = {
00225 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00226 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00227 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00228 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00229 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00230 {MKCOLOUR(0x98989898), MKCOLOUR(0x00000000)},
00231 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00232 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00233 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00234 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00235 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00236 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00237 };
00238
00240 static const AndOr _smallmap_vehicles_andor[] = {
00241 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00242 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00243 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00244 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00245 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00246 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00247 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00248 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00249 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00250 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00251 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00252 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00253 };
00254
00255 typedef uint32 GetSmallMapPixels(TileIndex tile);
00256
00257
00258 static inline TileType GetEffectiveTileType(TileIndex tile)
00259 {
00260 TileType t = GetTileType(tile);
00261
00262 if (t == MP_TUNNELBRIDGE) {
00263 TransportType tt = GetTunnelBridgeTransportType(tile);
00264
00265 switch (tt) {
00266 case TRANSPORT_RAIL: t = MP_RAILWAY; break;
00267 case TRANSPORT_ROAD: t = MP_ROAD; break;
00268 default: t = MP_WATER; break;
00269 }
00270 }
00271 return t;
00272 }
00273
00279 static inline uint32 GetSmallMapContoursPixels(TileIndex tile)
00280 {
00281 TileType t = GetEffectiveTileType(tile);
00282
00283 return ApplyMask(_map_height_bits[TileHeight(tile)], &_smallmap_contours_andor[t]);
00284 }
00285
00292 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile)
00293 {
00294 TileType t = GetEffectiveTileType(tile);
00295
00296 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00297 }
00298
00305 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile)
00306 {
00307 TileType t = GetEffectiveTileType(tile);
00308
00309 if (t == MP_INDUSTRY) {
00310
00311 if (_legend_from_industries[_industry_to_list_pos[Industry::GetByTile(tile)->type]].show_on_map) {
00312 return GetIndustrySpec(Industry::GetByTile(tile)->type)->map_colour * 0x01010101;
00313 } else {
00314
00315 t = MP_CLEAR;
00316 }
00317 }
00318
00319 return ApplyMask(_smallmap_industry_show_heightmap ? _map_height_bits[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00320 }
00321
00328 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile)
00329 {
00330 TileType t = GetEffectiveTileType(tile);
00331
00332 if (t == MP_STATION) {
00333 switch (GetStationType(tile)) {
00334 case STATION_RAIL: return MKCOLOUR(0x56565656);
00335 case STATION_AIRPORT: return MKCOLOUR(0xB8B8B8B8);
00336 case STATION_TRUCK: return MKCOLOUR(0xC2C2C2C2);
00337 case STATION_BUS: return MKCOLOUR(0xBFBFBFBF);
00338 case STATION_DOCK: return MKCOLOUR(0x98989898);
00339 default: return MKCOLOUR(0xFFFFFFFF);
00340 }
00341 }
00342
00343
00344 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_contours_andor[t]);
00345 }
00346
00347
00348 static const uint32 _vegetation_clear_bits[] = {
00349 MKCOLOUR(0x54545454),
00350 MKCOLOUR(0x52525252),
00351 MKCOLOUR(0x0A0A0A0A),
00352 MKCOLOUR(0x25252525),
00353 MKCOLOUR(0x98989898),
00354 MKCOLOUR(0xC2C2C2C2),
00355 MKCOLOUR(0x54545454),
00356 MKCOLOUR(0x54545454),
00357 };
00358
00365 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile)
00366 {
00367 TileType t = GetEffectiveTileType(tile);
00368
00369 switch (t) {
00370 case MP_CLEAR:
00371 return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR(0x37373737) : _vegetation_clear_bits[GetClearGround(tile)];
00372
00373 case MP_INDUSTRY:
00374 return GetIndustrySpec(Industry::GetByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR(0xD0D0D0D0) : MKCOLOUR(0xB5B5B5B5);
00375
00376 case MP_TREES:
00377 if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT || GetTreeGround(tile) == TREE_GROUND_ROUGH_SNOW) {
00378 return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR(0x98575798) : MKCOLOUR(0xC25757C2);
00379 }
00380 return MKCOLOUR(0x54575754);
00381
00382 default:
00383 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00384 }
00385 }
00386
00387
00388 static uint32 _owner_colours[OWNER_END + 1];
00389
00396 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile)
00397 {
00398 Owner o;
00399
00400 switch (GetTileType(tile)) {
00401 case MP_INDUSTRY: o = OWNER_END; break;
00402 case MP_HOUSE: o = OWNER_TOWN; break;
00403 default: o = GetTileOwner(tile); break;
00404
00405
00406
00407
00408 }
00409
00410 return _owner_colours[o];
00411 }
00412
00413
00414
00416 static GetSmallMapPixels * const _smallmap_draw_procs[] = {
00417 GetSmallMapContoursPixels,
00418 GetSmallMapVehiclesPixels,
00419 GetSmallMapIndustriesPixels,
00420 GetSmallMapRoutesPixels,
00421 GetSmallMapVegetationPixels,
00422 GetSmallMapOwnerPixels,
00423 };
00424
00426 static const byte _vehicle_type_colours[6] = {
00427 184, 191, 152, 15, 215, 184
00428 };
00429
00430
00432 class SmallMapWindow : public Window {
00434 enum SmallMapType {
00435 SMT_CONTOUR,
00436 SMT_VEHICLES,
00437 SMT_INDUSTRY,
00438 SMT_ROUTES,
00439 SMT_VEGETATION,
00440 SMT_OWNER,
00441 };
00442
00443 static SmallMapType map_type;
00444 static bool show_towns;
00445
00446 static const uint LEGEND_BLOB_WIDTH = 8;
00447 static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2;
00448 uint min_number_of_columns;
00449 uint min_number_of_fixed_rows;
00450 uint column_width;
00451
00452 int32 scroll_x;
00453 int32 scroll_y;
00454 int32 subscroll;
00455
00456 static const uint8 FORCE_REFRESH_PERIOD = 0x1F;
00457 uint8 refresh;
00458
00465 FORCEINLINE Point RemapTile(int tile_x, int tile_y) const
00466 {
00467 return RemapCoords(tile_x - this->scroll_x / TILE_SIZE,
00468 tile_y - this->scroll_y / TILE_SIZE, 0);
00469 }
00470
00480 FORCEINLINE Point PixelToTile(int dx, int dy, int *sub) const
00481 {
00482 dx += this->subscroll;
00483
00484
00485
00486 Point pt = {(dy >> 1) - (dx >> 2), (dy >> 1) + (dx >> 2)};
00487 dx &= 3;
00488
00489 if (dy & 1) {
00490 if (dx < 2) {
00491 pt.x++;
00492 dx += 2;
00493 } else {
00494 pt.y++;
00495 dx -= 2;
00496 }
00497 }
00498
00499 *sub = dx;
00500 return pt;
00501 }
00502
00519 void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter, GetSmallMapPixels *proc) const
00520 {
00521 void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
00522
00523 do {
00524
00525 uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
00526 if (IsInsideMM(xc, min_xy, MapMaxX()) && IsInsideMM(yc, min_xy, MapMaxY())) {
00527
00528 if (dst < _screen.dst_ptr) continue;
00529 if (dst >= dst_ptr_abs_end) continue;
00530
00531 uint32 val = proc(TileXY(xc, yc));
00532 uint8 *val8 = (uint8 *)&val;
00533 int idx = max(0, -start_pos);
00534 for (int pos = max(0, start_pos); pos < end_pos; pos++) {
00535 blitter->SetPixel(dst, idx, 0, val8[idx]);
00536 idx++;
00537 }
00538 }
00539
00540 } while (xc++, yc++, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
00541 }
00542
00548 void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
00549 {
00550 const Vehicle *v;
00551 FOR_ALL_VEHICLES(v) {
00552 if (v->type == VEH_EFFECT) continue;
00553 if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
00554
00555
00556 Point pt = this->RemapTile(v->x_pos / TILE_SIZE, v->y_pos / TILE_SIZE);
00557
00558 int y = pt.y - dpi->top;
00559 if (!IsInsideMM(y, 0, dpi->height)) continue;
00560
00561 bool skip = false;
00562 int x = pt.x - this->subscroll - 3 - dpi->left;
00563 if (x < 0) {
00564
00565
00566 if (++x != 0) continue;
00567 skip = true;
00568 } else if (x >= dpi->width - 1) {
00569
00570 if (x != dpi->width - 1) continue;
00571 skip = true;
00572 }
00573
00574
00575 byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF;
00576
00577
00578 blitter->SetPixel(dpi->dst_ptr, x, y, colour);
00579 if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
00580 }
00581 }
00582
00587 void DrawTowns(const DrawPixelInfo *dpi) const
00588 {
00589 const Town *t;
00590 FOR_ALL_TOWNS(t) {
00591
00592 Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
00593 int x = pt.x - this->subscroll - (t->sign.width_small >> 1);
00594 int y = pt.y;
00595
00596
00597 if (x + t->sign.width_small > dpi->left &&
00598 x < dpi->left + dpi->width &&
00599 y + FONT_HEIGHT_SMALL > dpi->top &&
00600 y < dpi->top + dpi->height) {
00601
00602 SetDParam(0, t->index);
00603 DrawString(x, x + t->sign.width_small, y, STR_SMALLMAP_TOWN);
00604 }
00605 }
00606 }
00607
00614 static inline void DrawVertMapIndicator(int x, int y, int y2)
00615 {
00616 GfxFillRect(x, y, x, y + 3, 69);
00617 GfxFillRect(x, y2 - 3, x, y2, 69);
00618 }
00619
00626 static inline void DrawHorizMapIndicator(int x, int x2, int y)
00627 {
00628 GfxFillRect(x, y, x + 3, y, 69);
00629 GfxFillRect(x2 - 3, y, x2, y, 69);
00630 }
00631
00635 void DrawMapIndicators() const
00636 {
00637
00638 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
00639
00640 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00641
00642 int x = vp->virtual_left - pt.x;
00643 int y = vp->virtual_top - pt.y;
00644 int x2 = (x + vp->virtual_width) / TILE_SIZE;
00645 int y2 = (y + vp->virtual_height) / TILE_SIZE;
00646 x /= TILE_SIZE;
00647 y /= TILE_SIZE;
00648
00649 x -= this->subscroll;
00650 x2 -= this->subscroll;
00651
00652 SmallMapWindow::DrawVertMapIndicator(x, y, y2);
00653 SmallMapWindow::DrawVertMapIndicator(x2, y, y2);
00654
00655 SmallMapWindow::DrawHorizMapIndicator(x, x2, y);
00656 SmallMapWindow::DrawHorizMapIndicator(x, x2, y2);
00657 }
00658
00670 void DrawSmallMap(DrawPixelInfo *dpi) const
00671 {
00672 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
00673 DrawPixelInfo *old_dpi;
00674
00675 old_dpi = _cur_dpi;
00676 _cur_dpi = dpi;
00677
00678
00679 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
00680
00681
00682 if (this->map_type == SMT_OWNER) {
00683 const Company *c;
00684
00685
00686 _owner_colours[OWNER_TOWN] = MKCOLOUR(0xB4B4B4B4);
00687 _owner_colours[OWNER_NONE] = MKCOLOUR(0x54545454);
00688 _owner_colours[OWNER_WATER] = MKCOLOUR(0xCACACACA);
00689 _owner_colours[OWNER_END] = MKCOLOUR(0x20202020);
00690
00691
00692 FOR_ALL_COMPANIES(c) {
00693 _owner_colours[c->index] = _colour_gradient[c->colour][5] * 0x01010101;
00694 }
00695 }
00696
00697
00698 int dx;
00699 Point tile = this->PixelToTile(dpi->left, dpi->top, &dx);
00700 int tile_x = this->scroll_x / TILE_SIZE + tile.x;
00701 int tile_y = this->scroll_y / TILE_SIZE + tile.y;
00702
00703 void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
00704 int x = - dx - 4;
00705 int y = 0;
00706
00707 for (;;) {
00708
00709 if (x >= -3) {
00710 if (x >= dpi->width) break;
00711
00712 int end_pos = min(dpi->width, x + 4);
00713 int reps = (dpi->height - y + 1) / 2;
00714 if (reps > 0) {
00715 this->DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter, _smallmap_draw_procs[this->map_type]);
00716 }
00717 }
00718
00719 if (y == 0) {
00720 tile_y++;
00721 y++;
00722 ptr = blitter->MoveTo(ptr, 0, 1);
00723 } else {
00724 tile_x--;
00725 y--;
00726 ptr = blitter->MoveTo(ptr, 0, -1);
00727 }
00728 ptr = blitter->MoveTo(ptr, 2, 0);
00729 x += 2;
00730 }
00731
00732
00733 if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
00734
00735
00736 if (this->show_towns) this->DrawTowns(dpi);
00737
00738
00739 this->DrawMapIndicators();
00740
00741 _cur_dpi = old_dpi;
00742 }
00743
00744 public:
00745 SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), refresh(FORCE_REFRESH_PERIOD)
00746 {
00747 this->InitNested(desc, window_number);
00748 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00749
00750 _smallmap_industry_show_heightmap = false;
00751 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
00752
00753 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00754 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00755
00756 this->SmallMapCenterOnCurrentPos();
00757 }
00758
00762 inline uint GetMaxLegendHeight() const
00763 {
00764 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + this->min_number_of_columns - 1) / this->min_number_of_columns);
00765 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00766 }
00767
00771 inline uint GetMinLegendWidth() const
00772 {
00773 return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
00774 }
00775
00779 inline uint GetNumberColumnsLegend(uint width) const
00780 {
00781 return width / this->column_width;
00782 }
00783
00787 uint GetLegendHeight(uint width) const
00788 {
00789 uint num_columns = this->GetNumberColumnsLegend(width);
00790 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + num_columns - 1) / num_columns);
00791 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00792 }
00793
00794 virtual void SetStringParameters(int widget) const
00795 {
00796 switch (widget) {
00797 case SM_WIDGET_CAPTION:
00798 SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
00799 break;
00800 }
00801 }
00802
00803 virtual void OnInit()
00804 {
00805 uint min_width = 0;
00806 this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
00807 this->min_number_of_fixed_rows = 0;
00808 for (uint i = 0; i < lengthof(_legend_table); i++) {
00809 uint height = 0;
00810 uint num_columns = 1;
00811 for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
00812 StringID str;
00813 if (i == SMT_INDUSTRY) {
00814 SetDParam(0, tbl->legend);
00815 SetDParam(1, IndustryPool::MAX_SIZE);
00816 str = STR_SMALLMAP_INDUSTRY;
00817 } else {
00818 if (tbl->col_break) {
00819 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00820 height = 0;
00821 num_columns++;
00822 }
00823 height++;
00824 str = tbl->legend;
00825 }
00826 min_width = max(GetStringBoundingBox(str).width, min_width);
00827 }
00828 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00829 this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
00830 }
00831
00832
00833 this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
00834 }
00835
00836 virtual void DrawWidget(const Rect &r, int widget) const
00837 {
00838 switch (widget) {
00839 case SM_WIDGET_MAP: {
00840 DrawPixelInfo new_dpi;
00841 if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
00842 this->DrawSmallMap(&new_dpi);
00843 } break;
00844
00845 case SM_WIDGET_LEGEND: {
00846 uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
00847 uint number_of_rows = max(this->map_type == SMT_INDUSTRY ? (_smallmap_industry_count + columns - 1) / columns : 0, this->min_number_of_fixed_rows);
00848 bool rtl = _dynlang.text_dir == TD_RTL;
00849 uint y_org = r.top + WD_FRAMERECT_TOP;
00850 uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
00851 uint y = y_org;
00852 uint i = 0;
00853 uint row_height = FONT_HEIGHT_SMALL;
00854
00855 uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
00856 uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
00857 uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
00858 uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
00859
00860 for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
00861 if (tbl->col_break || (this->map_type == SMT_INDUSTRY && i++ >= number_of_rows)) {
00862
00863
00864 x += rtl ? -(int)this->column_width : this->column_width;
00865 y = y_org;
00866 i = 1;
00867 }
00868
00869 if (this->map_type == SMT_INDUSTRY) {
00870
00871
00872 SetDParam(0, tbl->legend);
00873 assert(tbl->type < NUM_INDUSTRYTYPES);
00874 SetDParam(1, _industry_counts[tbl->type]);
00875 if (!tbl->show_on_map) {
00876
00877
00878 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
00879 } else {
00880 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
00881 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00882 }
00883 } else {
00884
00885 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00886 DrawString(x + text_left, x + text_right, y, tbl->legend);
00887 }
00888 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour);
00889
00890 y += row_height;
00891 }
00892 }
00893 }
00894 }
00895
00896 virtual void OnPaint()
00897 {
00898 this->DrawWidgets();
00899 }
00900
00901 virtual void OnClick(Point pt, int widget, int click_count)
00902 {
00903 switch (widget) {
00904 case SM_WIDGET_MAP: {
00905
00906
00907
00908
00909
00910
00911
00912
00913 _left_button_clicked = false;
00914
00915 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
00916 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00917 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
00918 w->viewport->follow_vehicle = INVALID_VEHICLE;
00919 w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + wid->pos_x) << 4) - (w->viewport->virtual_width >> 1);
00920 w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - wid->pos_y) << 4) - (w->viewport->virtual_height >> 1);
00921
00922 this->SetDirty();
00923 } break;
00924
00925 case SM_WIDGET_CONTOUR:
00926 case SM_WIDGET_VEHICLES:
00927 case SM_WIDGET_INDUSTRIES:
00928 case SM_WIDGET_ROUTES:
00929 case SM_WIDGET_VEGETATION:
00930 case SM_WIDGET_OWNERS:
00931 this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
00932 this->map_type = (SmallMapType)(widget - SM_WIDGET_CONTOUR);
00933 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00934
00935
00936 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00937
00938 this->SetDirty();
00939 SndPlayFx(SND_15_BEEP);
00940 break;
00941
00942 case SM_WIDGET_CENTERMAP:
00943 this->SmallMapCenterOnCurrentPos();
00944 this->HandleButtonClick(SM_WIDGET_CENTERMAP);
00945 SndPlayFx(SND_15_BEEP);
00946 break;
00947
00948 case SM_WIDGET_TOGGLETOWNNAME:
00949 this->show_towns = !this->show_towns;
00950 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00951
00952 this->SetDirty();
00953 SndPlayFx(SND_15_BEEP);
00954 break;
00955
00956 case SM_WIDGET_LEGEND:
00957
00958 if (this->map_type == SMT_INDUSTRY) {
00959
00960 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND);
00961 uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
00962 uint columns = this->GetNumberColumnsLegend(wi->current_x);
00963 uint number_of_rows = max((_smallmap_industry_count + columns - 1) / columns, this->min_number_of_fixed_rows);
00964 if (line >= number_of_rows) break;
00965
00966 bool rtl = _dynlang.text_dir == TD_RTL;
00967 int x = pt.x - wi->pos_x;
00968 if (rtl) x = wi->current_x - x;
00969 uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
00970
00971
00972 int industry_pos = (column * number_of_rows) + line;
00973 if (industry_pos < _smallmap_industry_count) {
00974 _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
00975 }
00976
00977
00978 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
00979 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
00980 this->SetDirty();
00981 }
00982 break;
00983
00984 case SM_WIDGET_ENABLEINDUSTRIES:
00985 for (int i = 0; i != _smallmap_industry_count; i++) {
00986 _legend_from_industries[i].show_on_map = true;
00987 }
00988
00989 this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
00990 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
00991 this->SetDirty();
00992 break;
00993
00994 case SM_WIDGET_DISABLEINDUSTRIES:
00995 for (int i = 0; i != _smallmap_industry_count; i++) {
00996 _legend_from_industries[i].show_on_map = false;
00997 }
00998
00999 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
01000 this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
01001 this->SetDirty();
01002 break;
01003
01004 case SM_WIDGET_SHOW_HEIGHT:
01005 _smallmap_industry_show_heightmap = !_smallmap_industry_show_heightmap;
01006 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
01007 this->SetDirty();
01008 break;
01009 }
01010 }
01011
01012 virtual void OnRightClick(Point pt, int widget)
01013 {
01014 if (widget == SM_WIDGET_MAP) {
01015 if (_scrolling_viewport) return;
01016 _scrolling_viewport = true;
01017 }
01018 }
01019
01020 virtual void OnTick()
01021 {
01022
01023 if (--this->refresh != 0) return;
01024
01025 this->refresh = FORCE_REFRESH_PERIOD;
01026 this->SetDirty();
01027 }
01028
01029 virtual void OnScroll(Point delta)
01030 {
01031 _cursor.fix_at = true;
01032
01033
01034 int sub;
01035 Point pt = this->PixelToTile(delta.x, delta.y, &sub);
01036 int x = this->scroll_x + pt.x * TILE_SIZE;
01037 int y = this->scroll_y + pt.y * TILE_SIZE;
01038
01039 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01040 int hx = wi->current_x / 2;
01041 int hy = wi->current_y / 2;
01042 int hvx = hx * -4 + hy * 8;
01043 int hvy = hx * 4 + hy * 8;
01044 if (x < -hvx) {
01045 x = -hvx;
01046 sub = 0;
01047 }
01048 if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
01049 x = MapMaxX() * TILE_SIZE - hvx;
01050 sub = 0;
01051 }
01052 if (y < -hvy) {
01053 y = -hvy;
01054 sub = 0;
01055 }
01056 if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
01057 y = MapMaxY() * TILE_SIZE - hvy;
01058 sub = 0;
01059 }
01060
01061 this->scroll_x = x;
01062 this->scroll_y = y;
01063 this->subscroll = sub;
01064
01065 this->SetDirty();
01066 }
01067
01068 void SmallMapCenterOnCurrentPos()
01069 {
01070 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
01071 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01072
01073 int x = ((vp->virtual_width - (int)wi->current_x * TILE_SIZE) / 2 + vp->virtual_left) / 4;
01074 int y = ((vp->virtual_height - (int)wi->current_y * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
01075 this->scroll_x = (y - x) & ~0xF;
01076 this->scroll_y = (x + y) & ~0xF;
01077 this->SetDirty();
01078 }
01079 };
01080
01081 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
01082 bool SmallMapWindow::show_towns = true;
01083
01092 class NWidgetSmallmapDisplay : public NWidgetContainer {
01093 const SmallMapWindow *smallmap_window;
01094 public:
01095 NWidgetSmallmapDisplay() : NWidgetContainer(NWID_VERTICAL)
01096 {
01097 this->smallmap_window = NULL;
01098 }
01099
01100 virtual void SetupSmallestSize(Window *w, bool init_array)
01101 {
01102 NWidgetBase *display = this->head;
01103 NWidgetBase *bar = display->next;
01104
01105 display->SetupSmallestSize(w, init_array);
01106 bar->SetupSmallestSize(w, init_array);
01107
01108 this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
01109 this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
01110 this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetMaxLegendHeight());
01111 this->fill_x = max(display->fill_x, bar->fill_x);
01112 this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
01113 this->resize_x = max(display->resize_x, bar->resize_x);
01114 this->resize_y = min(display->resize_y, bar->resize_y);
01115 }
01116
01117 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
01118 {
01119 this->pos_x = x;
01120 this->pos_y = y;
01121 this->current_x = given_width;
01122 this->current_y = given_height;
01123
01124 NWidgetBase *display = this->head;
01125 NWidgetBase *bar = display->next;
01126
01127 if (sizing == ST_SMALLEST) {
01128 this->smallest_x = given_width;
01129 this->smallest_y = given_height;
01130
01131 display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
01132 bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
01133 }
01134
01135 uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
01136 uint display_height = given_height - bar_height;
01137 display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
01138 bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
01139 }
01140
01141 virtual NWidgetCore *GetWidgetFromPos(int x, int y)
01142 {
01143 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
01144 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01145 NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
01146 if (widget != NULL) return widget;
01147 }
01148 return NULL;
01149 }
01150
01151 virtual void Draw(const Window *w)
01152 {
01153 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
01154 }
01155 };
01156
01158 static const NWidgetPart _nested_smallmap_display[] = {
01159 NWidget(WWT_PANEL, COLOUR_BROWN, SM_WIDGET_MAP_BORDER),
01160 NWidget(WWT_INSET, COLOUR_BROWN, SM_WIDGET_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
01161 EndContainer(),
01162 };
01163
01165 static const NWidgetPart _nested_smallmap_bar[] = {
01166 NWidget(WWT_PANEL, COLOUR_BROWN),
01167 NWidget(NWID_HORIZONTAL),
01168 NWidget(WWT_EMPTY, INVALID_COLOUR, SM_WIDGET_LEGEND), SetResize(1, 1),
01169 NWidget(NWID_VERTICAL),
01170
01171 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01172 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER),
01173 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR), SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP),
01174 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES), SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP),
01175 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES), SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP),
01176 EndContainer(),
01177
01178 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01179 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME), SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF),
01180 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES), SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON),
01181 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION), SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP),
01182 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP),
01183 EndContainer(),
01184 NWidget(NWID_SPACER), SetResize(0, 1),
01185 EndContainer(),
01186 EndContainer(),
01187 EndContainer(),
01188 };
01189
01190 static NWidgetBase *SmallMapDisplay(int *biggest_index)
01191 {
01192 NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
01193
01194 MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
01195 MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
01196 return map_display;
01197 }
01198
01199
01200 static const NWidgetPart _nested_smallmap_widgets[] = {
01201 NWidget(NWID_HORIZONTAL),
01202 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
01203 NWidget(WWT_CAPTION, COLOUR_BROWN, SM_WIDGET_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01204 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
01205 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
01206 EndContainer(),
01207 NWidgetFunction(SmallMapDisplay),
01208
01209 NWidget(NWID_HORIZONTAL),
01210 NWidget(WWT_PANEL, COLOUR_BROWN),
01211 NWidget(NWID_HORIZONTAL),
01212 NWidget(NWID_SELECTION, INVALID_COLOUR, SM_WIDGET_SELECTINDUSTRIES),
01213 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01214 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_ENABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_SMALLMAP_TOOLTIP_ENABLE_ALL),
01215 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_DISABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_SMALLMAP_TOOLTIP_DISABLE_ALL),
01216 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
01217 EndContainer(),
01218 NWidget(NWID_SPACER), SetFill(1, 1),
01219 EndContainer(),
01220 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
01221 EndContainer(),
01222 EndContainer(),
01223 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
01224 EndContainer(),
01225 };
01226
01227 static const WindowDesc _smallmap_desc(
01228 WDP_AUTO, 446, 314,
01229 WC_SMALLMAP, WC_NONE,
01230 WDF_UNCLICK_BUTTONS,
01231 _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
01232 );
01233
01234 void ShowSmallMap()
01235 {
01236 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
01237 }
01238
01247 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
01248 {
01249 bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
01250
01251
01252
01253
01254
01255 if (res) return res;
01256
01257 SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
01258 if (w != NULL) w->SmallMapCenterOnCurrentPos();
01259
01260 return res;
01261 }