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 "gfx_func.h"
00021 #include "town.h"
00022 #include "blitter/factory.hpp"
00023 #include "tunnelbridge_map.h"
00024 #include "strings_func.h"
00025 #include "core/endian_func.hpp"
00026 #include "vehicle_base.h"
00027 #include "sound_func.h"
00028 #include "window_func.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
00223 static const AndOr _smallmap_contours_andor[] = {
00224 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00225 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00226 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00227 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00228 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00229 {MKCOLOUR(0x98989898), MKCOLOUR(0x00000000)},
00230 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00231 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00232 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00233 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00234 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00235 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00236 };
00237
00238 static const AndOr _smallmap_vehicles_andor[] = {
00239 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00240 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00241 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00242 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00243 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00244 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00245 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00246 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00247 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00248 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00249 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00250 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00251 };
00252
00253 typedef uint32 GetSmallMapPixels(TileIndex tile);
00254
00255
00256 static inline TileType GetEffectiveTileType(TileIndex tile)
00257 {
00258 TileType t = GetTileType(tile);
00259
00260 if (t == MP_TUNNELBRIDGE) {
00261 TransportType tt = GetTunnelBridgeTransportType(tile);
00262
00263 switch (tt) {
00264 case TRANSPORT_RAIL: t = MP_RAILWAY; break;
00265 case TRANSPORT_ROAD: t = MP_ROAD; break;
00266 default: t = MP_WATER; break;
00267 }
00268 }
00269 return t;
00270 }
00271
00277 static inline uint32 GetSmallMapContoursPixels(TileIndex tile)
00278 {
00279 TileType t = GetEffectiveTileType(tile);
00280
00281 return ApplyMask(_map_height_bits[TileHeight(tile)], &_smallmap_contours_andor[t]);
00282 }
00283
00290 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile)
00291 {
00292 TileType t = GetEffectiveTileType(tile);
00293
00294 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00295 }
00296
00303 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile)
00304 {
00305 TileType t = GetEffectiveTileType(tile);
00306
00307 if (t == MP_INDUSTRY) {
00308
00309 if (_legend_from_industries[_industry_to_list_pos[Industry::GetByTile(tile)->type]].show_on_map) {
00310 return GetIndustrySpec(Industry::GetByTile(tile)->type)->map_colour * 0x01010101;
00311 } else {
00312
00313 t = MP_CLEAR;
00314 }
00315 }
00316
00317 return ApplyMask(_smallmap_industry_show_heightmap ? _map_height_bits[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00318 }
00319
00326 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile)
00327 {
00328 TileType t = GetEffectiveTileType(tile);
00329
00330 if (t == MP_STATION) {
00331 switch (GetStationType(tile)) {
00332 case STATION_RAIL: return MKCOLOUR(0x56565656);
00333 case STATION_AIRPORT: return MKCOLOUR(0xB8B8B8B8);
00334 case STATION_TRUCK: return MKCOLOUR(0xC2C2C2C2);
00335 case STATION_BUS: return MKCOLOUR(0xBFBFBFBF);
00336 case STATION_DOCK: return MKCOLOUR(0x98989898);
00337 default: return MKCOLOUR(0xFFFFFFFF);
00338 }
00339 }
00340
00341
00342 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_contours_andor[t]);
00343 }
00344
00345
00346 static const uint32 _vegetation_clear_bits[] = {
00347 MKCOLOUR(0x54545454),
00348 MKCOLOUR(0x52525252),
00349 MKCOLOUR(0x0A0A0A0A),
00350 MKCOLOUR(0x25252525),
00351 MKCOLOUR(0x98989898),
00352 MKCOLOUR(0xC2C2C2C2),
00353 MKCOLOUR(0x54545454),
00354 MKCOLOUR(0x54545454),
00355 };
00356
00357 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile)
00358 {
00359 TileType t = GetEffectiveTileType(tile);
00360
00361 switch (t) {
00362 case MP_CLEAR:
00363 return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR(0x37373737) : _vegetation_clear_bits[GetClearGround(tile)];
00364
00365 case MP_INDUSTRY:
00366 return GetIndustrySpec(Industry::GetByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR(0xD0D0D0D0) : MKCOLOUR(0xB5B5B5B5);
00367
00368 case MP_TREES:
00369 if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) {
00370 return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR(0x98575798) : MKCOLOUR(0xC25757C2);
00371 }
00372 return MKCOLOUR(0x54575754);
00373
00374 default:
00375 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00376 }
00377 }
00378
00379
00380 static uint32 _owner_colours[OWNER_END + 1];
00381
00388 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile)
00389 {
00390 Owner o;
00391
00392 switch (GetTileType(tile)) {
00393 case MP_INDUSTRY: o = OWNER_END; break;
00394 case MP_HOUSE: o = OWNER_TOWN; break;
00395 default: o = GetTileOwner(tile); break;
00396
00397
00398
00399
00400 }
00401
00402 return _owner_colours[o];
00403 }
00404
00405
00406 static const uint32 _smallmap_mask_left[3] = {
00407 MKCOLOUR(0xFF000000),
00408 MKCOLOUR(0xFFFF0000),
00409 MKCOLOUR(0xFFFFFF00),
00410 };
00411
00412 static const uint32 _smallmap_mask_right[] = {
00413 MKCOLOUR(0x000000FF),
00414 MKCOLOUR(0x0000FFFF),
00415 MKCOLOUR(0x00FFFFFF),
00416 };
00417
00418
00419
00420 static GetSmallMapPixels * const _smallmap_draw_procs[] = {
00421 GetSmallMapContoursPixels,
00422 GetSmallMapVehiclesPixels,
00423 GetSmallMapIndustriesPixels,
00424 GetSmallMapRoutesPixels,
00425 GetSmallMapVegetationPixels,
00426 GetSmallMapOwnerPixels,
00427 };
00428
00429 static const byte _vehicle_type_colours[6] = {
00430 184, 191, 152, 15, 215, 184
00431 };
00432
00433
00435 class SmallMapWindow : public Window {
00437 enum SmallMapType {
00438 SMT_CONTOUR,
00439 SMT_VEHICLES,
00440 SMT_INDUSTRY,
00441 SMT_ROUTES,
00442 SMT_VEGETATION,
00443 SMT_OWNER,
00444 };
00445
00446 static SmallMapType map_type;
00447 static bool show_towns;
00448
00449 static const uint LEGEND_BLOB_WIDTH = 8;
00450 static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2;
00451 uint min_number_of_columns;
00452 uint min_number_of_fixed_rows;
00453 uint column_width;
00454
00455 int32 scroll_x;
00456 int32 scroll_y;
00457 int32 subscroll;
00458
00459 static const uint8 FORCE_REFRESH_PERIOD = 0x1F;
00460 uint8 refresh;
00461
00468 inline int RemapX(int tile_x) const
00469 {
00470 return tile_x - this->scroll_x / TILE_SIZE;
00471 }
00472
00479 inline int RemapY(int tile_y) const
00480 {
00481 return tile_y - this->scroll_y / TILE_SIZE;
00482 }
00483
00498 void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, Blitter *blitter, GetSmallMapPixels *proc) const
00499 {
00500 void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
00501 void *dst_ptr_end = blitter->MoveTo(dst_ptr_abs_end, -4, 0);
00502
00503 do {
00504
00505 uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
00506 if (IsInsideMM(xc, min_xy, MapMaxX()) && IsInsideMM(yc, min_xy, MapMaxY())) {
00507
00508 if (dst < _screen.dst_ptr) continue;
00509 if (dst >= dst_ptr_abs_end) continue;
00510
00511 uint32 val = proc(TileXY(xc, yc)) & mask;
00512 uint8 *val8 = (uint8 *)&val;
00513
00514 if (dst <= dst_ptr_end) {
00515 blitter->SetPixelIfEmpty(dst, 0, 0, val8[0]);
00516 blitter->SetPixelIfEmpty(dst, 1, 0, val8[1]);
00517 blitter->SetPixelIfEmpty(dst, 2, 0, val8[2]);
00518 blitter->SetPixelIfEmpty(dst, 3, 0, val8[3]);
00519 } else {
00520
00521
00522 int i = 0;
00523 do {
00524 blitter->SetPixelIfEmpty(dst, 0, 0, val8[i]);
00525 } while (i++, dst = blitter->MoveTo(dst, 1, 0), dst < dst_ptr_abs_end);
00526 }
00527 }
00528
00529 } while (xc++, yc++, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
00530 }
00531
00537 void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
00538 {
00539 const Vehicle *v;
00540 FOR_ALL_VEHICLES(v) {
00541 if (v->type == VEH_EFFECT) continue;
00542 if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
00543
00544
00545 Point pt = RemapCoords(
00546 this->RemapX(v->x_pos / TILE_SIZE),
00547 this->RemapY(v->y_pos / TILE_SIZE),
00548 0);
00549 int x = pt.x;
00550 int y = pt.y;
00551
00552
00553 y -= dpi->top;
00554 if (!IsInsideMM(y, 0, dpi->height)) continue;
00555
00556
00557 bool skip = false;
00558
00559
00560 x -= this->subscroll + 3 + dpi->left;
00561
00562 if (x < 0) {
00563
00564
00565 if (++x != 0) continue;
00566 skip = true;
00567 } else if (x >= dpi->width - 1) {
00568
00569 if (x != dpi->width - 1) continue;
00570 skip = true;
00571 }
00572
00573
00574 byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF;
00575
00576
00577 blitter->SetPixel(dpi->dst_ptr, x, y, colour);
00578 if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
00579 }
00580 }
00581
00586 void DrawTowns(const DrawPixelInfo *dpi) const
00587 {
00588 const Town *t;
00589 FOR_ALL_TOWNS(t) {
00590
00591 Point pt = RemapCoords(
00592 this->RemapX(TileX(t->xy)),
00593 this->RemapY(TileY(t->xy)),
00594 0);
00595 int x = pt.x - this->subscroll - (t->sign.width_small >> 1);
00596 int y = pt.y;
00597
00598
00599 if (x + t->sign.width_small > dpi->left &&
00600 x < dpi->left + dpi->width &&
00601 y + FONT_HEIGHT_SMALL > dpi->top &&
00602 y < dpi->top + dpi->height) {
00603
00604 SetDParam(0, t->index);
00605 DrawString(x, x + t->sign.width_small, y, STR_SMALLMAP_TOWN);
00606 }
00607 }
00608 }
00609
00616 static inline void DrawVertMapIndicator(int x, int y, int y2)
00617 {
00618 GfxFillRect(x, y, x, y + 3, 69);
00619 GfxFillRect(x, y2 - 3, x, y2, 69);
00620 }
00621
00628 static inline void DrawHorizMapIndicator(int x, int x2, int y)
00629 {
00630 GfxFillRect(x, y, x + 3, y, 69);
00631 GfxFillRect(x2 - 3, y, x2, y, 69);
00632 }
00633
00637 void DrawMapIndicators() const
00638 {
00639
00640 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
00641
00642 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00643
00644 int x = vp->virtual_left - pt.x;
00645 int y = vp->virtual_top - pt.y;
00646 int x2 = (x + vp->virtual_width) / TILE_SIZE;
00647 int y2 = (y + vp->virtual_height) / TILE_SIZE;
00648 x /= TILE_SIZE;
00649 y /= TILE_SIZE;
00650
00651 x -= this->subscroll;
00652 x2 -= this->subscroll;
00653
00654 SmallMapWindow::DrawVertMapIndicator(x, y, y2);
00655 SmallMapWindow::DrawVertMapIndicator(x2, y, y2);
00656
00657 SmallMapWindow::DrawHorizMapIndicator(x, x2, y);
00658 SmallMapWindow::DrawHorizMapIndicator(x, x2, y2);
00659 }
00660
00672 void DrawSmallMap(DrawPixelInfo *dpi) const
00673 {
00674 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
00675 DrawPixelInfo *old_dpi;
00676
00677 old_dpi = _cur_dpi;
00678 _cur_dpi = dpi;
00679
00680
00681 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
00682
00683
00684 if (this->map_type == SMT_OWNER) {
00685 const Company *c;
00686
00687
00688 _owner_colours[OWNER_TOWN] = MKCOLOUR(0xB4B4B4B4);
00689 _owner_colours[OWNER_NONE] = MKCOLOUR(0x54545454);
00690 _owner_colours[OWNER_WATER] = MKCOLOUR(0xCACACACA);
00691 _owner_colours[OWNER_END] = MKCOLOUR(0x20202020);
00692
00693
00694 FOR_ALL_COMPANIES(c) {
00695 _owner_colours[c->index] = _colour_gradient[c->colour][5] * 0x01010101;
00696 }
00697 }
00698
00699 int tile_x = this->scroll_x / TILE_SIZE;
00700 int tile_y = this->scroll_y / TILE_SIZE;
00701
00702 int dx = dpi->left + this->subscroll;
00703 tile_x -= dx / 4;
00704 tile_y += dx / 4;
00705 dx &= 3;
00706
00707 int dy = dpi->top;
00708 tile_x += dy / 2;
00709 tile_y += dy / 2;
00710
00711 if (dy & 1) {
00712 tile_x++;
00713 dx += 2;
00714 if (dx > 3) {
00715 dx -= 4;
00716 tile_x--;
00717 tile_y++;
00718 }
00719 }
00720
00721 void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
00722 int x = - dx - 4;
00723 int y = 0;
00724
00725 for (;;) {
00726 uint32 mask = 0xFFFFFFFF;
00727
00728
00729 if (x >= -3) {
00730 if (x < 0) {
00731
00732 mask = _smallmap_mask_left[x + 3];
00733 }
00734
00735
00736 int t = dpi->width - x;
00737 if (t < 4) {
00738 if (t <= 0) break;
00739
00740 mask &= _smallmap_mask_right[t - 1];
00741 }
00742
00743
00744 int reps = (dpi->height - y + 1) / 2;
00745 if (reps > 0) {
00746 this->DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, blitter, _smallmap_draw_procs[this->map_type]);
00747 }
00748 }
00749
00750 if (y == 0) {
00751 tile_y++;
00752 y++;
00753 ptr = blitter->MoveTo(ptr, 0, 1);
00754 } else {
00755 tile_x--;
00756 y--;
00757 ptr = blitter->MoveTo(ptr, 0, -1);
00758 }
00759 ptr = blitter->MoveTo(ptr, 2, 0);
00760 x += 2;
00761 }
00762
00763
00764 if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
00765
00766
00767 if (this->show_towns) this->DrawTowns(dpi);
00768
00769
00770 this->DrawMapIndicators();
00771
00772 _cur_dpi = old_dpi;
00773 }
00774
00775 public:
00776 SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), refresh(FORCE_REFRESH_PERIOD)
00777 {
00778 this->InitNested(desc, window_number);
00779 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00780
00781 _smallmap_industry_show_heightmap = false;
00782 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
00783
00784 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00785 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00786
00787 this->SmallMapCenterOnCurrentPos();
00788 }
00789
00793 inline uint GetMaxLegendHeight() const
00794 {
00795 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + this->min_number_of_columns - 1) / this->min_number_of_columns);
00796 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00797 }
00798
00802 inline uint GetMinLegendWidth() const
00803 {
00804 return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
00805 }
00806
00810 inline uint GetNumberColumnsLegend(uint width) const
00811 {
00812 return width / this->column_width;
00813 }
00814
00818 uint GetLegendHeight(uint width) const
00819 {
00820 uint num_columns = this->GetNumberColumnsLegend(width);
00821 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + num_columns - 1) / num_columns);
00822 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00823 }
00824
00825 virtual void SetStringParameters(int widget) const
00826 {
00827 switch (widget) {
00828 case SM_WIDGET_CAPTION:
00829 SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
00830 break;
00831 }
00832 }
00833
00834 virtual void OnInit()
00835 {
00836 uint min_width = 0;
00837 this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
00838 this->min_number_of_fixed_rows = 0;
00839 for (uint i = 0; i < lengthof(_legend_table); i++) {
00840 uint height = 0;
00841 uint num_columns = 1;
00842 for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
00843 StringID str;
00844 if (i == SMT_INDUSTRY) {
00845 SetDParam(0, tbl->legend);
00846 SetDParam(1, IndustryPool::MAX_SIZE);
00847 str = STR_SMALLMAP_INDUSTRY;
00848 } else {
00849 if (tbl->col_break) {
00850 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00851 height = 0;
00852 num_columns++;
00853 }
00854 height++;
00855 str = tbl->legend;
00856 }
00857 min_width = max(GetStringBoundingBox(str).width, min_width);
00858 }
00859 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00860 this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
00861 }
00862
00863
00864 this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
00865 }
00866
00867 virtual void DrawWidget(const Rect &r, int widget) const
00868 {
00869 switch (widget) {
00870 case SM_WIDGET_MAP: {
00871 DrawPixelInfo new_dpi;
00872 if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
00873 this->DrawSmallMap(&new_dpi);
00874 } break;
00875
00876 case SM_WIDGET_LEGEND: {
00877 uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
00878 uint number_of_rows = max(this->map_type == SMT_INDUSTRY ? (_smallmap_industry_count + columns - 1) / columns : 0, this->min_number_of_fixed_rows);
00879 bool rtl = _dynlang.text_dir == TD_RTL;
00880 uint y_org = r.top + WD_FRAMERECT_TOP;
00881 uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
00882 uint y = y_org;
00883 uint i = 0;
00884 uint row_height = FONT_HEIGHT_SMALL;
00885
00886 uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
00887 uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
00888 uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
00889 uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
00890
00891 for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
00892 if (tbl->col_break || (this->map_type == SMT_INDUSTRY && i++ >= number_of_rows)) {
00893
00894
00895 x += rtl ? -(int)this->column_width : this->column_width;
00896 y = y_org;
00897 i = 1;
00898 }
00899
00900 if (this->map_type == SMT_INDUSTRY) {
00901
00902
00903 SetDParam(0, tbl->legend);
00904 assert(tbl->type < NUM_INDUSTRYTYPES);
00905 SetDParam(1, _industry_counts[tbl->type]);
00906 if (!tbl->show_on_map) {
00907
00908
00909 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
00910 } else {
00911 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
00912 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00913 }
00914 } else {
00915
00916 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00917 DrawString(x + text_left, x + text_right, y, tbl->legend);
00918 }
00919 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour);
00920
00921 y += row_height;
00922 }
00923 }
00924 }
00925 }
00926
00927 virtual void OnPaint()
00928 {
00929 this->DrawWidgets();
00930 }
00931
00932 virtual void OnClick(Point pt, int widget)
00933 {
00934 switch (widget) {
00935 case SM_WIDGET_MAP: {
00936
00937
00938
00939
00940
00941
00942
00943
00944 _left_button_clicked = false;
00945
00946 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00947 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
00948 w->viewport->follow_vehicle = INVALID_VEHICLE;
00949 w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + 2) << 4) - (w->viewport->virtual_width >> 1);
00950 w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - 16) << 4) - (w->viewport->virtual_height >> 1);
00951
00952 this->SetDirty();
00953 } break;
00954
00955 case SM_WIDGET_CONTOUR:
00956 case SM_WIDGET_VEHICLES:
00957 case SM_WIDGET_INDUSTRIES:
00958 case SM_WIDGET_ROUTES:
00959 case SM_WIDGET_VEGETATION:
00960 case SM_WIDGET_OWNERS:
00961 this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
00962 this->map_type = (SmallMapType)(widget - SM_WIDGET_CONTOUR);
00963 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00964
00965
00966 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00967
00968 this->SetDirty();
00969 SndPlayFx(SND_15_BEEP);
00970 break;
00971
00972 case SM_WIDGET_CENTERMAP:
00973 this->SmallMapCenterOnCurrentPos();
00974 this->HandleButtonClick(SM_WIDGET_CENTERMAP);
00975 SndPlayFx(SND_15_BEEP);
00976 break;
00977
00978 case SM_WIDGET_TOGGLETOWNNAME:
00979 this->show_towns = !this->show_towns;
00980 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00981
00982 this->SetDirty();
00983 SndPlayFx(SND_15_BEEP);
00984 break;
00985
00986 case SM_WIDGET_LEGEND:
00987
00988 if (this->map_type == SMT_INDUSTRY) {
00989
00990 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND);
00991 uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
00992 uint columns = this->GetNumberColumnsLegend(wi->current_x);
00993 uint number_of_rows = max((_smallmap_industry_count + columns - 1) / columns, this->min_number_of_fixed_rows);
00994 if (line >= number_of_rows) break;
00995
00996 bool rtl = _dynlang.text_dir == TD_RTL;
00997 int x = pt.x - wi->pos_x;
00998 if (rtl) x = wi->current_x - x;
00999 uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
01000
01001
01002 int industry_pos = (column * number_of_rows) + line;
01003 if (industry_pos < _smallmap_industry_count) {
01004 _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
01005 }
01006
01007
01008 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
01009 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
01010 this->SetDirty();
01011 }
01012 break;
01013
01014 case SM_WIDGET_ENABLEINDUSTRIES:
01015 for (int i = 0; i != _smallmap_industry_count; i++) {
01016 _legend_from_industries[i].show_on_map = true;
01017 }
01018
01019 this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
01020 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
01021 this->SetDirty();
01022 break;
01023
01024 case SM_WIDGET_DISABLEINDUSTRIES:
01025 for (int i = 0; i != _smallmap_industry_count; i++) {
01026 _legend_from_industries[i].show_on_map = false;
01027 }
01028
01029 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
01030 this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
01031 this->SetDirty();
01032 break;
01033
01034 case SM_WIDGET_SHOW_HEIGHT:
01035 _smallmap_industry_show_heightmap = !_smallmap_industry_show_heightmap;
01036 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
01037 this->SetDirty();
01038 break;
01039 }
01040 }
01041
01042 virtual void OnRightClick(Point pt, int widget)
01043 {
01044 if (widget == SM_WIDGET_MAP) {
01045 if (_scrolling_viewport) return;
01046 _scrolling_viewport = true;
01047 }
01048 }
01049
01050 virtual void OnTick()
01051 {
01052
01053 if (--this->refresh != 0) return;
01054
01055 this->refresh = FORCE_REFRESH_PERIOD;
01056 this->SetDirty();
01057 }
01058
01059 virtual void OnScroll(Point delta)
01060 {
01061 _cursor.fix_at = true;
01062
01063 int x = this->scroll_x;
01064 int y = this->scroll_y;
01065
01066 int sub = this->subscroll + delta.x;
01067
01068 x -= (sub >> 2) << 4;
01069 y += (sub >> 2) << 4;
01070 sub &= 3;
01071
01072 x += (delta.y >> 1) << 4;
01073 y += (delta.y >> 1) << 4;
01074
01075 if (delta.y & 1) {
01076 x += TILE_SIZE;
01077 sub += 2;
01078 if (sub > 3) {
01079 sub -= 4;
01080 x -= TILE_SIZE;
01081 y += TILE_SIZE;
01082 }
01083 }
01084
01085 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01086 int hx = wi->current_x / 2;
01087 int hy = wi->current_y / 2;
01088 int hvx = hx * -4 + hy * 8;
01089 int hvy = hx * 4 + hy * 8;
01090 if (x < -hvx) {
01091 x = -hvx;
01092 sub = 0;
01093 }
01094 if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
01095 x = MapMaxX() * TILE_SIZE - hvx;
01096 sub = 0;
01097 }
01098 if (y < -hvy) {
01099 y = -hvy;
01100 sub = 0;
01101 }
01102 if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
01103 y = MapMaxY() * TILE_SIZE - hvy;
01104 sub = 0;
01105 }
01106
01107 this->scroll_x = x;
01108 this->scroll_y = y;
01109 this->subscroll = sub;
01110
01111 this->SetDirty();
01112 }
01113
01114 void SmallMapCenterOnCurrentPos()
01115 {
01116 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
01117 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01118
01119 int x = ((vp->virtual_width - (int)wi->current_x * TILE_SIZE) / 2 + vp->virtual_left) / 4;
01120 int y = ((vp->virtual_height - (int)wi->current_y * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
01121 this->scroll_x = (y - x) & ~0xF;
01122 this->scroll_y = (x + y) & ~0xF;
01123 this->SetDirty();
01124 }
01125 };
01126
01127 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
01128 bool SmallMapWindow::show_towns = true;
01129
01138 class NWidgetSmallmapDisplay : public NWidgetContainer {
01139 const SmallMapWindow *smallmap_window;
01140 public:
01141 NWidgetSmallmapDisplay() : NWidgetContainer(NWID_VERTICAL)
01142 {
01143 this->smallmap_window = NULL;
01144 }
01145
01146 virtual void SetupSmallestSize(Window *w, bool init_array)
01147 {
01148 NWidgetBase *display = this->head;
01149 NWidgetBase *bar = display->next;
01150
01151 display->SetupSmallestSize(w, init_array);
01152 bar->SetupSmallestSize(w, init_array);
01153
01154 this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
01155 this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
01156 this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetMaxLegendHeight());
01157 this->fill_x = max(display->fill_x, bar->fill_x);
01158 this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
01159 this->resize_x = max(display->resize_x, bar->resize_x);
01160 this->resize_y = min(display->resize_y, bar->resize_y);
01161 }
01162
01163 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
01164 {
01165 this->pos_x = x;
01166 this->pos_y = y;
01167 this->current_x = given_width;
01168 this->current_y = given_height;
01169
01170 NWidgetBase *display = this->head;
01171 NWidgetBase *bar = display->next;
01172
01173 if (sizing == ST_SMALLEST) {
01174 this->smallest_x = given_width;
01175 this->smallest_y = given_height;
01176
01177 display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
01178 bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
01179 }
01180
01181 uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
01182 uint display_height = given_height - bar_height;
01183 display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
01184 bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
01185 }
01186
01187 virtual NWidgetCore *GetWidgetFromPos(int x, int y)
01188 {
01189 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
01190 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01191 NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
01192 if (widget != NULL) return widget;
01193 }
01194 return NULL;
01195 }
01196
01197 virtual void Draw(const Window *w)
01198 {
01199 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
01200 }
01201 };
01202
01204 static const NWidgetPart _nested_smallmap_display[] = {
01205 NWidget(WWT_PANEL, COLOUR_BROWN, SM_WIDGET_MAP_BORDER),
01206 NWidget(WWT_INSET, COLOUR_BROWN, SM_WIDGET_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
01207 EndContainer(),
01208 };
01209
01211 static const NWidgetPart _nested_smallmap_bar[] = {
01212 NWidget(WWT_PANEL, COLOUR_BROWN),
01213 NWidget(NWID_HORIZONTAL),
01214 NWidget(WWT_EMPTY, INVALID_COLOUR, SM_WIDGET_LEGEND), SetResize(1, 1),
01215 NWidget(NWID_VERTICAL),
01216
01217 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01218 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER),
01219 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR), SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP),
01220 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES), SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP),
01221 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES), SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP),
01222 EndContainer(),
01223
01224 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01225 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME), SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF),
01226 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES), SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON),
01227 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION), SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP),
01228 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP),
01229 EndContainer(),
01230 NWidget(NWID_SPACER), SetResize(0, 1),
01231 EndContainer(),
01232 EndContainer(),
01233 EndContainer(),
01234 };
01235
01236 static NWidgetBase *SmallMapDisplay(int *biggest_index)
01237 {
01238 NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
01239
01240 MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
01241 MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
01242 return map_display;
01243 }
01244
01245
01246 static const NWidgetPart _nested_smallmap_widgets[] = {
01247 NWidget(NWID_HORIZONTAL),
01248 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
01249 NWidget(WWT_CAPTION, COLOUR_BROWN, SM_WIDGET_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01250 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
01251 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
01252 EndContainer(),
01253 NWidgetFunction(SmallMapDisplay),
01254
01255 NWidget(NWID_HORIZONTAL),
01256 NWidget(WWT_PANEL, COLOUR_BROWN),
01257 NWidget(NWID_HORIZONTAL),
01258 NWidget(NWID_SELECTION, INVALID_COLOUR, SM_WIDGET_SELECTINDUSTRIES),
01259 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01260 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_ENABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_SMALLMAP_TOOLTIP_ENABLE_ALL),
01261 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_DISABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_SMALLMAP_TOOLTIP_DISABLE_ALL),
01262 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
01263 EndContainer(),
01264 NWidget(NWID_SPACER), SetFill(1, 1),
01265 EndContainer(),
01266 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
01267 EndContainer(),
01268 EndContainer(),
01269 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
01270 EndContainer(),
01271 };
01272
01273 static const WindowDesc _smallmap_desc(
01274 WDP_AUTO, 446, 314,
01275 WC_SMALLMAP, WC_NONE,
01276 WDF_UNCLICK_BUTTONS,
01277 _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
01278 );
01279
01280 void ShowSmallMap()
01281 {
01282 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
01283 }
01284
01293 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
01294 {
01295 bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
01296
01297
01298
01299
01300
01301 if (res) return res;
01302
01303 SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
01304 if (w != NULL) w->SmallMapCenterOnCurrentPos();
01305
01306 return res;
01307 }