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
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 static const uint32 _smallmap_mask_left[3] = {
00415 MKCOLOUR(0xFF000000),
00416 MKCOLOUR(0xFFFF0000),
00417 MKCOLOUR(0xFFFFFF00),
00418 };
00419
00420 static const uint32 _smallmap_mask_right[] = {
00421 MKCOLOUR(0x000000FF),
00422 MKCOLOUR(0x0000FFFF),
00423 MKCOLOUR(0x00FFFFFF),
00424 };
00425
00426
00427
00429 static GetSmallMapPixels * const _smallmap_draw_procs[] = {
00430 GetSmallMapContoursPixels,
00431 GetSmallMapVehiclesPixels,
00432 GetSmallMapIndustriesPixels,
00433 GetSmallMapRoutesPixels,
00434 GetSmallMapVegetationPixels,
00435 GetSmallMapOwnerPixels,
00436 };
00437
00439 static const byte _vehicle_type_colours[6] = {
00440 184, 191, 152, 15, 215, 184
00441 };
00442
00443
00445 class SmallMapWindow : public Window {
00447 enum SmallMapType {
00448 SMT_CONTOUR,
00449 SMT_VEHICLES,
00450 SMT_INDUSTRY,
00451 SMT_ROUTES,
00452 SMT_VEGETATION,
00453 SMT_OWNER,
00454 };
00455
00456 static SmallMapType map_type;
00457 static bool show_towns;
00458
00459 static const uint LEGEND_BLOB_WIDTH = 8;
00460 static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2;
00461 uint min_number_of_columns;
00462 uint min_number_of_fixed_rows;
00463 uint column_width;
00464
00465 int32 scroll_x;
00466 int32 scroll_y;
00467 int32 subscroll;
00468
00469 static const uint8 FORCE_REFRESH_PERIOD = 0x1F;
00470 uint8 refresh;
00471
00478 inline int RemapX(int tile_x) const
00479 {
00480 return tile_x - this->scroll_x / TILE_SIZE;
00481 }
00482
00489 inline int RemapY(int tile_y) const
00490 {
00491 return tile_y - this->scroll_y / TILE_SIZE;
00492 }
00493
00508 void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, Blitter *blitter, GetSmallMapPixels *proc) const
00509 {
00510 void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
00511 void *dst_ptr_end = blitter->MoveTo(dst_ptr_abs_end, -4, 0);
00512
00513 do {
00514
00515 uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
00516 if (IsInsideMM(xc, min_xy, MapMaxX()) && IsInsideMM(yc, min_xy, MapMaxY())) {
00517
00518 if (dst < _screen.dst_ptr) continue;
00519 if (dst >= dst_ptr_abs_end) continue;
00520
00521 uint32 val = proc(TileXY(xc, yc)) & mask;
00522 uint8 *val8 = (uint8 *)&val;
00523
00524 if (dst <= dst_ptr_end) {
00525 blitter->SetPixelIfEmpty(dst, 0, 0, val8[0]);
00526 blitter->SetPixelIfEmpty(dst, 1, 0, val8[1]);
00527 blitter->SetPixelIfEmpty(dst, 2, 0, val8[2]);
00528 blitter->SetPixelIfEmpty(dst, 3, 0, val8[3]);
00529 } else {
00530
00531
00532 int i = 0;
00533 do {
00534 blitter->SetPixelIfEmpty(dst, 0, 0, val8[i]);
00535 } while (i++, dst = blitter->MoveTo(dst, 1, 0), dst < dst_ptr_abs_end);
00536 }
00537 }
00538
00539 } while (xc++, yc++, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
00540 }
00541
00547 void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
00548 {
00549 const Vehicle *v;
00550 FOR_ALL_VEHICLES(v) {
00551 if (v->type == VEH_EFFECT) continue;
00552 if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
00553
00554
00555 Point pt = RemapCoords(
00556 this->RemapX(v->x_pos / TILE_SIZE),
00557 this->RemapY(v->y_pos / TILE_SIZE),
00558 0);
00559 int x = pt.x;
00560 int y = pt.y;
00561
00562
00563 y -= dpi->top;
00564 if (!IsInsideMM(y, 0, dpi->height)) continue;
00565
00566
00567 bool skip = false;
00568
00569
00570 x -= this->subscroll + 3 + dpi->left;
00571
00572 if (x < 0) {
00573
00574
00575 if (++x != 0) continue;
00576 skip = true;
00577 } else if (x >= dpi->width - 1) {
00578
00579 if (x != dpi->width - 1) continue;
00580 skip = true;
00581 }
00582
00583
00584 byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF;
00585
00586
00587 blitter->SetPixel(dpi->dst_ptr, x, y, colour);
00588 if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
00589 }
00590 }
00591
00596 void DrawTowns(const DrawPixelInfo *dpi) const
00597 {
00598 const Town *t;
00599 FOR_ALL_TOWNS(t) {
00600
00601 Point pt = RemapCoords(
00602 this->RemapX(TileX(t->xy)),
00603 this->RemapY(TileY(t->xy)),
00604 0);
00605 int x = pt.x - this->subscroll - (t->sign.width_small >> 1);
00606 int y = pt.y;
00607
00608
00609 if (x + t->sign.width_small > dpi->left &&
00610 x < dpi->left + dpi->width &&
00611 y + FONT_HEIGHT_SMALL > dpi->top &&
00612 y < dpi->top + dpi->height) {
00613
00614 SetDParam(0, t->index);
00615 DrawString(x, x + t->sign.width_small, y, STR_SMALLMAP_TOWN);
00616 }
00617 }
00618 }
00619
00626 static inline void DrawVertMapIndicator(int x, int y, int y2)
00627 {
00628 GfxFillRect(x, y, x, y + 3, 69);
00629 GfxFillRect(x, y2 - 3, x, y2, 69);
00630 }
00631
00638 static inline void DrawHorizMapIndicator(int x, int x2, int y)
00639 {
00640 GfxFillRect(x, y, x + 3, y, 69);
00641 GfxFillRect(x2 - 3, y, x2, y, 69);
00642 }
00643
00647 void DrawMapIndicators() const
00648 {
00649
00650 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
00651
00652 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00653
00654 int x = vp->virtual_left - pt.x;
00655 int y = vp->virtual_top - pt.y;
00656 int x2 = (x + vp->virtual_width) / TILE_SIZE;
00657 int y2 = (y + vp->virtual_height) / TILE_SIZE;
00658 x /= TILE_SIZE;
00659 y /= TILE_SIZE;
00660
00661 x -= this->subscroll;
00662 x2 -= this->subscroll;
00663
00664 SmallMapWindow::DrawVertMapIndicator(x, y, y2);
00665 SmallMapWindow::DrawVertMapIndicator(x2, y, y2);
00666
00667 SmallMapWindow::DrawHorizMapIndicator(x, x2, y);
00668 SmallMapWindow::DrawHorizMapIndicator(x, x2, y2);
00669 }
00670
00682 void DrawSmallMap(DrawPixelInfo *dpi) const
00683 {
00684 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
00685 DrawPixelInfo *old_dpi;
00686
00687 old_dpi = _cur_dpi;
00688 _cur_dpi = dpi;
00689
00690
00691 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
00692
00693
00694 if (this->map_type == SMT_OWNER) {
00695 const Company *c;
00696
00697
00698 _owner_colours[OWNER_TOWN] = MKCOLOUR(0xB4B4B4B4);
00699 _owner_colours[OWNER_NONE] = MKCOLOUR(0x54545454);
00700 _owner_colours[OWNER_WATER] = MKCOLOUR(0xCACACACA);
00701 _owner_colours[OWNER_END] = MKCOLOUR(0x20202020);
00702
00703
00704 FOR_ALL_COMPANIES(c) {
00705 _owner_colours[c->index] = _colour_gradient[c->colour][5] * 0x01010101;
00706 }
00707 }
00708
00709 int tile_x = this->scroll_x / TILE_SIZE;
00710 int tile_y = this->scroll_y / TILE_SIZE;
00711
00712 int dx = dpi->left + this->subscroll;
00713 tile_x -= dx / 4;
00714 tile_y += dx / 4;
00715 dx &= 3;
00716
00717 int dy = dpi->top;
00718 tile_x += dy / 2;
00719 tile_y += dy / 2;
00720
00721 if (dy & 1) {
00722 tile_x++;
00723 dx += 2;
00724 if (dx > 3) {
00725 dx -= 4;
00726 tile_x--;
00727 tile_y++;
00728 }
00729 }
00730
00731 void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
00732 int x = - dx - 4;
00733 int y = 0;
00734
00735 for (;;) {
00736 uint32 mask = 0xFFFFFFFF;
00737
00738
00739 if (x >= -3) {
00740 if (x < 0) {
00741
00742 mask = _smallmap_mask_left[x + 3];
00743 }
00744
00745
00746 int t = dpi->width - x;
00747 if (t < 4) {
00748 if (t <= 0) break;
00749
00750 mask &= _smallmap_mask_right[t - 1];
00751 }
00752
00753
00754 int reps = (dpi->height - y + 1) / 2;
00755 if (reps > 0) {
00756 this->DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, blitter, _smallmap_draw_procs[this->map_type]);
00757 }
00758 }
00759
00760 if (y == 0) {
00761 tile_y++;
00762 y++;
00763 ptr = blitter->MoveTo(ptr, 0, 1);
00764 } else {
00765 tile_x--;
00766 y--;
00767 ptr = blitter->MoveTo(ptr, 0, -1);
00768 }
00769 ptr = blitter->MoveTo(ptr, 2, 0);
00770 x += 2;
00771 }
00772
00773
00774 if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
00775
00776
00777 if (this->show_towns) this->DrawTowns(dpi);
00778
00779
00780 this->DrawMapIndicators();
00781
00782 _cur_dpi = old_dpi;
00783 }
00784
00785 public:
00786 SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), refresh(FORCE_REFRESH_PERIOD)
00787 {
00788 this->InitNested(desc, window_number);
00789 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00790
00791 _smallmap_industry_show_heightmap = false;
00792 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
00793
00794 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00795 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00796
00797 this->SmallMapCenterOnCurrentPos();
00798 }
00799
00803 inline uint GetMaxLegendHeight() const
00804 {
00805 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + this->min_number_of_columns - 1) / this->min_number_of_columns);
00806 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00807 }
00808
00812 inline uint GetMinLegendWidth() const
00813 {
00814 return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
00815 }
00816
00820 inline uint GetNumberColumnsLegend(uint width) const
00821 {
00822 return width / this->column_width;
00823 }
00824
00828 uint GetLegendHeight(uint width) const
00829 {
00830 uint num_columns = this->GetNumberColumnsLegend(width);
00831 uint num_rows = max(this->min_number_of_fixed_rows, (_smallmap_industry_count + num_columns - 1) / num_columns);
00832 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + num_rows * FONT_HEIGHT_SMALL;
00833 }
00834
00835 virtual void SetStringParameters(int widget) const
00836 {
00837 switch (widget) {
00838 case SM_WIDGET_CAPTION:
00839 SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
00840 break;
00841 }
00842 }
00843
00844 virtual void OnInit()
00845 {
00846 uint min_width = 0;
00847 this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
00848 this->min_number_of_fixed_rows = 0;
00849 for (uint i = 0; i < lengthof(_legend_table); i++) {
00850 uint height = 0;
00851 uint num_columns = 1;
00852 for (const LegendAndColour *tbl = _legend_table[i]; !tbl->end; ++tbl) {
00853 StringID str;
00854 if (i == SMT_INDUSTRY) {
00855 SetDParam(0, tbl->legend);
00856 SetDParam(1, IndustryPool::MAX_SIZE);
00857 str = STR_SMALLMAP_INDUSTRY;
00858 } else {
00859 if (tbl->col_break) {
00860 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00861 height = 0;
00862 num_columns++;
00863 }
00864 height++;
00865 str = tbl->legend;
00866 }
00867 min_width = max(GetStringBoundingBox(str).width, min_width);
00868 }
00869 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
00870 this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
00871 }
00872
00873
00874 this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
00875 }
00876
00877 virtual void DrawWidget(const Rect &r, int widget) const
00878 {
00879 switch (widget) {
00880 case SM_WIDGET_MAP: {
00881 DrawPixelInfo new_dpi;
00882 if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
00883 this->DrawSmallMap(&new_dpi);
00884 } break;
00885
00886 case SM_WIDGET_LEGEND: {
00887 uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
00888 uint number_of_rows = max(this->map_type == SMT_INDUSTRY ? (_smallmap_industry_count + columns - 1) / columns : 0, this->min_number_of_fixed_rows);
00889 bool rtl = _dynlang.text_dir == TD_RTL;
00890 uint y_org = r.top + WD_FRAMERECT_TOP;
00891 uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
00892 uint y = y_org;
00893 uint i = 0;
00894 uint row_height = FONT_HEIGHT_SMALL;
00895
00896 uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
00897 uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
00898 uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
00899 uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
00900
00901 for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
00902 if (tbl->col_break || (this->map_type == SMT_INDUSTRY && i++ >= number_of_rows)) {
00903
00904
00905 x += rtl ? -(int)this->column_width : this->column_width;
00906 y = y_org;
00907 i = 1;
00908 }
00909
00910 if (this->map_type == SMT_INDUSTRY) {
00911
00912
00913 SetDParam(0, tbl->legend);
00914 assert(tbl->type < NUM_INDUSTRYTYPES);
00915 SetDParam(1, _industry_counts[tbl->type]);
00916 if (!tbl->show_on_map) {
00917
00918
00919 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
00920 } else {
00921 DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
00922 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00923 }
00924 } else {
00925
00926 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, 0);
00927 DrawString(x + text_left, x + text_right, y, tbl->legend);
00928 }
00929 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour);
00930
00931 y += row_height;
00932 }
00933 }
00934 }
00935 }
00936
00937 virtual void OnPaint()
00938 {
00939 this->DrawWidgets();
00940 }
00941
00942 virtual void OnClick(Point pt, int widget)
00943 {
00944 switch (widget) {
00945 case SM_WIDGET_MAP: {
00946
00947
00948
00949
00950
00951
00952
00953
00954 _left_button_clicked = false;
00955
00956 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00957 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
00958 w->viewport->follow_vehicle = INVALID_VEHICLE;
00959 w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + 2) << 4) - (w->viewport->virtual_width >> 1);
00960 w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - 16) << 4) - (w->viewport->virtual_height >> 1);
00961
00962 this->SetDirty();
00963 } break;
00964
00965 case SM_WIDGET_CONTOUR:
00966 case SM_WIDGET_VEHICLES:
00967 case SM_WIDGET_INDUSTRIES:
00968 case SM_WIDGET_ROUTES:
00969 case SM_WIDGET_VEGETATION:
00970 case SM_WIDGET_OWNERS:
00971 this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
00972 this->map_type = (SmallMapType)(widget - SM_WIDGET_CONTOUR);
00973 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00974
00975
00976 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECTINDUSTRIES)->SetDisplayedPlane(this->map_type != SMT_INDUSTRY);
00977
00978 this->SetDirty();
00979 SndPlayFx(SND_15_BEEP);
00980 break;
00981
00982 case SM_WIDGET_CENTERMAP:
00983 this->SmallMapCenterOnCurrentPos();
00984 this->HandleButtonClick(SM_WIDGET_CENTERMAP);
00985 SndPlayFx(SND_15_BEEP);
00986 break;
00987
00988 case SM_WIDGET_TOGGLETOWNNAME:
00989 this->show_towns = !this->show_towns;
00990 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00991
00992 this->SetDirty();
00993 SndPlayFx(SND_15_BEEP);
00994 break;
00995
00996 case SM_WIDGET_LEGEND:
00997
00998 if (this->map_type == SMT_INDUSTRY) {
00999
01000 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND);
01001 uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
01002 uint columns = this->GetNumberColumnsLegend(wi->current_x);
01003 uint number_of_rows = max((_smallmap_industry_count + columns - 1) / columns, this->min_number_of_fixed_rows);
01004 if (line >= number_of_rows) break;
01005
01006 bool rtl = _dynlang.text_dir == TD_RTL;
01007 int x = pt.x - wi->pos_x;
01008 if (rtl) x = wi->current_x - x;
01009 uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
01010
01011
01012 int industry_pos = (column * number_of_rows) + line;
01013 if (industry_pos < _smallmap_industry_count) {
01014 _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
01015 }
01016
01017
01018 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
01019 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
01020 this->SetDirty();
01021 }
01022 break;
01023
01024 case SM_WIDGET_ENABLEINDUSTRIES:
01025 for (int i = 0; i != _smallmap_industry_count; i++) {
01026 _legend_from_industries[i].show_on_map = true;
01027 }
01028
01029 this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
01030 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
01031 this->SetDirty();
01032 break;
01033
01034 case SM_WIDGET_DISABLEINDUSTRIES:
01035 for (int i = 0; i != _smallmap_industry_count; i++) {
01036 _legend_from_industries[i].show_on_map = false;
01037 }
01038
01039 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
01040 this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
01041 this->SetDirty();
01042 break;
01043
01044 case SM_WIDGET_SHOW_HEIGHT:
01045 _smallmap_industry_show_heightmap = !_smallmap_industry_show_heightmap;
01046 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_industry_show_heightmap);
01047 this->SetDirty();
01048 break;
01049 }
01050 }
01051
01052 virtual void OnRightClick(Point pt, int widget)
01053 {
01054 if (widget == SM_WIDGET_MAP) {
01055 if (_scrolling_viewport) return;
01056 _scrolling_viewport = true;
01057 }
01058 }
01059
01060 virtual void OnTick()
01061 {
01062
01063 if (--this->refresh != 0) return;
01064
01065 this->refresh = FORCE_REFRESH_PERIOD;
01066 this->SetDirty();
01067 }
01068
01069 virtual void OnScroll(Point delta)
01070 {
01071 _cursor.fix_at = true;
01072
01073 int x = this->scroll_x;
01074 int y = this->scroll_y;
01075
01076 int sub = this->subscroll + delta.x;
01077
01078 x -= (sub >> 2) << 4;
01079 y += (sub >> 2) << 4;
01080 sub &= 3;
01081
01082 x += (delta.y >> 1) << 4;
01083 y += (delta.y >> 1) << 4;
01084
01085 if (delta.y & 1) {
01086 x += TILE_SIZE;
01087 sub += 2;
01088 if (sub > 3) {
01089 sub -= 4;
01090 x -= TILE_SIZE;
01091 y += TILE_SIZE;
01092 }
01093 }
01094
01095 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01096 int hx = wi->current_x / 2;
01097 int hy = wi->current_y / 2;
01098 int hvx = hx * -4 + hy * 8;
01099 int hvy = hx * 4 + hy * 8;
01100 if (x < -hvx) {
01101 x = -hvx;
01102 sub = 0;
01103 }
01104 if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
01105 x = MapMaxX() * TILE_SIZE - hvx;
01106 sub = 0;
01107 }
01108 if (y < -hvy) {
01109 y = -hvy;
01110 sub = 0;
01111 }
01112 if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
01113 y = MapMaxY() * TILE_SIZE - hvy;
01114 sub = 0;
01115 }
01116
01117 this->scroll_x = x;
01118 this->scroll_y = y;
01119 this->subscroll = sub;
01120
01121 this->SetDirty();
01122 }
01123
01124 void SmallMapCenterOnCurrentPos()
01125 {
01126 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
01127 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
01128
01129 int x = ((vp->virtual_width - (int)wi->current_x * TILE_SIZE) / 2 + vp->virtual_left) / 4;
01130 int y = ((vp->virtual_height - (int)wi->current_y * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
01131 this->scroll_x = (y - x) & ~0xF;
01132 this->scroll_y = (x + y) & ~0xF;
01133 this->SetDirty();
01134 }
01135 };
01136
01137 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
01138 bool SmallMapWindow::show_towns = true;
01139
01148 class NWidgetSmallmapDisplay : public NWidgetContainer {
01149 const SmallMapWindow *smallmap_window;
01150 public:
01151 NWidgetSmallmapDisplay() : NWidgetContainer(NWID_VERTICAL)
01152 {
01153 this->smallmap_window = NULL;
01154 }
01155
01156 virtual void SetupSmallestSize(Window *w, bool init_array)
01157 {
01158 NWidgetBase *display = this->head;
01159 NWidgetBase *bar = display->next;
01160
01161 display->SetupSmallestSize(w, init_array);
01162 bar->SetupSmallestSize(w, init_array);
01163
01164 this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
01165 this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
01166 this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetMaxLegendHeight());
01167 this->fill_x = max(display->fill_x, bar->fill_x);
01168 this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
01169 this->resize_x = max(display->resize_x, bar->resize_x);
01170 this->resize_y = min(display->resize_y, bar->resize_y);
01171 }
01172
01173 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
01174 {
01175 this->pos_x = x;
01176 this->pos_y = y;
01177 this->current_x = given_width;
01178 this->current_y = given_height;
01179
01180 NWidgetBase *display = this->head;
01181 NWidgetBase *bar = display->next;
01182
01183 if (sizing == ST_SMALLEST) {
01184 this->smallest_x = given_width;
01185 this->smallest_y = given_height;
01186
01187 display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
01188 bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
01189 }
01190
01191 uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
01192 uint display_height = given_height - bar_height;
01193 display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
01194 bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
01195 }
01196
01197 virtual NWidgetCore *GetWidgetFromPos(int x, int y)
01198 {
01199 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
01200 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01201 NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
01202 if (widget != NULL) return widget;
01203 }
01204 return NULL;
01205 }
01206
01207 virtual void Draw(const Window *w)
01208 {
01209 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
01210 }
01211 };
01212
01214 static const NWidgetPart _nested_smallmap_display[] = {
01215 NWidget(WWT_PANEL, COLOUR_BROWN, SM_WIDGET_MAP_BORDER),
01216 NWidget(WWT_INSET, COLOUR_BROWN, SM_WIDGET_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
01217 EndContainer(),
01218 };
01219
01221 static const NWidgetPart _nested_smallmap_bar[] = {
01222 NWidget(WWT_PANEL, COLOUR_BROWN),
01223 NWidget(NWID_HORIZONTAL),
01224 NWidget(WWT_EMPTY, INVALID_COLOUR, SM_WIDGET_LEGEND), SetResize(1, 1),
01225 NWidget(NWID_VERTICAL),
01226
01227 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01228 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER),
01229 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR), SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP),
01230 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES), SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP),
01231 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES), SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP),
01232 EndContainer(),
01233
01234 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01235 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME), SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF),
01236 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES), SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON),
01237 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION), SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP),
01238 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP),
01239 EndContainer(),
01240 NWidget(NWID_SPACER), SetResize(0, 1),
01241 EndContainer(),
01242 EndContainer(),
01243 EndContainer(),
01244 };
01245
01246 static NWidgetBase *SmallMapDisplay(int *biggest_index)
01247 {
01248 NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
01249
01250 MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
01251 MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
01252 return map_display;
01253 }
01254
01255
01256 static const NWidgetPart _nested_smallmap_widgets[] = {
01257 NWidget(NWID_HORIZONTAL),
01258 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
01259 NWidget(WWT_CAPTION, COLOUR_BROWN, SM_WIDGET_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
01260 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
01261 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
01262 EndContainer(),
01263 NWidgetFunction(SmallMapDisplay),
01264
01265 NWidget(NWID_HORIZONTAL),
01266 NWidget(WWT_PANEL, COLOUR_BROWN),
01267 NWidget(NWID_HORIZONTAL),
01268 NWidget(NWID_SELECTION, INVALID_COLOUR, SM_WIDGET_SELECTINDUSTRIES),
01269 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
01270 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_ENABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_SMALLMAP_TOOLTIP_ENABLE_ALL),
01271 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_DISABLEINDUSTRIES), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_SMALLMAP_TOOLTIP_DISABLE_ALL),
01272 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
01273 EndContainer(),
01274 NWidget(NWID_SPACER), SetFill(1, 1),
01275 EndContainer(),
01276 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
01277 EndContainer(),
01278 EndContainer(),
01279 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
01280 EndContainer(),
01281 };
01282
01283 static const WindowDesc _smallmap_desc(
01284 WDP_AUTO, 446, 314,
01285 WC_SMALLMAP, WC_NONE,
01286 WDF_UNCLICK_BUTTONS,
01287 _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
01288 );
01289
01290 void ShowSmallMap()
01291 {
01292 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
01293 }
01294
01303 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
01304 {
01305 bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
01306
01307
01308
01309
01310
01311 if (res) return res;
01312
01313 SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
01314 if (w != NULL) w->SmallMapCenterOnCurrentPos();
01315
01316 return res;
01317 }