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