00001
00002
00005 #include "stdafx.h"
00006 #include "clear_map.h"
00007 #include "industry_map.h"
00008 #include "station_map.h"
00009 #include "landscape.h"
00010 #include "window_gui.h"
00011 #include "tree_map.h"
00012 #include "viewport_func.h"
00013 #include "gfx_func.h"
00014 #include "town.h"
00015 #include "blitter/factory.hpp"
00016 #include "tunnelbridge_map.h"
00017 #include "strings_func.h"
00018 #include "zoom_func.h"
00019 #include "core/endian_func.hpp"
00020 #include "vehicle_base.h"
00021 #include "sound_func.h"
00022 #include "window_func.h"
00023
00024 #include "table/strings.h"
00025 #include "table/sprites.h"
00026
00027 static const Widget _smallmap_widgets[] = {
00028 { WWT_CLOSEBOX, RESIZE_NONE, COLOUR_BROWN, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
00029 { WWT_CAPTION, RESIZE_RIGHT, COLOUR_BROWN, 11, 337, 0, 13, STR_00B0_MAP, STR_018C_WINDOW_TITLE_DRAG_THIS},
00030 { WWT_STICKYBOX, RESIZE_LR, COLOUR_BROWN, 338, 349, 0, 13, 0x0, STR_STICKY_BUTTON},
00031 { WWT_PANEL, RESIZE_RB, COLOUR_BROWN, 0, 349, 14, 157, 0x0, STR_NULL},
00032 { WWT_INSET, RESIZE_RB, COLOUR_BROWN, 2, 347, 16, 155, 0x0, STR_NULL},
00033 { WWT_PANEL, RESIZE_RTB, COLOUR_BROWN, 0, 261, 158, 201, 0x0, STR_NULL},
00034 { WWT_PANEL, RESIZE_LRTB, COLOUR_BROWN, 262, 349, 158, 158, 0x0, STR_NULL},
00035 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 284, 305, 158, 179, SPR_IMG_SHOW_COUNTOURS, STR_0191_SHOW_LAND_CONTOURS_ON_MAP},
00036 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 306, 327, 158, 179, SPR_IMG_SHOW_VEHICLES, STR_0192_SHOW_VEHICLES_ON_MAP},
00037 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 328, 349, 158, 179, SPR_IMG_INDUSTRY, STR_0193_SHOW_INDUSTRIES_ON_MAP},
00038 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 284, 305, 180, 201, SPR_IMG_SHOW_ROUTES, STR_0194_SHOW_TRANSPORT_ROUTES_ON},
00039 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 306, 327, 180, 201, SPR_IMG_PLANTTREES, STR_0195_SHOW_VEGETATION_ON_MAP},
00040 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 328, 349, 180, 201, SPR_IMG_COMPANY_GENERAL, STR_0196_SHOW_LAND_OWNERS_ON_MAP},
00041 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 262, 283, 158, 179, SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER},
00042 { WWT_IMGBTN, RESIZE_LRTB, COLOUR_BROWN, 262, 283, 180, 201, SPR_IMG_TOWN, STR_0197_TOGGLE_TOWN_NAMES_ON_OFF},
00043 { WWT_PANEL, RESIZE_RTB, COLOUR_BROWN, 0, 337, 202, 213, 0x0, STR_NULL},
00044 { WWT_TEXTBTN, RESIZE_TB, COLOUR_BROWN, 0, 99, 202, 213, STR_MESSAGES_ENABLE_ALL, STR_NULL},
00045 { WWT_TEXTBTN, RESIZE_TB, COLOUR_BROWN, 100, 201, 202, 213, STR_MESSAGES_DISABLE_ALL, STR_NULL},
00046 { WWT_RESIZEBOX, RESIZE_LRTB, COLOUR_BROWN, 338, 349, 202, 213, 0x0, STR_RESIZE_BUTTON},
00047 { WIDGETS_END},
00048 };
00049
00050
00051 static int _smallmap_industry_count;
00052
00054 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, true, false, false}
00055
00056 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, true, true, false}
00057
00059 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, true, false, true}
00060
00062 struct LegendAndColour {
00063 uint16 colour;
00064 StringID legend;
00065 IndustryType type;
00066 bool show_on_map;
00067 bool end;
00068 bool col_break;
00069 };
00070
00072 static const LegendAndColour _legend_land_contours[] = {
00073 MK(0x5A, STR_00F0_100M),
00074 MK(0x5C, STR_00F1_200M),
00075 MK(0x5E, STR_00F2_300M),
00076 MK(0x1F, STR_00F3_400M),
00077 MK(0x27, STR_00F4_500M),
00078
00079 MS(0xD7, STR_00EB_ROADS),
00080 MK(0x0A, STR_00EC_RAILROADS),
00081 MK(0x98, STR_00ED_STATIONS_AIRPORTS_DOCKS),
00082 MK(0xB5, STR_00EE_BUILDINGS_INDUSTRIES),
00083 MK(0x0F, STR_00EF_VEHICLES),
00084 MKEND()
00085 };
00086
00087 static const LegendAndColour _legend_vehicles[] = {
00088 MK(0xB8, STR_00F5_TRAINS),
00089 MK(0xBF, STR_00F6_ROAD_VEHICLES),
00090 MK(0x98, STR_00F7_SHIPS),
00091 MK(0x0F, STR_00F8_AIRCRAFT),
00092 MS(0xD7, STR_00F9_TRANSPORT_ROUTES),
00093 MK(0xB5, STR_00EE_BUILDINGS_INDUSTRIES),
00094 MKEND()
00095 };
00096
00097 static const LegendAndColour _legend_routes[] = {
00098 MK(0xD7, STR_00EB_ROADS),
00099 MK(0x0A, STR_00EC_RAILROADS),
00100 MK(0xB5, STR_00EE_BUILDINGS_INDUSTRIES),
00101 MS(0x56, STR_011B_RAILROAD_STATION),
00102
00103 MK(0xC2, STR_011C_TRUCK_LOADING_BAY),
00104 MK(0xBF, STR_011D_BUS_STATION),
00105 MK(0xB8, STR_011E_AIRPORT_HELIPORT),
00106 MK(0x98, STR_011F_DOCK),
00107 MKEND()
00108 };
00109
00110 static const LegendAndColour _legend_vegetation[] = {
00111 MK(0x52, STR_0120_ROUGH_LAND),
00112 MK(0x54, STR_0121_GRASS_LAND),
00113 MK(0x37, STR_0122_BARE_LAND),
00114 MK(0x25, STR_0123_FIELDS),
00115 MK(0x57, STR_0124_TREES),
00116 MK(0xD0, STR_00FC_FOREST),
00117 MS(0x0A, STR_0125_ROCKS),
00118
00119 MK(0xC2, STR_012A_DESERT),
00120 MK(0x98, STR_012B_SNOW),
00121 MK(0xD7, STR_00F9_TRANSPORT_ROUTES),
00122 MK(0xB5, STR_00EE_BUILDINGS_INDUSTRIES),
00123 MKEND()
00124 };
00125
00126 static const LegendAndColour _legend_land_owners[] = {
00127 MK(0xCA, STR_0126_WATER),
00128 MK(0x54, STR_0127_NO_OWNER),
00129 MK(0xB4, STR_0128_TOWNS),
00130 MK(0x20, STR_0129_INDUSTRIES),
00131 MKEND()
00132 };
00133 #undef MK
00134 #undef MS
00135 #undef MKEND
00136
00139 static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES + 1];
00140
00141 static uint _industry_to_list_pos[NUM_INDUSTRYTYPES];
00142
00146 void BuildIndustriesLegend()
00147 {
00148 const IndustrySpec *indsp;
00149 uint j = 0;
00150
00151
00152 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
00153 indsp = GetIndustrySpec(i);
00154 if (indsp->enabled) {
00155 _legend_from_industries[j].legend = indsp->name;
00156 _legend_from_industries[j].colour = indsp->map_colour;
00157 _legend_from_industries[j].type = i;
00158 _legend_from_industries[j].show_on_map = true;
00159 _legend_from_industries[j].col_break = false;
00160 _legend_from_industries[j].end = false;
00161
00162
00163 _industry_to_list_pos[i] = j;
00164 j++;
00165 }
00166 }
00167
00168 _legend_from_industries[j].end = true;
00169
00170
00171 _smallmap_industry_count = j;
00172 }
00173
00174 static const LegendAndColour * const _legend_table[] = {
00175 _legend_land_contours,
00176 _legend_vehicles,
00177 _legend_from_industries,
00178 _legend_routes,
00179 _legend_vegetation,
00180 _legend_land_owners,
00181 };
00182
00183 #define MKCOLOUR(x) TO_LE32X(x)
00184
00188 static const uint32 _map_height_bits[] = {
00189 MKCOLOUR(0x5A5A5A5A),
00190 MKCOLOUR(0x5A5B5A5B),
00191 MKCOLOUR(0x5B5B5B5B),
00192 MKCOLOUR(0x5B5C5B5C),
00193 MKCOLOUR(0x5C5C5C5C),
00194 MKCOLOUR(0x5C5D5C5D),
00195 MKCOLOUR(0x5D5D5D5D),
00196 MKCOLOUR(0x5D5E5D5E),
00197 MKCOLOUR(0x5E5E5E5E),
00198 MKCOLOUR(0x5E5F5E5F),
00199 MKCOLOUR(0x5F5F5F5F),
00200 MKCOLOUR(0x5F1F5F1F),
00201 MKCOLOUR(0x1F1F1F1F),
00202 MKCOLOUR(0x1F271F27),
00203 MKCOLOUR(0x27272727),
00204 MKCOLOUR(0x27272727),
00205 };
00206 assert_compile(lengthof(_map_height_bits) == MAX_TILE_HEIGHT + 1);
00207
00208 struct AndOr {
00209 uint32 mor;
00210 uint32 mand;
00211 };
00212
00213 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
00214 {
00215 return (colour & mask->mand) | mask->mor;
00216 }
00217
00218
00219 static const AndOr _smallmap_contours_andor[] = {
00220 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00221 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00222 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00223 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00224 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00225 {MKCOLOUR(0x98989898), MKCOLOUR(0x00000000)},
00226 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00227 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00228 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00229 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00230 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00231 {MKCOLOUR(0x000A0A00), MKCOLOUR(0xFF0000FF)},
00232 };
00233
00234 static const AndOr _smallmap_vehicles_andor[] = {
00235 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00236 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00237 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00238 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00239 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00240 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00241 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00242 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00243 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00244 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00245 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00246 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00247 };
00248
00249 static const AndOr _smallmap_vegetation_andor[] = {
00250 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00251 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00252 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00253 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00254 {MKCOLOUR(0x00575700), MKCOLOUR(0xFF0000FF)},
00255 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00256 {MKCOLOUR(0xCACACACA), MKCOLOUR(0x00000000)},
00257 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00258 {MKCOLOUR(0xB5B5B5B5), MKCOLOUR(0x00000000)},
00259 {MKCOLOUR(0x00000000), MKCOLOUR(0xFFFFFFFF)},
00260 {MKCOLOUR(0x00B5B500), MKCOLOUR(0xFF0000FF)},
00261 {MKCOLOUR(0x00D7D700), MKCOLOUR(0xFF0000FF)},
00262 };
00263
00264 typedef uint32 GetSmallMapPixels(TileIndex tile);
00265
00279 static void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, GetSmallMapPixels *proc)
00280 {
00281 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
00282 void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
00283 void *dst_ptr_end = blitter->MoveTo(dst_ptr_abs_end, -4, 0);
00284
00285 do {
00286
00287 uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
00288 if (IsInsideMM(xc, min_xy, MapMaxX()) && IsInsideMM(yc, min_xy, MapMaxY())) {
00289
00290 if (dst < _screen.dst_ptr) continue;
00291 if (dst >= dst_ptr_abs_end) continue;
00292
00293 uint32 val = proc(TileXY(xc, yc)) & mask;
00294 uint8 *val8 = (uint8 *)&val;
00295
00296 if (dst <= dst_ptr_end) {
00297 blitter->SetPixelIfEmpty(dst, 0, 0, val8[0]);
00298 blitter->SetPixelIfEmpty(dst, 1, 0, val8[1]);
00299 blitter->SetPixelIfEmpty(dst, 2, 0, val8[2]);
00300 blitter->SetPixelIfEmpty(dst, 3, 0, val8[3]);
00301 } else {
00302
00303 int i = 0;
00304 do {
00305 blitter->SetPixelIfEmpty(dst, 0, 0, val8[i]);
00306 } while (i++, dst = blitter->MoveTo(dst, 1, 0), dst < dst_ptr_abs_end);
00307 }
00308 }
00309
00310 } while (xc++, yc++, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
00311 }
00312
00313
00314 static inline TileType GetEffectiveTileType(TileIndex tile)
00315 {
00316 TileType t = GetTileType(tile);
00317
00318 if (t == MP_TUNNELBRIDGE) {
00319 TransportType tt = GetTunnelBridgeTransportType(tile);
00320
00321 switch (tt) {
00322 case TRANSPORT_RAIL: t = MP_RAILWAY; break;
00323 case TRANSPORT_ROAD: t = MP_ROAD; break;
00324 default: t = MP_WATER; break;
00325 }
00326 }
00327 return t;
00328 }
00329
00335 static inline uint32 GetSmallMapContoursPixels(TileIndex tile)
00336 {
00337 TileType t = GetEffectiveTileType(tile);
00338
00339 return
00340 ApplyMask(_map_height_bits[TileHeight(tile)], &_smallmap_contours_andor[t]);
00341 }
00342
00349 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile)
00350 {
00351 TileType t = GetEffectiveTileType(tile);
00352
00353 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00354 }
00355
00362 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile)
00363 {
00364 TileType t = GetEffectiveTileType(tile);
00365
00366 if (t == MP_INDUSTRY) {
00367
00368 if (_legend_from_industries[_industry_to_list_pos[GetIndustryByTile(tile)->type]].show_on_map) {
00369 return GetIndustrySpec(GetIndustryByTile(tile)->type)->map_colour * 0x01010101;
00370 } else {
00371
00372 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[MP_CLEAR]);
00373 }
00374 }
00375
00376 return ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00377 }
00378
00385 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile)
00386 {
00387 TileType t = GetEffectiveTileType(tile);
00388 uint32 bits;
00389
00390 if (t == MP_STATION) {
00391 switch (GetStationType(tile)) {
00392 case STATION_RAIL: bits = MKCOLOUR(0x56565656); break;
00393 case STATION_AIRPORT: bits = MKCOLOUR(0xB8B8B8B8); break;
00394 case STATION_TRUCK: bits = MKCOLOUR(0xC2C2C2C2); break;
00395 case STATION_BUS: bits = MKCOLOUR(0xBFBFBFBF); break;
00396 case STATION_DOCK: bits = MKCOLOUR(0x98989898); break;
00397 default: bits = MKCOLOUR(0xFFFFFFFF); break;
00398 }
00399 } else {
00400
00401 bits = ApplyMask(MKCOLOUR(0x54545454), &_smallmap_contours_andor[t]);
00402 }
00403 return bits;
00404 }
00405
00406
00407 static const uint32 _vegetation_clear_bits[] = {
00408 MKCOLOUR(0x54545454),
00409 MKCOLOUR(0x52525252),
00410 MKCOLOUR(0x0A0A0A0A),
00411 MKCOLOUR(0x25252525),
00412 MKCOLOUR(0x98989898),
00413 MKCOLOUR(0xC2C2C2C2),
00414 MKCOLOUR(0x54545454),
00415 MKCOLOUR(0x54545454),
00416 };
00417
00418 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile)
00419 {
00420 TileType t = GetEffectiveTileType(tile);
00421 uint32 bits;
00422
00423 switch (t) {
00424 case MP_CLEAR:
00425 if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) {
00426 bits = MKCOLOUR(0x37373737);
00427 } else {
00428 bits = _vegetation_clear_bits[GetClearGround(tile)];
00429 }
00430 break;
00431
00432 case MP_INDUSTRY:
00433 bits = GetIndustrySpec(GetIndustryByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR(0xD0D0D0D0) : MKCOLOUR(0xB5B5B5B5);
00434 break;
00435
00436 case MP_TREES:
00437 if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) {
00438 bits = (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR(0x98575798) : MKCOLOUR(0xC25757C2);
00439 } else {
00440 bits = MKCOLOUR(0x54575754);
00441 }
00442 break;
00443
00444 default:
00445 bits = ApplyMask(MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
00446 break;
00447 }
00448
00449 return bits;
00450 }
00451
00452
00453 static uint32 _owner_colours[OWNER_END + 1];
00454
00461 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile)
00462 {
00463 Owner o;
00464
00465 switch (GetTileType(tile)) {
00466 case MP_INDUSTRY: o = OWNER_END; break;
00467 case MP_HOUSE: o = OWNER_TOWN; break;
00468 default: o = GetTileOwner(tile); break;
00469
00470
00471
00472
00473 }
00474
00475 return _owner_colours[o];
00476 }
00477
00478
00479 static const uint32 _smallmap_mask_left[3] = {
00480 MKCOLOUR(0xFF000000),
00481 MKCOLOUR(0xFFFF0000),
00482 MKCOLOUR(0xFFFFFF00),
00483 };
00484
00485 static const uint32 _smallmap_mask_right[] = {
00486 MKCOLOUR(0x000000FF),
00487 MKCOLOUR(0x0000FFFF),
00488 MKCOLOUR(0x00FFFFFF),
00489 };
00490
00491
00492
00493 static GetSmallMapPixels *_smallmap_draw_procs[] = {
00494 GetSmallMapContoursPixels,
00495 GetSmallMapVehiclesPixels,
00496 GetSmallMapIndustriesPixels,
00497 GetSmallMapRoutesPixels,
00498 GetSmallMapVegetationPixels,
00499 GetSmallMapOwnerPixels,
00500 };
00501
00502 static const byte _vehicle_type_colours[6] = {
00503 184, 191, 152, 15, 215, 184
00504 };
00505
00506
00507 static void DrawVertMapIndicator(int x, int y, int x2, int y2)
00508 {
00509 GfxFillRect(x, y, x2, y + 3, 69);
00510 GfxFillRect(x, y2 - 3, x2, y2, 69);
00511 }
00512
00513 static void DrawHorizMapIndicator(int x, int y, int x2, int y2)
00514 {
00515 GfxFillRect(x, y, x + 3, y2, 69);
00516 GfxFillRect(x2 - 3, y, x2, y2, 69);
00517 }
00518
00519 enum SmallMapWindowWidgets {
00520 SM_WIDGET_MAP_BORDER = 3,
00521 SM_WIDGET_MAP,
00522 SM_WIDGET_LEGEND,
00523 SM_WIDGET_BUTTONSPANEL,
00524 SM_WIDGET_CONTOUR,
00525 SM_WIDGET_VEHICLES,
00526 SM_WIDGET_INDUSTRIES,
00527 SM_WIDGET_ROUTES,
00528 SM_WIDGET_VEGETATION,
00529 SM_WIDGET_OWNERS,
00530 SM_WIDGET_CENTERMAP,
00531 SM_WIDGET_TOGGLETOWNNAME,
00532 SM_WIDGET_BOTTOMPANEL,
00533 SM_WIDGET_ENABLEINDUSTRIES,
00534 SM_WIDGET_DISABLEINDUSTRIES,
00535 SM_WIDGET_RESIZEBOX,
00536 };
00537
00538 class SmallMapWindow : public Window
00539 {
00540 enum SmallMapType {
00541 SMT_CONTOUR,
00542 SMT_VEHICLES,
00543 SMT_INDUSTRY,
00544 SMT_ROUTES,
00545 SMT_VEGETATION,
00546 SMT_OWNER,
00547 };
00548
00549 static SmallMapType map_type;
00550 static bool show_towns;
00551
00552 int32 scroll_x;
00553 int32 scroll_y;
00554 int32 subscroll;
00555 uint8 refresh;
00556
00557 static const int COLUMN_WIDTH = 119;
00558 static const int MIN_LEGEND_HEIGHT = 6 * 7;
00559
00560 public:
00575 void DrawSmallMap(DrawPixelInfo *dpi)
00576 {
00577 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
00578 DrawPixelInfo *old_dpi;
00579 int dx, dy, x, y, x2, y2;
00580 void *ptr;
00581 int tile_x;
00582 int tile_y;
00583 ViewPort *vp;
00584
00585 old_dpi = _cur_dpi;
00586 _cur_dpi = dpi;
00587
00588
00589 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 0);
00590
00591
00592 if (this->map_type == SMT_OWNER) {
00593 const Company *c;
00594
00595
00596 _owner_colours[OWNER_TOWN] = MKCOLOUR(0xB4B4B4B4);
00597 _owner_colours[OWNER_NONE] = MKCOLOUR(0x54545454);
00598 _owner_colours[OWNER_WATER] = MKCOLOUR(0xCACACACA);
00599 _owner_colours[OWNER_END] = MKCOLOUR(0x20202020);
00600
00601
00602 FOR_ALL_COMPANIES(c) {
00603 _owner_colours[c->index] =
00604 _colour_gradient[c->colour][5] * 0x01010101;
00605 }
00606 }
00607
00608 tile_x = this->scroll_x / TILE_SIZE;
00609 tile_y = this->scroll_y / TILE_SIZE;
00610
00611 dx = dpi->left + this->subscroll;
00612 tile_x -= dx / 4;
00613 tile_y += dx / 4;
00614 dx &= 3;
00615
00616 dy = dpi->top;
00617 tile_x += dy / 2;
00618 tile_y += dy / 2;
00619
00620 if (dy & 1) {
00621 tile_x++;
00622 dx += 2;
00623 if (dx > 3) {
00624 dx -= 4;
00625 tile_x--;
00626 tile_y++;
00627 }
00628 }
00629
00630 ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
00631 x = - dx - 4;
00632 y = 0;
00633
00634 for (;;) {
00635 uint32 mask = 0xFFFFFFFF;
00636 int reps;
00637 int t;
00638
00639
00640 if (x < 0) {
00641 if (x < -3) goto skip_column;
00642
00643 mask = _smallmap_mask_left[x + 3];
00644 }
00645
00646
00647 t = dpi->width - x;
00648 if (t < 4) {
00649 if (t <= 0) break;
00650
00651 mask &= _smallmap_mask_right[t - 1];
00652 }
00653
00654
00655 reps = (dpi->height - y + 1) / 2;
00656 if (reps > 0) {
00657 DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[this->map_type]);
00658 }
00659
00660 skip_column:
00661 if (y == 0) {
00662 tile_y++;
00663 y++;
00664 ptr = blitter->MoveTo(ptr, 0, 1);
00665 } else {
00666 tile_x--;
00667 y--;
00668 ptr = blitter->MoveTo(ptr, 0, -1);
00669 }
00670 ptr = blitter->MoveTo(ptr, 2, 0);
00671 x += 2;
00672 }
00673
00674
00675 if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) {
00676 Vehicle *v;
00677 bool skip;
00678 byte colour;
00679
00680 FOR_ALL_VEHICLES(v) {
00681 if (v->type != VEH_EFFECT &&
00682 (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
00683
00684 Point pt = RemapCoords(
00685 v->x_pos / TILE_SIZE - this->scroll_x / TILE_SIZE,
00686 v->y_pos / TILE_SIZE - this->scroll_y / TILE_SIZE,
00687 0);
00688 x = pt.x;
00689 y = pt.y;
00690
00691
00692 y -= dpi->top;
00693 if (!IsInsideMM(y, 0, dpi->height)) continue;
00694
00695
00696 skip = false;
00697
00698
00699 x -= this->subscroll + 3 + dpi->left;
00700
00701 if (x < 0) {
00702
00703
00704 if (++x != 0) continue;
00705 skip = true;
00706 } else if (x >= dpi->width - 1) {
00707
00708 if (x != dpi->width - 1) continue;
00709 skip = true;
00710 }
00711
00712
00713 colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : 0xF;
00714
00715
00716 blitter->SetPixel(dpi->dst_ptr, x, y, colour);
00717 if (!skip) blitter->SetPixel(dpi->dst_ptr, x + 1, y, colour);
00718 }
00719 }
00720 }
00721
00722 if (this->show_towns) {
00723 const Town *t;
00724
00725 FOR_ALL_TOWNS(t) {
00726
00727 Point pt = RemapCoords(
00728 (int)(TileX(t->xy) * TILE_SIZE - this->scroll_x) / TILE_SIZE,
00729 (int)(TileY(t->xy) * TILE_SIZE - this->scroll_y) / TILE_SIZE,
00730 0);
00731 x = pt.x - this->subscroll + 3 - (t->sign.width_2 >> 1);
00732 y = pt.y;
00733
00734
00735 if (x + t->sign.width_2 > dpi->left &&
00736 x < dpi->left + dpi->width &&
00737 y + 6 > dpi->top &&
00738 y < dpi->top + dpi->height) {
00739
00740 SetDParam(0, t->index);
00741 DrawString(x, y, STR_2056, TC_WHITE);
00742 }
00743 }
00744 }
00745
00746
00747 {
00748 Point pt;
00749
00750
00751 vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
00752
00753 pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00754
00755 x = vp->virtual_left - pt.x;
00756 y = vp->virtual_top - pt.y;
00757 x2 = (x + vp->virtual_width) / TILE_SIZE;
00758 y2 = (y + vp->virtual_height) / TILE_SIZE;
00759 x /= TILE_SIZE;
00760 y /= TILE_SIZE;
00761
00762 x -= this->subscroll;
00763 x2 -= this->subscroll;
00764
00765 DrawVertMapIndicator(x, y, x, y2);
00766 DrawVertMapIndicator(x2, y, x2, y2);
00767
00768 DrawHorizMapIndicator(x, y, x2, y);
00769 DrawHorizMapIndicator(x, y2, x2, y2);
00770 }
00771 _cur_dpi = old_dpi;
00772 }
00773
00774 void SmallMapCenterOnCurrentPos()
00775 {
00776 int x, y;
00777 ViewPort *vp;
00778 vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
00779
00780 x = ((vp->virtual_width - (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) * TILE_SIZE) / 2 + vp->virtual_left) / 4;
00781 y = ((vp->virtual_height - (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) * TILE_SIZE) / 2 + vp->virtual_top ) / 2 - TILE_SIZE * 2;
00782 this->scroll_x = (y - x) & ~0xF;
00783 this->scroll_y = (x + y) & ~0xF;
00784 this->SetDirty();
00785 }
00786
00787 void ResizeLegend()
00788 {
00789 Widget *legend = &this->widget[SM_WIDGET_LEGEND];
00790 int rows = (legend->bottom - legend->top) - 1;
00791 int columns = (legend->right - legend->left) / COLUMN_WIDTH;
00792 int new_rows = (this->map_type == SMT_INDUSTRY) ? ((_smallmap_industry_count + columns - 1) / columns) * 6 : MIN_LEGEND_HEIGHT;
00793
00794 new_rows = max(new_rows, MIN_LEGEND_HEIGHT);
00795
00796 if (new_rows != rows) {
00797 this->SetDirty();
00798
00799
00800
00801 legend->top--;
00802
00803 ResizeWindowForWidget(this, SM_WIDGET_BUTTONSPANEL, 0, new_rows - rows);
00804 legend->top++;
00805
00806
00807 ResizeWindowForWidget(this, SM_WIDGET_MAP_BORDER, 0, rows - new_rows);
00808
00809
00810 this->widget[SM_WIDGET_MAP].bottom += rows - new_rows;
00811
00812 this->SetDirty();
00813 }
00814 }
00815
00816 SmallMapWindow(const WindowDesc *desc, int window_number) : Window(desc, window_number)
00817 {
00818 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00819 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00820
00821 this->SmallMapCenterOnCurrentPos();
00822 this->FindWindowPlacementAndResize(desc);
00823 }
00824
00825 virtual void OnPaint()
00826 {
00827 DrawPixelInfo new_dpi;
00828
00829
00830 this->SetWidgetHiddenState(SM_WIDGET_ENABLEINDUSTRIES, this->map_type != SMT_INDUSTRY);
00831 this->SetWidgetHiddenState(SM_WIDGET_DISABLEINDUSTRIES, this->map_type != SMT_INDUSTRY);
00832
00833
00834 SetDParam(0, STR_00E5_CONTOURS + this->map_type);
00835 this->DrawWidgets();
00836
00837 const Widget *legend = &this->widget[SM_WIDGET_LEGEND];
00838
00839 int y_org = legend->top + 1;
00840 int x = 4;
00841 int y = y_org;
00842
00843 for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) {
00844 if (tbl->col_break || y >= legend->bottom) {
00845
00846
00847 x += COLUMN_WIDTH;
00848 y = y_org;
00849 }
00850
00851 if (this->map_type == SMT_INDUSTRY) {
00852
00853
00854 SetDParam(0, tbl->legend);
00855 assert(tbl->type < NUM_INDUSTRYTYPES);
00856 SetDParam(1, _industry_counts[tbl->type]);
00857 if (!tbl->show_on_map) {
00858
00859
00860 DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_GREY);
00861 } else {
00862 DrawString(x + 11, y, STR_SMALLMAP_INDUSTRY, TC_BLACK);
00863 GfxFillRect(x, y + 1, x + 8, y + 5, 0);
00864 }
00865 } else {
00866
00867 GfxFillRect(x, y + 1, x + 8, y + 5, 0);
00868 DrawString(x + 11, y, tbl->legend, TC_FROMSTRING);
00869 }
00870 GfxFillRect(x + 1, y + 2, x + 7, y + 4, tbl->colour);
00871
00872 y += 6;
00873 }
00874
00875 const Widget *wi = &this->widget[SM_WIDGET_MAP];
00876 if (!FillDrawPixelInfo(&new_dpi, wi->left + 1, wi->top + 1, wi->right - wi->left - 1, wi->bottom - wi->top - 1)) return;
00877
00878 this->DrawSmallMap(&new_dpi);
00879 }
00880
00881 virtual void OnClick(Point pt, int widget)
00882 {
00883 switch (widget) {
00884 case SM_WIDGET_MAP: {
00885
00886
00887
00888
00889
00890
00891
00892
00893 _left_button_clicked = false;
00894
00895 Point pt = RemapCoords(this->scroll_x, this->scroll_y, 0);
00896 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
00897 w->viewport->follow_vehicle = INVALID_VEHICLE;
00898 w->viewport->dest_scrollpos_x = pt.x + ((_cursor.pos.x - this->left + 2) << 4) - (w->viewport->virtual_width >> 1);
00899 w->viewport->dest_scrollpos_y = pt.y + ((_cursor.pos.y - this->top - 16) << 4) - (w->viewport->virtual_height >> 1);
00900
00901 this->SetDirty();
00902 } break;
00903
00904 case SM_WIDGET_CONTOUR:
00905 case SM_WIDGET_VEHICLES:
00906 case SM_WIDGET_INDUSTRIES:
00907 case SM_WIDGET_ROUTES:
00908 case SM_WIDGET_VEGETATION:
00909 case SM_WIDGET_OWNERS:
00910 this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
00911 this->map_type = (SmallMapType)(widget - SM_WIDGET_CONTOUR);
00912 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
00913
00914 this->ResizeLegend();
00915
00916 this->SetDirty();
00917 SndPlayFx(SND_15_BEEP);
00918 break;
00919
00920 case SM_WIDGET_CENTERMAP:
00921 this->SmallMapCenterOnCurrentPos();
00922
00923 this->SetDirty();
00924 SndPlayFx(SND_15_BEEP);
00925 break;
00926
00927 case SM_WIDGET_TOGGLETOWNNAME:
00928 this->show_towns = !this->show_towns;
00929 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
00930
00931 this->SetDirty();
00932 SndPlayFx(SND_15_BEEP);
00933 break;
00934
00935 case SM_WIDGET_LEGEND:
00936
00937 if (this->map_type == SMT_INDUSTRY) {
00938
00939 Widget *wi = &this->widget[SM_WIDGET_LEGEND];
00940 uint column = (pt.x - 4) / COLUMN_WIDTH;
00941 uint line = (pt.y - wi->top - 2) / 6;
00942 int rows_per_column = (wi->bottom - wi->top) / 6;
00943
00944
00945 int industry_pos = (column * rows_per_column) + line;
00946 if (industry_pos < _smallmap_industry_count) {
00947 _legend_from_industries[industry_pos].show_on_map = !_legend_from_industries[industry_pos].show_on_map;
00948 }
00949
00950
00951 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
00952 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
00953 this->SetDirty();
00954 }
00955 break;
00956
00957 case SM_WIDGET_ENABLEINDUSTRIES:
00958 for (int i = 0; i != _smallmap_industry_count; i++) {
00959 _legend_from_industries[i].show_on_map = true;
00960 }
00961
00962 this->LowerWidget(SM_WIDGET_ENABLEINDUSTRIES);
00963 this->RaiseWidget(SM_WIDGET_DISABLEINDUSTRIES);
00964 this->SetDirty();
00965 break;
00966
00967 case SM_WIDGET_DISABLEINDUSTRIES:
00968 for (int i = 0; i != _smallmap_industry_count; i++) {
00969 _legend_from_industries[i].show_on_map = false;
00970 }
00971
00972 this->RaiseWidget(SM_WIDGET_ENABLEINDUSTRIES);
00973 this->LowerWidget(SM_WIDGET_DISABLEINDUSTRIES);
00974 this->SetDirty();
00975 break;
00976 }
00977 }
00978
00979 virtual void OnRightClick(Point pt, int widget)
00980 {
00981 if (widget == SM_WIDGET_MAP) {
00982 if (_scrolling_viewport) return;
00983 _scrolling_viewport = true;
00984 _cursor.delta.x = 0;
00985 _cursor.delta.y = 0;
00986 }
00987 }
00988
00989 virtual void OnTick()
00990 {
00991
00992 if ((++this->refresh & 0x1F) == 0) this->SetDirty();
00993 }
00994
00995 virtual void OnScroll(Point delta)
00996 {
00997 _cursor.fix_at = true;
00998
00999 int x = this->scroll_x;
01000 int y = this->scroll_y;
01001
01002 int sub = this->subscroll + delta.x;
01003
01004 x -= (sub >> 2) << 4;
01005 y += (sub >> 2) << 4;
01006 sub &= 3;
01007
01008 x += (delta.y >> 1) << 4;
01009 y += (delta.y >> 1) << 4;
01010
01011 if (delta.y & 1) {
01012 x += TILE_SIZE;
01013 sub += 2;
01014 if (sub > 3) {
01015 sub -= 4;
01016 x -= TILE_SIZE;
01017 y += TILE_SIZE;
01018 }
01019 }
01020
01021 int hx = (this->widget[SM_WIDGET_MAP].right - this->widget[SM_WIDGET_MAP].left) / 2;
01022 int hy = (this->widget[SM_WIDGET_MAP].bottom - this->widget[SM_WIDGET_MAP].top ) / 2;
01023 int hvx = hx * -4 + hy * 8;
01024 int hvy = hx * 4 + hy * 8;
01025 if (x < -hvx) {
01026 x = -hvx;
01027 sub = 0;
01028 }
01029 if (x > (int)MapMaxX() * TILE_SIZE - hvx) {
01030 x = MapMaxX() * TILE_SIZE - hvx;
01031 sub = 0;
01032 }
01033 if (y < -hvy) {
01034 y = -hvy;
01035 sub = 0;
01036 }
01037 if (y > (int)MapMaxY() * TILE_SIZE - hvy) {
01038 y = MapMaxY() * TILE_SIZE - hvy;
01039 sub = 0;
01040 }
01041
01042 this->scroll_x = x;
01043 this->scroll_y = y;
01044 this->subscroll = sub;
01045
01046 this->SetDirty();
01047 }
01048
01049 virtual void OnResize(Point new_size, Point delta)
01050 {
01051 if (delta.x != 0 && this->map_type == SMT_INDUSTRY) this->ResizeLegend();
01052 }
01053 };
01054
01055 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
01056 bool SmallMapWindow::show_towns = true;
01057
01058 static const WindowDesc _smallmap_desc(
01059 WDP_AUTO, WDP_AUTO, 350, 214, 446, 314,
01060 WC_SMALLMAP, WC_NONE,
01061 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
01062 _smallmap_widgets
01063 );
01064
01065 void ShowSmallMap()
01066 {
01067 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
01068 }
01069
01070
01071 static const Widget _extra_view_port_widgets[] = {
01072 { WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
01073 { WWT_CAPTION, RESIZE_RIGHT, COLOUR_GREY, 11, 287, 0, 13, STR_EXTRA_VIEW_PORT_TITLE, STR_018C_WINDOW_TITLE_DRAG_THIS},
01074 { WWT_STICKYBOX, RESIZE_LR, COLOUR_GREY, 288, 299, 0, 13, 0x0, STR_STICKY_BUTTON},
01075 { WWT_PANEL, RESIZE_RB, COLOUR_GREY, 0, 299, 14, 33, 0x0, STR_NULL},
01076 { WWT_INSET, RESIZE_RB, COLOUR_GREY, 2, 297, 16, 31, 0x0, STR_NULL},
01077 { WWT_PUSHIMGBTN, RESIZE_TB, COLOUR_GREY, 0, 21, 34, 55, SPR_IMG_ZOOMIN, STR_017F_ZOOM_THE_VIEW_IN},
01078 { WWT_PUSHIMGBTN, RESIZE_TB, COLOUR_GREY, 22, 43, 34, 55, SPR_IMG_ZOOMOUT, STR_0180_ZOOM_THE_VIEW_OUT},
01079 { WWT_PUSHTXTBTN, RESIZE_TB, COLOUR_GREY, 44, 171, 34, 55, STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW, STR_EXTRA_VIEW_MOVE_MAIN_TO_VIEW_TT},
01080 { WWT_PUSHTXTBTN, RESIZE_TB, COLOUR_GREY, 172, 298, 34, 55, STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN, STR_EXTRA_VIEW_MOVE_VIEW_TO_MAIN_TT},
01081 { WWT_PANEL, RESIZE_RTB, COLOUR_GREY, 299, 299, 34, 55, 0x0, STR_NULL},
01082 { WWT_PANEL, RESIZE_RTB, COLOUR_GREY, 0, 287, 56, 67, 0x0, STR_NULL},
01083 { WWT_RESIZEBOX, RESIZE_LRTB, COLOUR_GREY, 288, 299, 56, 67, 0x0, STR_RESIZE_BUTTON},
01084 { WIDGETS_END},
01085 };
01086
01087 class ExtraViewportWindow : public Window
01088 {
01089 enum ExtraViewportWindowWidgets {
01090 EVW_CLOSE,
01091 EVW_CAPTION,
01092 EVW_STICKY,
01093 EVW_BACKGROUND,
01094 EVW_VIEWPORT,
01095 EVW_ZOOMIN,
01096 EVW_ZOOMOUT,
01097 EVW_MAIN_TO_VIEW,
01098 EVW_VIEW_TO_MAIN,
01099 EVW_SPACER1,
01100 EVW_SPACER2,
01101 EVW_RESIZE,
01102 };
01103
01104 public:
01105 ExtraViewportWindow(const WindowDesc *desc, int window_number, TileIndex tile) : Window(desc, window_number)
01106 {
01107
01108 InitializeWindowViewport(this, 3, 17, this->widget[EVW_VIEWPORT].right - this->widget[EVW_VIEWPORT].left - 1, this->widget[EVW_VIEWPORT].bottom - this->widget[EVW_VIEWPORT].top - 1, 0, ZOOM_LVL_VIEWPORT);
01109
01110 this->DisableWidget(EVW_ZOOMIN);
01111 this->FindWindowPlacementAndResize(desc);
01112
01113 Point pt;
01114 if (tile == INVALID_TILE) {
01115
01116 const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
01117
01118
01119 pt.x = w->viewport->scrollpos_x + w->viewport->virtual_height / 2;
01120 pt.y = w->viewport->scrollpos_y + w->viewport->virtual_height / 2;
01121 } else {
01122 pt = RemapCoords(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2, TileHeight(tile));
01123 }
01124
01125 this->viewport->scrollpos_x = pt.x - ((this->widget[EVW_VIEWPORT].right - this->widget[EVW_VIEWPORT].left) - 1) / 2;
01126 this->viewport->scrollpos_y = pt.y - ((this->widget[EVW_VIEWPORT].bottom - this->widget[EVW_VIEWPORT].top) - 1) / 2;
01127 this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
01128 this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
01129
01130 }
01131
01132 virtual void OnPaint()
01133 {
01134
01135 SetDParam(0, this->window_number + 1);
01136
01137 this->DrawWidgets();
01138 this->DrawViewport();
01139 }
01140
01141 virtual void OnClick(Point pt, int widget)
01142 {
01143 switch (widget) {
01144 case EVW_ZOOMIN: DoZoomInOutWindow(ZOOM_IN, this); break;
01145 case EVW_ZOOMOUT: DoZoomInOutWindow(ZOOM_OUT, this); break;
01146
01147 case EVW_MAIN_TO_VIEW: {
01148 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
01149 int x = this->viewport->scrollpos_x;
01150 int y = this->viewport->scrollpos_y;
01151
01152
01153 w->viewport->dest_scrollpos_x = x - (w->viewport->virtual_width - this->viewport->virtual_width) / 2;
01154 w->viewport->dest_scrollpos_y = y - (w->viewport->virtual_height - this->viewport->virtual_height) / 2;
01155 w->viewport->follow_vehicle = INVALID_VEHICLE;
01156 } break;
01157
01158 case EVW_VIEW_TO_MAIN: {
01159 const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
01160 int x = w->viewport->scrollpos_x;
01161 int y = w->viewport->scrollpos_y;
01162
01163 this->viewport->dest_scrollpos_x = x + (w->viewport->virtual_width - this->viewport->virtual_width) / 2;
01164 this->viewport->dest_scrollpos_y = y + (w->viewport->virtual_height - this->viewport->virtual_height) / 2;
01165 } break;
01166 }
01167 }
01168
01169 virtual void OnResize(Point new_size, Point delta)
01170 {
01171 this->viewport->width += delta.x;
01172 this->viewport->height += delta.y;
01173 this->viewport->virtual_width += delta.x;
01174 this->viewport->virtual_height += delta.y;
01175 }
01176
01177 virtual void OnScroll(Point delta)
01178 {
01179 const ViewPort *vp = IsPtInWindowViewport(this, _cursor.pos.x, _cursor.pos.y);
01180 if (vp == NULL) return;
01181
01182 this->viewport->scrollpos_x += ScaleByZoom(delta.x, vp->zoom);
01183 this->viewport->scrollpos_y += ScaleByZoom(delta.y, vp->zoom);
01184 this->viewport->dest_scrollpos_x = this->viewport->scrollpos_x;
01185 this->viewport->dest_scrollpos_y = this->viewport->scrollpos_y;
01186 }
01187
01188 virtual void OnMouseWheel(int wheel)
01189 {
01190 ZoomInOrOutToCursorWindow(wheel < 0, this);
01191 }
01192
01193 virtual void OnInvalidateData(int data = 0)
01194 {
01195
01196 HandleZoomMessage(this, this->viewport, EVW_ZOOMIN, EVW_ZOOMOUT);
01197 }
01198 };
01199
01200 static const WindowDesc _extra_view_port_desc(
01201 WDP_AUTO, WDP_AUTO, 300, 68, 300, 268,
01202 WC_EXTRA_VIEW_PORT, WC_NONE,
01203 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
01204 _extra_view_port_widgets
01205 );
01206
01207 void ShowExtraViewPortWindow(TileIndex tile)
01208 {
01209 int i = 0;
01210
01211
01212 while (FindWindowById(WC_EXTRA_VIEW_PORT, i) != NULL) i++;
01213
01214 new ExtraViewportWindow(&_extra_view_port_desc, i, tile);
01215 }
01216
01225 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
01226 {
01227 bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
01228
01229
01230
01231
01232
01233 if (res) return res;
01234
01235 SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
01236 if (w != NULL) w->SmallMapCenterOnCurrentPos();
01237
01238 return res;
01239 }