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