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 "town.h"
00021 #include "blitter/factory.hpp"
00022 #include "tunnelbridge_map.h"
00023 #include "strings_func.h"
00024 #include "core/endian_func.hpp"
00025 #include "vehicle_base.h"
00026 #include "sound_func.h"
00027 #include "window_func.h"
00028 #include "company_base.h"
00029
00030
00031 #include "company_func.h"
00032 #include "station_base.h"
00033
00034 #include "table/strings.h"
00035
00036
00037 #include <vector>
00038
00040 enum SmallMapWindowWidgets {
00041 SM_WIDGET_CAPTION,
00042 SM_WIDGET_MAP_BORDER,
00043 SM_WIDGET_MAP,
00044 SM_WIDGET_LEGEND,
00045 SM_WIDGET_BLANK,
00046 SM_WIDGET_ZOOM_IN,
00047 SM_WIDGET_ZOOM_OUT,
00048 SM_WIDGET_CONTOUR,
00049 SM_WIDGET_VEHICLES,
00050 SM_WIDGET_INDUSTRIES,
00051 SM_WIDGET_LINKSTATS,
00052 SM_WIDGET_ROUTES,
00053 SM_WIDGET_VEGETATION,
00054 SM_WIDGET_OWNERS,
00055 SM_WIDGET_CENTERMAP,
00056 SM_WIDGET_TOGGLETOWNNAME,
00057 SM_WIDGET_SELECT_BUTTONS,
00058 SM_WIDGET_ENABLE_ALL,
00059 SM_WIDGET_DISABLE_ALL,
00060 SM_WIDGET_SHOW_HEIGHT,
00061 };
00062
00063 static int _smallmap_industry_count;
00064 static int _smallmap_company_count;
00065 static const int NUM_NO_COMPANY_ENTRIES = 4;
00066 static int _smallmap_cargo_count;
00067
00068 static const uint8 PC_ROUGH_LAND = 0x52;
00069 static const uint8 PC_GRASS_LAND = 0x54;
00070 static const uint8 PC_BARE_LAND = 0x37;
00071 static const uint8 PC_FIELDS = 0x25;
00072 static const uint8 PC_TREES = 0x57;
00073 static const uint8 PC_WATER = 0xCA;
00074
00075 enum SmallMapStats {
00076 STAT_CAPACITY,
00077 STAT_BEGIN = STAT_CAPACITY,
00078 STAT_USAGE,
00079 STAT_PLANNED,
00080 STAT_SENT,
00081 STAT_TEXT,
00082 STAT_GRAPH,
00083 STAT_END,
00084 NUM_STATS = STAT_END,
00085 };
00086
00088 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
00089
00091 #define MC(height) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, false}
00092
00097 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true}
00098
00100 #define MCS(height) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, true}
00101
00103 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false}
00104
00106 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false}
00107
00109 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false}
00110
00112 struct LegendAndColour {
00113 uint8 colour;
00114 StringID legend;
00115 IndustryType type;
00116 uint8 height;
00117 CompanyID company;
00118 bool show_on_map;
00119 bool end;
00120 bool col_break;
00121 };
00122
00124 static LegendAndColour _legend_land_contours_old[] = {
00125
00126 MC(1),
00127 MC(5),
00128 MC(9),
00129 MC(13),
00130 MC(15),
00131
00132 MS(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
00133 MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
00134 MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
00135 MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00136 MK(PC_WHITE, STR_SMALLMAP_LEGENDA_VEHICLES),
00137 MKEND()
00138 };
00139
00141 static LegendAndColour _legend_land_contours_extended[] = {
00142
00143 MC(1),
00144 MC(16),
00145 MC(32),
00146 MC(48),
00147 MC(64),
00148 MC(80),
00149
00150 MCS(96),
00151 MC(112),
00152 MC(128),
00153 MC(144),
00154 MC(160),
00155 MC(176),
00156
00157 MCS(192),
00158 MC(208),
00159 MC(224),
00160 MC(240),
00161 MC(255),
00162
00163 MS(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
00164 MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
00165 MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_STATIONS_AIRPORTS_DOCKS),
00166 MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00167 MK(PC_WHITE, STR_SMALLMAP_LEGENDA_VEHICLES),
00168 MKEND()
00169 };
00170
00171 static const LegendAndColour _legend_vehicles[] = {
00172 MK(PC_RED, STR_SMALLMAP_LEGENDA_TRAINS),
00173 MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_ROAD_VEHICLES),
00174 MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SHIPS),
00175 MK(PC_WHITE, STR_SMALLMAP_LEGENDA_AIRCRAFT),
00176
00177 MS(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
00178 MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00179 MKEND()
00180 };
00181
00182 static const LegendAndColour _legend_routes[] = {
00183 MK(PC_BLACK, STR_SMALLMAP_LEGENDA_ROADS),
00184 MK(PC_GREY, STR_SMALLMAP_LEGENDA_RAILROADS),
00185 MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00186
00187 MS(PC_VERY_DARK_BROWN, STR_SMALLMAP_LEGENDA_RAILROAD_STATION),
00188 MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
00189 MK(PC_YELLOW, STR_SMALLMAP_LEGENDA_BUS_STATION),
00190 MK(PC_RED, STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
00191 MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_DOCK),
00192 MKEND()
00193 };
00194
00195 static const LegendAndColour _legend_vegetation[] = {
00196 MK(PC_ROUGH_LAND, STR_SMALLMAP_LEGENDA_ROUGH_LAND),
00197 MK(PC_GRASS_LAND, STR_SMALLMAP_LEGENDA_GRASS_LAND),
00198 MK(PC_BARE_LAND, STR_SMALLMAP_LEGENDA_BARE_LAND),
00199 MK(PC_FIELDS, STR_SMALLMAP_LEGENDA_FIELDS),
00200 MK(PC_TREES, STR_SMALLMAP_LEGENDA_TREES),
00201 MK(PC_GREEN, STR_SMALLMAP_LEGENDA_FOREST),
00202
00203 MS(PC_GREY, STR_SMALLMAP_LEGENDA_ROCKS),
00204 MK(PC_ORANGE, STR_SMALLMAP_LEGENDA_DESERT),
00205 MK(PC_LIGHT_BLUE, STR_SMALLMAP_LEGENDA_SNOW),
00206 MK(PC_BLACK, STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
00207 MK(PC_DARK_RED, STR_SMALLMAP_LEGENDA_BUILDINGS_INDUSTRIES),
00208 MKEND()
00209 };
00210
00211 static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1] = {
00212 MO(PC_WATER, STR_SMALLMAP_LEGENDA_WATER),
00213 MO(0x00, STR_SMALLMAP_LEGENDA_NO_OWNER),
00214 MO(PC_DARK_RED, STR_SMALLMAP_LEGENDA_TOWNS),
00215 MO(PC_DARK_GREY, STR_SMALLMAP_LEGENDA_INDUSTRIES),
00216
00217 MOEND(),
00218 };
00219
00220 #undef MK
00221 #undef MC
00222 #undef MS
00223 #undef MCS
00224 #undef MO
00225 #undef MOEND
00226 #undef MKEND
00227
00232 static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES + 1];
00234 static uint _industry_to_list_pos[NUM_INDUSTRYTYPES];
00236 static bool _smallmap_show_heightmap = false;
00238 static uint _company_to_list_pos[MAX_COMPANIES];
00239
00243 void BuildIndustriesLegend()
00244 {
00245 uint j = 0;
00246
00247
00248 for (uint8 i = 0; i < NUM_INDUSTRYTYPES; i++) {
00249 IndustryType ind = _sorted_industry_types[i];
00250 const IndustrySpec *indsp = GetIndustrySpec(ind);
00251 if (indsp->enabled) {
00252 _legend_from_industries[j].legend = indsp->name;
00253 _legend_from_industries[j].colour = indsp->map_colour;
00254 _legend_from_industries[j].type = ind;
00255 _legend_from_industries[j].show_on_map = true;
00256 _legend_from_industries[j].col_break = false;
00257 _legend_from_industries[j].end = false;
00258
00259
00260 _industry_to_list_pos[ind] = j;
00261 j++;
00262 }
00263 }
00264
00265 _legend_from_industries[j].end = true;
00266
00267
00268 _smallmap_industry_count = j;
00269 }
00270
00271 static LegendAndColour _legend_linkstats[NUM_CARGO + NUM_STATS + 1];
00272
00276 void BuildLinkStatsLegend()
00277 {
00278
00279 memset(_legend_linkstats, 0, sizeof(_legend_linkstats));
00280
00281 uint i = 0;
00282 for (; i < _sorted_cargo_specs_size; ++i) {
00283 const CargoSpec *cs = _sorted_cargo_specs[i];
00284
00285 _legend_linkstats[i].legend = cs->name;
00286 _legend_linkstats[i].colour = cs->legend_colour;
00287 _legend_linkstats[i].type = cs->Index();
00288 _legend_linkstats[i].show_on_map = true;
00289 }
00290
00291 _legend_linkstats[i].col_break = true;
00292
00293 _smallmap_cargo_count = i;
00294
00295
00296
00297
00298 for (uint st = 0; st < NUM_STATS; ++st) {
00299 LegendAndColour & legend_entry = _legend_linkstats[i + st];
00300 switch(st) {
00301 case STAT_CAPACITY:
00302 legend_entry.colour = _colour_gradient[COLOUR_WHITE][7];
00303 legend_entry.legend = STR_SMALLMAP_LEGENDA_CAPACITY;
00304 legend_entry.show_on_map = true;
00305 break;
00306 case STAT_USAGE:
00307 legend_entry.colour = _colour_gradient[COLOUR_GREY][1];
00308 legend_entry.legend = STR_SMALLMAP_LEGENDA_USAGE;
00309 legend_entry.show_on_map = false;
00310 break;
00311 case STAT_PLANNED:
00312 legend_entry.colour = _colour_gradient[COLOUR_RED][5];
00313 legend_entry.legend = STR_SMALLMAP_LEGENDA_PLANNED;
00314 legend_entry.show_on_map = true;
00315 break;
00316 case STAT_SENT:
00317 legend_entry.colour = _colour_gradient[COLOUR_YELLOW][5];
00318 legend_entry.legend = STR_SMALLMAP_LEGENDA_SENT;
00319 legend_entry.show_on_map = false;
00320 break;
00321 case STAT_TEXT:
00322 legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
00323 legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_TEXT;
00324 legend_entry.show_on_map = false;
00325 break;
00326 case STAT_GRAPH:
00327 legend_entry.colour = _colour_gradient[COLOUR_GREY][7];
00328 legend_entry.legend = STR_SMALLMAP_LEGENDA_SHOW_GRAPH;
00329 legend_entry.show_on_map = true;
00330 break;
00331 }
00332 }
00333
00334 _legend_linkstats[i + NUM_STATS].end = true;
00335 }
00336
00337 static const LegendAndColour * const _legend_table_old[] = {
00338 _legend_land_contours_old,
00339 _legend_vehicles,
00340 _legend_from_industries,
00341 _legend_linkstats,
00342 _legend_routes,
00343 _legend_vegetation,
00344 _legend_land_owners,
00345 };
00346
00347 static const LegendAndColour * const _legend_table_extended[] = {
00348 _legend_land_contours_extended,
00349 _legend_vehicles,
00350 _legend_from_industries,
00351 _legend_linkstats,
00352 _legend_routes,
00353 _legend_vegetation,
00354 _legend_land_owners,
00355 };
00356
00357 #define MKCOLOUR(x) TO_LE32X(x)
00358
00359 #define MKCOLOUR_XXXX(x) (MKCOLOUR(0x01010101) * (uint)(x))
00360 #define MKCOLOUR_X0X0(x) (MKCOLOUR(0x01000100) * (uint)(x))
00361 #define MKCOLOUR_0X0X(x) (MKCOLOUR(0x00010001) * (uint)(x))
00362 #define MKCOLOUR_0XX0(x) (MKCOLOUR(0x00010100) * (uint)(x))
00363 #define MKCOLOUR_X00X(x) (MKCOLOUR(0x01000001) * (uint)(x))
00364
00365 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y))
00366 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y))
00367
00368 #define MKCOLOUR_0000 MKCOLOUR_XXXX(0x00)
00369 #define MKCOLOUR_0FF0 MKCOLOUR_0XX0(0xFF)
00370 #define MKCOLOUR_F00F MKCOLOUR_X00X(0xFF)
00371 #define MKCOLOUR_FFFF MKCOLOUR_XXXX(0xFF)
00372
00377 static const uint32 _green_map_heights_old[] = {
00378 MKCOLOUR(0x04dcdcdc),
00379 MKCOLOUR_XXXX(0x5A),
00380 MKCOLOUR_XYXY(0x5A, 0x5B),
00381 MKCOLOUR_XXXX(0x5B),
00382 MKCOLOUR_XYXY(0x5B, 0x5C),
00383 MKCOLOUR_XXXX(0x5C),
00384 MKCOLOUR_XYXY(0x5C, 0x5D),
00385 MKCOLOUR_XXXX(0x5D),
00386 MKCOLOUR_XYXY(0x5D, 0x5E),
00387 MKCOLOUR_XXXX(0x5E),
00388 MKCOLOUR_XYXY(0x5E, 0x5F),
00389 MKCOLOUR_XXXX(0x5F),
00390 MKCOLOUR_XYXY(0x5F, 0x1F),
00391 MKCOLOUR_XXXX(0x1F),
00392 MKCOLOUR_XYXY(0x1F, 0x27),
00393 MKCOLOUR_XXXX(0x27),
00394 MKCOLOUR_XXXX(0x27),
00395 };
00396 assert_compile(lengthof(_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
00397
00403 static const uint32 _green_map_heights_extended[] = {
00404
00405
00406 MKCOLOUR(0x04dcdcdc),
00407 MKCOLOUR(0x59595958),
00408 MKCOLOUR(0x59595958),
00409 MKCOLOUR(0X59595959),
00410 MKCOLOUR(0X59595959),
00411 MKCOLOUR(0X5959595A),
00412 MKCOLOUR(0X5959595A),
00413 MKCOLOUR(0X59595A59),
00414 MKCOLOUR(0X59595A59),
00415 MKCOLOUR(0X59595A5A),
00416 MKCOLOUR(0X59595A5A),
00417 MKCOLOUR(0X595A5959),
00418 MKCOLOUR(0X595A5959),
00419 MKCOLOUR(0X595A595A),
00420 MKCOLOUR(0X595A595A),
00421 MKCOLOUR(0X595A5A59),
00422 MKCOLOUR(0X595A5A59),
00423 MKCOLOUR(0X595A5A5A),
00424 MKCOLOUR(0X595A5A5A),
00425 MKCOLOUR(0X5A595959),
00426 MKCOLOUR(0X5A595959),
00427 MKCOLOUR(0X5A59595A),
00428 MKCOLOUR(0X5A59595A),
00429 MKCOLOUR(0X5A595A59),
00430 MKCOLOUR(0X5A595A59),
00431 MKCOLOUR(0X5A595A5A),
00432 MKCOLOUR(0X5A595A5A),
00433 MKCOLOUR(0X5A5A5959),
00434 MKCOLOUR(0X5A5A5959),
00435 MKCOLOUR(0X5A5A595A),
00436 MKCOLOUR(0X5A5A595A),
00437 MKCOLOUR(0X5A5A5A59),
00438 MKCOLOUR(0X5A5A5A59),
00439 MKCOLOUR(0x5A5A5A5A),
00440 MKCOLOUR(0x5A5A5A5A),
00441 MKCOLOUR(0x5A5A5A5B),
00442 MKCOLOUR(0x5A5A5A5B),
00443 MKCOLOUR(0x5A5A5B5A),
00444 MKCOLOUR(0x5A5A5B5A),
00445 MKCOLOUR(0x5A5A5B5B),
00446 MKCOLOUR(0x5A5A5B5B),
00447 MKCOLOUR(0x5A5B5A5A),
00448 MKCOLOUR(0x5A5B5A5A),
00449 MKCOLOUR(0x5A5B5A5B),
00450 MKCOLOUR(0x5A5B5A5B),
00451 MKCOLOUR(0x5A5B5B5A),
00452 MKCOLOUR(0x5A5B5B5A),
00453 MKCOLOUR(0x5A5B5B5B),
00454 MKCOLOUR(0x5A5B5B5B),
00455 MKCOLOUR(0x5B5A5A5A),
00456 MKCOLOUR(0x5B5A5A5A),
00457 MKCOLOUR(0x5B5A5A5B),
00458 MKCOLOUR(0x5B5A5A5B),
00459 MKCOLOUR(0x5B5A5B5A),
00460 MKCOLOUR(0x5B5A5B5A),
00461 MKCOLOUR(0x5B5A5B5B),
00462 MKCOLOUR(0x5B5A5B5B),
00463 MKCOLOUR(0x5B5B5A5A),
00464 MKCOLOUR(0x5B5B5A5A),
00465 MKCOLOUR(0x5B5B5A5B),
00466 MKCOLOUR(0x5B5B5A5B),
00467 MKCOLOUR(0x5B5B5B5B),
00468 MKCOLOUR(0x5B5B5B5B),
00469 MKCOLOUR(0x5B5B5B5C),
00470 MKCOLOUR(0x5B5B5B5C),
00471 MKCOLOUR(0x5B5B5C5B),
00472 MKCOLOUR(0x5B5B5C5B),
00473 MKCOLOUR(0x5B5B5C5C),
00474 MKCOLOUR(0x5B5B5C5C),
00475 MKCOLOUR(0x5B5C5B5B),
00476 MKCOLOUR(0x5B5C5B5B),
00477 MKCOLOUR(0x5B5C5B5C),
00478 MKCOLOUR(0x5B5C5B5C),
00479 MKCOLOUR(0x5B5C5C5B),
00480 MKCOLOUR(0x5B5C5C5B),
00481 MKCOLOUR(0x5B5C5C5C),
00482 MKCOLOUR(0x5B5C5C5C),
00483 MKCOLOUR(0x5C5B5B5B),
00484 MKCOLOUR(0x5C5B5B5B),
00485 MKCOLOUR(0x5C5B5B5C),
00486 MKCOLOUR(0x5C5B5B5C),
00487 MKCOLOUR(0x5C5B5C5B),
00488 MKCOLOUR(0x5C5B5C5B),
00489 MKCOLOUR(0x5C5B5C5C),
00490 MKCOLOUR(0x5C5B5C5C),
00491 MKCOLOUR(0x5C5C5B5B),
00492 MKCOLOUR(0x5C5C5B5B),
00493 MKCOLOUR(0x5C5C5B5C),
00494 MKCOLOUR(0x5C5C5B5C),
00495 MKCOLOUR(0x5C5C5C5C),
00496 MKCOLOUR(0x5C5C5C5C),
00497 MKCOLOUR(0x5C5C5C5D),
00498 MKCOLOUR(0x5C5C5C5D),
00499 MKCOLOUR(0x5C5C5D5C),
00500 MKCOLOUR(0x5C5C5D5C),
00501 MKCOLOUR(0x5C5C5D5D),
00502 MKCOLOUR(0x5C5C5D5D),
00503 MKCOLOUR(0x5C5D5C5C),
00504 MKCOLOUR(0x5C5D5C5C),
00505 MKCOLOUR(0x5C5D5C5D),
00506 MKCOLOUR(0x5C5D5C5D),
00507 MKCOLOUR(0x5C5D5D5C),
00508 MKCOLOUR(0x5C5D5D5C),
00509 MKCOLOUR(0x5C5D5D5D),
00510 MKCOLOUR(0x5C5D5D5D),
00511 MKCOLOUR(0x5D5C5C5C),
00512 MKCOLOUR(0x5D5C5C5C),
00513 MKCOLOUR(0x5D5C5C5D),
00514 MKCOLOUR(0x5D5C5C5D),
00515 MKCOLOUR(0x5D5C5D5C),
00516 MKCOLOUR(0x5D5C5D5C),
00517 MKCOLOUR(0x5D5C5D5D),
00518 MKCOLOUR(0x5D5C5D5D),
00519 MKCOLOUR(0x5D5D5C5C),
00520 MKCOLOUR(0x5D5D5C5C),
00521 MKCOLOUR(0x5D5D5C5D),
00522 MKCOLOUR(0x5D5D5C5D),
00523 MKCOLOUR(0x5D5D5D5D),
00524 MKCOLOUR(0x5D5D5D5D),
00525 MKCOLOUR(0x5D5D5D5E),
00526 MKCOLOUR(0x5D5D5D5E),
00527 MKCOLOUR(0x5D5D5E5D),
00528 MKCOLOUR(0x5D5D5E5D),
00529 MKCOLOUR(0x5D5D5E5E),
00530 MKCOLOUR(0x5D5D5E5E),
00531 MKCOLOUR(0x5D5E5D5D),
00532 MKCOLOUR(0x5D5E5D5D),
00533 MKCOLOUR(0x5D5E5D5E),
00534 MKCOLOUR(0x5D5E5D5E),
00535 MKCOLOUR(0x5D5E5E5D),
00536 MKCOLOUR(0x5D5E5E5D),
00537 MKCOLOUR(0x5D5E5E5E),
00538 MKCOLOUR(0x5D5E5E5E),
00539 MKCOLOUR(0x5E5D5D5D),
00540 MKCOLOUR(0x5E5D5D5D),
00541 MKCOLOUR(0x5E5D5D5E),
00542 MKCOLOUR(0x5E5D5D5E),
00543 MKCOLOUR(0x5E5D5E5D),
00544 MKCOLOUR(0x5E5D5E5D),
00545 MKCOLOUR(0x5E5D5E5E),
00546 MKCOLOUR(0x5E5D5E5E),
00547 MKCOLOUR(0x5E5D5D5D),
00548 MKCOLOUR(0x5E5D5D5D),
00549 MKCOLOUR(0x5E5D5D5E),
00550 MKCOLOUR(0x5E5D5D5E),
00551 MKCOLOUR(0x5E5E5E5E),
00552 MKCOLOUR(0x5E5E5E5E),
00553 MKCOLOUR(0x5E5E5E5F),
00554 MKCOLOUR(0x5E5E5E5F),
00555 MKCOLOUR(0x5E5E5F5E),
00556 MKCOLOUR(0x5E5E5F5E),
00557 MKCOLOUR(0x5E5E5F5F),
00558 MKCOLOUR(0x5E5E5F5F),
00559 MKCOLOUR(0x5E5F5E5E),
00560 MKCOLOUR(0x5E5F5E5E),
00561 MKCOLOUR(0x5E5F5E5F),
00562 MKCOLOUR(0x5E5F5E5F),
00563 MKCOLOUR(0x5E5F5F5E),
00564 MKCOLOUR(0x5E5F5F5E),
00565 MKCOLOUR(0x5E5F5F5F),
00566 MKCOLOUR(0x5E5F5F5F),
00567 MKCOLOUR(0x5F5E5E5E),
00568 MKCOLOUR(0x5F5E5E5E),
00569 MKCOLOUR(0x5F5E5E5F),
00570 MKCOLOUR(0x5F5E5E5F),
00571 MKCOLOUR(0x5F5E5F5E),
00572 MKCOLOUR(0x5F5E5F5E),
00573 MKCOLOUR(0x5F5E5F5F),
00574 MKCOLOUR(0x5F5E5F5F),
00575 MKCOLOUR(0x5F5F5E5E),
00576 MKCOLOUR(0x5F5F5E5E),
00577 MKCOLOUR(0x5F5F5E5F),
00578 MKCOLOUR(0x5F5F5E5F),
00579 MKCOLOUR(0x5F5F5F5F),
00580 MKCOLOUR(0x5F5F5F5F),
00581 MKCOLOUR(0x5F5F5F1F),
00582 MKCOLOUR(0x5F5F5F1F),
00583 MKCOLOUR(0x5F5F1F5F),
00584 MKCOLOUR(0x5F5F1F5F),
00585 MKCOLOUR(0x5F5F1F1F),
00586 MKCOLOUR(0x5F5F1F1F),
00587 MKCOLOUR(0x5F1F5F1F),
00588 MKCOLOUR(0x5F1F5F1F),
00589
00590 MKCOLOUR(0x5F1F1F1F),
00591 MKCOLOUR(0x5F1F1F1F),
00592 MKCOLOUR(0x1F5F5F5F),
00593 MKCOLOUR(0x1F5F5F5F),
00594 MKCOLOUR(0x1F5F5F1F),
00595 MKCOLOUR(0x1F5F5F1F),
00596 MKCOLOUR(0x1F5F1F5F),
00597 MKCOLOUR(0x1F5F1F5F),
00598 MKCOLOUR(0x1F5F1F1F),
00599 MKCOLOUR(0x1F5F1F1F),
00600 MKCOLOUR(0x1F1F5F5F),
00601 MKCOLOUR(0x1F1F5F5F),
00602 MKCOLOUR(0x1F1F5F1F),
00603 MKCOLOUR(0x1F1F5F1F),
00604 MKCOLOUR(0x1F1F1F5F),
00605 MKCOLOUR(0x1F1F1F5F),
00606
00607 MKCOLOUR(0x1F1F1F1F),
00608 MKCOLOUR(0x1F1F1F1F),
00609 MKCOLOUR(0x1F1F1F27),
00610 MKCOLOUR(0x1F1F1F27),
00611 MKCOLOUR(0x1F1F271F),
00612 MKCOLOUR(0x1F1F271F),
00613 MKCOLOUR(0x1F1F2727),
00614 MKCOLOUR(0x1F1F2727),
00615 MKCOLOUR(0x1F271F1F),
00616 MKCOLOUR(0x1F271F1F),
00617 MKCOLOUR(0x1F271F27),
00618 MKCOLOUR(0x1F271F27),
00619 MKCOLOUR(0x1F272727),
00620 MKCOLOUR(0x1F272727),
00621 MKCOLOUR(0x271F1F1F),
00622 MKCOLOUR(0x271F1F1F),
00623 MKCOLOUR(0x271F1F27),
00624 MKCOLOUR(0x271F1F27),
00625 MKCOLOUR(0x271F271F),
00626 MKCOLOUR(0x271F271F),
00627 MKCOLOUR(0x271F2727),
00628 MKCOLOUR(0x271F2727),
00629 MKCOLOUR(0x27271F1F),
00630 MKCOLOUR(0x27271F1F),
00631 MKCOLOUR(0x27271F27),
00632 MKCOLOUR(0x27271F27),
00633 MKCOLOUR(0x2727271F),
00634 MKCOLOUR(0x2727271F),
00635 MKCOLOUR(0x27272727),
00636 MKCOLOUR(0x27272727),
00637
00638 MKCOLOUR(0x27272727),
00639 MKCOLOUR(0x27272727),
00640
00641 MKCOLOUR(0x1F27AF27),
00642 MKCOLOUR(0x1F27AF27),
00643 MKCOLOUR(0x1F274FAF),
00644 MKCOLOUR(0x1F274FAF),
00645 MKCOLOUR(0x4F274FAF),
00646 MKCOLOUR(0x4F274FAF),
00647 MKCOLOUR(0x4FAF1FAF),
00648 MKCOLOUR(0x4FAF1FAF),
00649 MKCOLOUR(0x4F2727AF),
00650 MKCOLOUR(0x4F2727AF),
00651 MKCOLOUR(0x4F27AF27),
00652 MKCOLOUR(0x4F27AF27),
00653 MKCOLOUR(0x4F27AFAF),
00654 MKCOLOUR(0x4F27AFAF),
00655 MKCOLOUR(0x4FAF2727),
00656 MKCOLOUR(0x4FAF2727),
00657 MKCOLOUR(0x4FAF27AF),
00658 MKCOLOUR(0x4FAF27AF),
00659 MKCOLOUR(0x4FAFAF27),
00660 MKCOLOUR(0x4FAFAF27),
00661 MKCOLOUR(0x4FAFAFAF),
00662 MKCOLOUR(0x4FAFAFAF),
00663 MKCOLOUR(0x4FAFAFCF),
00664 MKCOLOUR(0x4FAFAFCF),
00665 MKCOLOUR(0x4FAFCFAF),
00666 MKCOLOUR(0x4FCFAFAF),
00667
00668
00669 };
00670 assert_compile(lengthof(_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
00671
00676 static const uint32 _dark_green_map_heights_old[] = {
00677 MKCOLOUR(0x04dcdcdc),
00678 MKCOLOUR_XXXX(0x60),
00679 MKCOLOUR_XYXY(0x60, 0x61),
00680 MKCOLOUR_XXXX(0x61),
00681 MKCOLOUR_XYXY(0x61, 0x62),
00682 MKCOLOUR_XXXX(0x62),
00683 MKCOLOUR_XYXY(0x62, 0x63),
00684 MKCOLOUR_XXXX(0x63),
00685 MKCOLOUR_XYXY(0x63, 0x64),
00686 MKCOLOUR_XXXX(0x64),
00687 MKCOLOUR_XYXY(0x64, 0x65),
00688 MKCOLOUR_XXXX(0x65),
00689 MKCOLOUR_XYXY(0x65, 0x66),
00690 MKCOLOUR_XXXX(0x66),
00691 MKCOLOUR_XYXY(0x66, 0x67),
00692 MKCOLOUR_XXXX(0x67),
00693 MKCOLOUR_XXXX(0x67),
00694 };
00695 assert_compile(lengthof(_dark_green_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
00696
00702 static const uint32 _dark_green_map_heights_extended[] = {
00703
00704
00705 MKCOLOUR(0x04dcdcdc),
00706 MKCOLOUR(0x60606060),
00707 MKCOLOUR(0x60606060),
00708 MKCOLOUR(0x60606061),
00709 MKCOLOUR(0x60606061),
00710 MKCOLOUR(0x60606160),
00711 MKCOLOUR(0x60606160),
00712 MKCOLOUR(0x60606161),
00713 MKCOLOUR(0x60606161),
00714 MKCOLOUR(0x60616060),
00715 MKCOLOUR(0x60616060),
00716 MKCOLOUR(0x60616061),
00717 MKCOLOUR(0x60616061),
00718 MKCOLOUR(0x60616160),
00719 MKCOLOUR(0x60616160),
00720 MKCOLOUR(0x60616161),
00721 MKCOLOUR(0x60616161),
00722 MKCOLOUR(0x61606060),
00723 MKCOLOUR(0x61606060),
00724 MKCOLOUR(0x61606061),
00725 MKCOLOUR(0x61606061),
00726 MKCOLOUR(0x61606160),
00727 MKCOLOUR(0x61606160),
00728 MKCOLOUR(0x61606161),
00729 MKCOLOUR(0x61606161),
00730 MKCOLOUR(0x61616060),
00731 MKCOLOUR(0x61616060),
00732 MKCOLOUR(0x61616061),
00733 MKCOLOUR(0x61616061),
00734 MKCOLOUR(0x61616160),
00735 MKCOLOUR(0x61616160),
00736 MKCOLOUR(0x61616161),
00737 MKCOLOUR(0x61616161),
00738 MKCOLOUR(0x61616162),
00739 MKCOLOUR(0x61616162),
00740 MKCOLOUR(0x61616261),
00741 MKCOLOUR(0x61616261),
00742 MKCOLOUR(0x61616262),
00743 MKCOLOUR(0x61616262),
00744 MKCOLOUR(0x61626161),
00745 MKCOLOUR(0x61626161),
00746 MKCOLOUR(0x61626162),
00747 MKCOLOUR(0x61626162),
00748 MKCOLOUR(0x61626261),
00749 MKCOLOUR(0x61626261),
00750 MKCOLOUR(0x61626262),
00751 MKCOLOUR(0x61626262),
00752 MKCOLOUR(0x62616161),
00753 MKCOLOUR(0x62616161),
00754 MKCOLOUR(0x62616162),
00755 MKCOLOUR(0x62616162),
00756 MKCOLOUR(0x62616261),
00757 MKCOLOUR(0x62616261),
00758 MKCOLOUR(0x62616262),
00759 MKCOLOUR(0x62616262),
00760 MKCOLOUR(0x62626161),
00761 MKCOLOUR(0x62626161),
00762 MKCOLOUR(0x62626162),
00763 MKCOLOUR(0x62626162),
00764 MKCOLOUR(0x62626261),
00765 MKCOLOUR(0x62626261),
00766 MKCOLOUR(0x62626262),
00767 MKCOLOUR(0x62626262),
00768 MKCOLOUR(0x62626263),
00769 MKCOLOUR(0x62626263),
00770 MKCOLOUR(0x62626362),
00771 MKCOLOUR(0x62626362),
00772 MKCOLOUR(0x62626363),
00773 MKCOLOUR(0x62626363),
00774 MKCOLOUR(0x62636262),
00775 MKCOLOUR(0x62636262),
00776 MKCOLOUR(0x62636263),
00777 MKCOLOUR(0x62636263),
00778 MKCOLOUR(0x62636362),
00779 MKCOLOUR(0x62636362),
00780 MKCOLOUR(0x62636363),
00781 MKCOLOUR(0x62636363),
00782 MKCOLOUR(0x63626262),
00783 MKCOLOUR(0x63626262),
00784 MKCOLOUR(0x63626263),
00785 MKCOLOUR(0x63626263),
00786 MKCOLOUR(0x63626362),
00787 MKCOLOUR(0x63626362),
00788 MKCOLOUR(0x63626363),
00789 MKCOLOUR(0x63626363),
00790 MKCOLOUR(0x63636262),
00791 MKCOLOUR(0x63636262),
00792 MKCOLOUR(0x63636263),
00793 MKCOLOUR(0x63636263),
00794 MKCOLOUR(0x63636362),
00795 MKCOLOUR(0x63636362),
00796 MKCOLOUR(0x63636363),
00797 MKCOLOUR(0x63636363),
00798 MKCOLOUR(0x63636364),
00799 MKCOLOUR(0x63636364),
00800 MKCOLOUR(0x63636463),
00801 MKCOLOUR(0x63636463),
00802 MKCOLOUR(0x63636464),
00803 MKCOLOUR(0x63636464),
00804 MKCOLOUR(0x63646363),
00805 MKCOLOUR(0x63646363),
00806 MKCOLOUR(0x63646364),
00807 MKCOLOUR(0x63646364),
00808 MKCOLOUR(0x63646463),
00809 MKCOLOUR(0x63646463),
00810 MKCOLOUR(0x63646464),
00811 MKCOLOUR(0x63646464),
00812 MKCOLOUR(0x64636363),
00813 MKCOLOUR(0x64636363),
00814 MKCOLOUR(0x64636364),
00815 MKCOLOUR(0x64636364),
00816 MKCOLOUR(0x64636463),
00817 MKCOLOUR(0x64636463),
00818 MKCOLOUR(0x64636464),
00819 MKCOLOUR(0x64636464),
00820 MKCOLOUR(0x64646363),
00821 MKCOLOUR(0x64646363),
00822 MKCOLOUR(0x64646364),
00823 MKCOLOUR(0x64646364),
00824 MKCOLOUR(0x64646463),
00825 MKCOLOUR(0x64646463),
00826 MKCOLOUR(0x64646464),
00827 MKCOLOUR(0x64646464),
00828 MKCOLOUR(0x64646465),
00829 MKCOLOUR(0x64646465),
00830 MKCOLOUR(0x64646564),
00831 MKCOLOUR(0x64646564),
00832 MKCOLOUR(0x64646565),
00833 MKCOLOUR(0x64646565),
00834 MKCOLOUR(0x64656464),
00835 MKCOLOUR(0x64656464),
00836 MKCOLOUR(0x64656465),
00837 MKCOLOUR(0x64656465),
00838 MKCOLOUR(0x64656564),
00839 MKCOLOUR(0x64656564),
00840 MKCOLOUR(0x64656565),
00841 MKCOLOUR(0x64656565),
00842 MKCOLOUR(0x65646464),
00843 MKCOLOUR(0x65646464),
00844 MKCOLOUR(0x65646465),
00845 MKCOLOUR(0x65646465),
00846 MKCOLOUR(0x65646564),
00847 MKCOLOUR(0x65646564),
00848 MKCOLOUR(0x65646565),
00849 MKCOLOUR(0x65646565),
00850 MKCOLOUR(0x65656464),
00851 MKCOLOUR(0x65656464),
00852 MKCOLOUR(0x65656465),
00853 MKCOLOUR(0x65656465),
00854 MKCOLOUR(0x65656564),
00855 MKCOLOUR(0x65656564),
00856 MKCOLOUR(0x65656565),
00857 MKCOLOUR(0x65656565),
00858 MKCOLOUR(0x65656566),
00859 MKCOLOUR(0x65656566),
00860 MKCOLOUR(0x65656665),
00861 MKCOLOUR(0x65656665),
00862 MKCOLOUR(0x65656666),
00863 MKCOLOUR(0x65656666),
00864 MKCOLOUR(0x65666565),
00865 MKCOLOUR(0x65666565),
00866 MKCOLOUR(0x65666566),
00867 MKCOLOUR(0x65666566),
00868 MKCOLOUR(0x65666665),
00869 MKCOLOUR(0x65666665),
00870 MKCOLOUR(0x65666666),
00871 MKCOLOUR(0x65666666),
00872 MKCOLOUR(0x66656565),
00873 MKCOLOUR(0x66656565),
00874 MKCOLOUR(0x66656566),
00875 MKCOLOUR(0x66656566),
00876 MKCOLOUR(0x66656665),
00877 MKCOLOUR(0x66656665),
00878 MKCOLOUR(0x66656666),
00879 MKCOLOUR(0x66656666),
00880 MKCOLOUR(0x66666565),
00881 MKCOLOUR(0x66666565),
00882 MKCOLOUR(0x66666566),
00883 MKCOLOUR(0x66666566),
00884 MKCOLOUR(0x66666665),
00885 MKCOLOUR(0x66666665),
00886 MKCOLOUR(0x66666666),
00887 MKCOLOUR(0x66666666),
00888 MKCOLOUR(0x66666667),
00889 MKCOLOUR(0x66666667),
00890 MKCOLOUR(0x66666766),
00891 MKCOLOUR(0x66666766),
00892 MKCOLOUR(0x66666767),
00893 MKCOLOUR(0x66666767),
00894 MKCOLOUR(0x66676666),
00895 MKCOLOUR(0x66676666),
00896 MKCOLOUR(0x66676667),
00897 MKCOLOUR(0x66676667),
00898 MKCOLOUR(0x66676766),
00899 MKCOLOUR(0x66676766),
00900 MKCOLOUR(0x66676767),
00901 MKCOLOUR(0x66676767),
00902 MKCOLOUR(0x67676767),
00903 MKCOLOUR(0x67676767),
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924 MKCOLOUR(0x67676767),
00925 MKCOLOUR(0x67676767),
00926 MKCOLOUR(0x67676767),
00927 MKCOLOUR(0x67676767),
00928 MKCOLOUR(0x67676767),
00929 MKCOLOUR(0x67676767),
00930 MKCOLOUR(0x67676767),
00931 MKCOLOUR(0x67676767),
00932 MKCOLOUR(0x67676767),
00933 MKCOLOUR(0x67676767),
00934 MKCOLOUR(0x67676767),
00935 MKCOLOUR(0x67676767),
00936 MKCOLOUR(0x67676767),
00937 MKCOLOUR(0x67676767),
00938 MKCOLOUR(0x67676767),
00939 MKCOLOUR(0x67676767),
00940 MKCOLOUR(0x67676767),
00941 MKCOLOUR(0x67676767),
00942 MKCOLOUR(0x67676767),
00943 MKCOLOUR(0x67676767),
00944 MKCOLOUR(0x67676767),
00945 MKCOLOUR(0x67676767),
00946 MKCOLOUR(0x67676767),
00947 MKCOLOUR(0x67676767),
00948 MKCOLOUR(0x67676767),
00949 MKCOLOUR(0x67676767),
00950 MKCOLOUR(0x67676767),
00951 MKCOLOUR(0x67676767),
00952 MKCOLOUR(0x67676767),
00953 MKCOLOUR(0x67676767),
00954 MKCOLOUR(0x67676767),
00955 MKCOLOUR(0x67676767),
00956
00957
00958
00959
00960 MKCOLOUR(0x1F27AF27),
00961 MKCOLOUR(0x1F27AF27),
00962 MKCOLOUR(0x1F274FAF),
00963 MKCOLOUR(0x1F274FAF),
00964 MKCOLOUR(0x4F274FAF),
00965 MKCOLOUR(0x4F274FAF),
00966 MKCOLOUR(0x4FAF1FAF),
00967 MKCOLOUR(0x4FAF1FAF),
00968 MKCOLOUR(0x4F2727AF),
00969 MKCOLOUR(0x4F2727AF),
00970 MKCOLOUR(0x4F27AF27),
00971 MKCOLOUR(0x4F27AF27),
00972 MKCOLOUR(0x4F27AFAF),
00973 MKCOLOUR(0x4F27AFAF),
00974 MKCOLOUR(0x4FAF2727),
00975 MKCOLOUR(0x4FAF2727),
00976 MKCOLOUR(0x4FAF27AF),
00977 MKCOLOUR(0x4FAF27AF),
00978 MKCOLOUR(0x4FAFAF27),
00979 MKCOLOUR(0x4FAFAF27),
00980 MKCOLOUR(0x4FAFAFAF),
00981 MKCOLOUR(0x4FAFAFAF),
00982 MKCOLOUR(0x4FAFAFCF),
00983 MKCOLOUR(0x4FAFAFCF),
00984 MKCOLOUR(0x4FAFCFAF),
00985 MKCOLOUR(0x4FCFAFAF),
00986
00987
00988 };
00989 assert_compile(lengthof(_dark_green_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
00990
00995 static const uint32 _violet_map_heights_old[] = {
00996 MKCOLOUR(0x04dcdcdc),
00997 MKCOLOUR_XXXX(0x80),
00998 MKCOLOUR_XYXY(0x80, 0x81),
00999 MKCOLOUR_XXXX(0x81),
01000 MKCOLOUR_XYXY(0x81, 0x82),
01001 MKCOLOUR_XXXX(0x82),
01002 MKCOLOUR_XYXY(0x82, 0x83),
01003 MKCOLOUR_XXXX(0x83),
01004 MKCOLOUR_XYXY(0x83, 0x84),
01005 MKCOLOUR_XXXX(0x84),
01006 MKCOLOUR_XYXY(0x84, 0x85),
01007 MKCOLOUR_XXXX(0x85),
01008 MKCOLOUR_XYXY(0x85, 0x86),
01009 MKCOLOUR_XXXX(0x86),
01010 MKCOLOUR_XYXY(0x86, 0x87),
01011 MKCOLOUR_XXXX(0x87),
01012 MKCOLOUR_XXXX(0x87),
01013 };
01014 assert_compile(lengthof(_violet_map_heights_old) == MAX_TILE_HEIGHT_OLD + 2);
01015
01021 static const uint32 _violet_map_heights_extended[] = {
01022
01023
01024 MKCOLOUR(0x04dcdcdc),
01025 MKCOLOUR(0x80808080),
01026 MKCOLOUR(0x80808080),
01027 MKCOLOUR(0x80808081),
01028 MKCOLOUR(0x80808081),
01029 MKCOLOUR(0x80808180),
01030 MKCOLOUR(0x80808180),
01031 MKCOLOUR(0x80808181),
01032 MKCOLOUR(0x80808181),
01033 MKCOLOUR(0x80818080),
01034 MKCOLOUR(0x80818080),
01035 MKCOLOUR(0x80818081),
01036 MKCOLOUR(0x80818081),
01037 MKCOLOUR(0x80818180),
01038 MKCOLOUR(0x80818180),
01039 MKCOLOUR(0x80818181),
01040 MKCOLOUR(0x80818181),
01041 MKCOLOUR(0x81808080),
01042 MKCOLOUR(0x81808080),
01043 MKCOLOUR(0x81808081),
01044 MKCOLOUR(0x81808081),
01045 MKCOLOUR(0x81808180),
01046 MKCOLOUR(0x81808180),
01047 MKCOLOUR(0x81808181),
01048 MKCOLOUR(0x81808181),
01049 MKCOLOUR(0x81818080),
01050 MKCOLOUR(0x81818080),
01051 MKCOLOUR(0x81818081),
01052 MKCOLOUR(0x81818081),
01053 MKCOLOUR(0x81818180),
01054 MKCOLOUR(0x81818180),
01055 MKCOLOUR(0x81818181),
01056 MKCOLOUR(0x81818181),
01057 MKCOLOUR(0x81818182),
01058 MKCOLOUR(0x81818182),
01059 MKCOLOUR(0x81818281),
01060 MKCOLOUR(0x81818281),
01061 MKCOLOUR(0x81818282),
01062 MKCOLOUR(0x81818282),
01063 MKCOLOUR(0x81828181),
01064 MKCOLOUR(0x81828181),
01065 MKCOLOUR(0x81828182),
01066 MKCOLOUR(0x81828182),
01067 MKCOLOUR(0x81828281),
01068 MKCOLOUR(0x81828281),
01069 MKCOLOUR(0x81828282),
01070 MKCOLOUR(0x81828282),
01071 MKCOLOUR(0x82818181),
01072 MKCOLOUR(0x82818181),
01073 MKCOLOUR(0x82818182),
01074 MKCOLOUR(0x82818182),
01075 MKCOLOUR(0x82818281),
01076 MKCOLOUR(0x82818281),
01077 MKCOLOUR(0x82818282),
01078 MKCOLOUR(0x82818282),
01079 MKCOLOUR(0x82828181),
01080 MKCOLOUR(0x82828181),
01081 MKCOLOUR(0x82828182),
01082 MKCOLOUR(0x82828182),
01083 MKCOLOUR(0x82828281),
01084 MKCOLOUR(0x82828281),
01085 MKCOLOUR(0x82828282),
01086 MKCOLOUR(0x82828282),
01087 MKCOLOUR(0x82828283),
01088 MKCOLOUR(0x82828283),
01089 MKCOLOUR(0x82828382),
01090 MKCOLOUR(0x82828382),
01091 MKCOLOUR(0x82828383),
01092 MKCOLOUR(0x82828383),
01093 MKCOLOUR(0x82838282),
01094 MKCOLOUR(0x82838282),
01095 MKCOLOUR(0x82838283),
01096 MKCOLOUR(0x82838283),
01097 MKCOLOUR(0x82838382),
01098 MKCOLOUR(0x82838382),
01099 MKCOLOUR(0x82838383),
01100 MKCOLOUR(0x82838383),
01101 MKCOLOUR(0x83828282),
01102 MKCOLOUR(0x83828282),
01103 MKCOLOUR(0x83828283),
01104 MKCOLOUR(0x83828283),
01105 MKCOLOUR(0x83828382),
01106 MKCOLOUR(0x83828382),
01107 MKCOLOUR(0x83828383),
01108 MKCOLOUR(0x83828383),
01109 MKCOLOUR(0x83838282),
01110 MKCOLOUR(0x83838282),
01111 MKCOLOUR(0x83838283),
01112 MKCOLOUR(0x83838283),
01113 MKCOLOUR(0x83838382),
01114 MKCOLOUR(0x83838382),
01115 MKCOLOUR(0x83838383),
01116 MKCOLOUR(0x83838383),
01117 MKCOLOUR(0x83838384),
01118 MKCOLOUR(0x83838384),
01119 MKCOLOUR(0x83838483),
01120 MKCOLOUR(0x83838483),
01121 MKCOLOUR(0x83838484),
01122 MKCOLOUR(0x83838484),
01123 MKCOLOUR(0x83848383),
01124 MKCOLOUR(0x83848383),
01125 MKCOLOUR(0x83848384),
01126 MKCOLOUR(0x83848384),
01127 MKCOLOUR(0x83848483),
01128 MKCOLOUR(0x83848483),
01129 MKCOLOUR(0x83848484),
01130 MKCOLOUR(0x83848484),
01131 MKCOLOUR(0x84838383),
01132 MKCOLOUR(0x84838383),
01133 MKCOLOUR(0x84838384),
01134 MKCOLOUR(0x84838384),
01135 MKCOLOUR(0x84838483),
01136 MKCOLOUR(0x84838483),
01137 MKCOLOUR(0x84838484),
01138 MKCOLOUR(0x84838484),
01139 MKCOLOUR(0x84848383),
01140 MKCOLOUR(0x84848383),
01141 MKCOLOUR(0x84848384),
01142 MKCOLOUR(0x84848384),
01143 MKCOLOUR(0x84848483),
01144 MKCOLOUR(0x84848483),
01145 MKCOLOUR(0x84848484),
01146 MKCOLOUR(0x84848484),
01147 MKCOLOUR(0x84848485),
01148 MKCOLOUR(0x84848485),
01149 MKCOLOUR(0x84848584),
01150 MKCOLOUR(0x84848584),
01151 MKCOLOUR(0x84848585),
01152 MKCOLOUR(0x84848585),
01153 MKCOLOUR(0x84858484),
01154 MKCOLOUR(0x84858484),
01155 MKCOLOUR(0x84858485),
01156 MKCOLOUR(0x84858485),
01157 MKCOLOUR(0x84858584),
01158 MKCOLOUR(0x84858584),
01159 MKCOLOUR(0x84858585),
01160 MKCOLOUR(0x84858585),
01161 MKCOLOUR(0x85848484),
01162 MKCOLOUR(0x85848484),
01163 MKCOLOUR(0x85848485),
01164 MKCOLOUR(0x85848485),
01165 MKCOLOUR(0x85848584),
01166 MKCOLOUR(0x85848584),
01167 MKCOLOUR(0x85848585),
01168 MKCOLOUR(0x85848585),
01169 MKCOLOUR(0x85858484),
01170 MKCOLOUR(0x85858484),
01171 MKCOLOUR(0x85858485),
01172 MKCOLOUR(0x85858485),
01173 MKCOLOUR(0x85858584),
01174 MKCOLOUR(0x85858584),
01175 MKCOLOUR(0x85858585),
01176 MKCOLOUR(0x85858585),
01177 MKCOLOUR(0x85858586),
01178 MKCOLOUR(0x85858586),
01179 MKCOLOUR(0x85858685),
01180 MKCOLOUR(0x85858685),
01181 MKCOLOUR(0x85858686),
01182 MKCOLOUR(0x85858686),
01183 MKCOLOUR(0x85868585),
01184 MKCOLOUR(0x85868585),
01185 MKCOLOUR(0x85868586),
01186 MKCOLOUR(0x85868586),
01187 MKCOLOUR(0x85868685),
01188 MKCOLOUR(0x85868685),
01189 MKCOLOUR(0x85868686),
01190 MKCOLOUR(0x85868686),
01191 MKCOLOUR(0x85868585),
01192 MKCOLOUR(0x85868585),
01193 MKCOLOUR(0x85868586),
01194 MKCOLOUR(0x85868586),
01195 MKCOLOUR(0x85868685),
01196 MKCOLOUR(0x85868685),
01197 MKCOLOUR(0x85868686),
01198 MKCOLOUR(0x85868686),
01199 MKCOLOUR(0x86868585),
01200 MKCOLOUR(0x86868585),
01201 MKCOLOUR(0x86868586),
01202 MKCOLOUR(0x86868586),
01203 MKCOLOUR(0x86868685),
01204 MKCOLOUR(0x86868685),
01205 MKCOLOUR(0x86868686),
01206 MKCOLOUR(0x86868686),
01207 MKCOLOUR(0x86868687),
01208 MKCOLOUR(0x86868687),
01209 MKCOLOUR(0x86868786),
01210 MKCOLOUR(0x86868786),
01211 MKCOLOUR(0x86868787),
01212 MKCOLOUR(0x86868787),
01213 MKCOLOUR(0x86878686),
01214 MKCOLOUR(0x86878686),
01215 MKCOLOUR(0x86878687),
01216 MKCOLOUR(0x86878687),
01217 MKCOLOUR(0x86878786),
01218 MKCOLOUR(0x86878786),
01219 MKCOLOUR(0x86878787),
01220 MKCOLOUR(0x86878787),
01221 MKCOLOUR(0x87868686),
01222 MKCOLOUR(0x87868686),
01223 MKCOLOUR(0x87868687),
01224 MKCOLOUR(0x87868687),
01225 MKCOLOUR(0x87868786),
01226 MKCOLOUR(0x87868786),
01227 MKCOLOUR(0x87868787),
01228 MKCOLOUR(0x87868787),
01229 MKCOLOUR(0x87878686),
01230 MKCOLOUR(0x87878686),
01231 MKCOLOUR(0x87878687),
01232 MKCOLOUR(0x87878687),
01233 MKCOLOUR(0x87878786),
01234 MKCOLOUR(0x87878786),
01235 MKCOLOUR(0x87878787),
01236 MKCOLOUR(0x87878787),
01237 MKCOLOUR(0x87878787),
01238 MKCOLOUR(0x87878787),
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 MKCOLOUR(0x87878787),
01266 MKCOLOUR(0x87878787),
01267 MKCOLOUR(0x87878787),
01268 MKCOLOUR(0x87878787),
01269 MKCOLOUR(0x87878787),
01270 MKCOLOUR(0x87878787),
01271 MKCOLOUR(0x87878787),
01272 MKCOLOUR(0x87878787),
01273 MKCOLOUR(0x87878787),
01274 MKCOLOUR(0x87878787),
01275 MKCOLOUR(0x87878787),
01276 MKCOLOUR(0x87878787),
01277 MKCOLOUR(0x87878787),
01278 MKCOLOUR(0x87878787),
01279 MKCOLOUR(0x87878787),
01280 MKCOLOUR(0x87878787),
01281
01282
01283
01284
01285 MKCOLOUR(0x1F27AF27),
01286 MKCOLOUR(0x1F27AF27),
01287 MKCOLOUR(0x1F274FAF),
01288 MKCOLOUR(0x1F274FAF),
01289 MKCOLOUR(0x4F274FAF),
01290 MKCOLOUR(0x4F274FAF),
01291 MKCOLOUR(0x4FAF1FAF),
01292 MKCOLOUR(0x4FAF1FAF),
01293 MKCOLOUR(0x4F2727AF),
01294 MKCOLOUR(0x4F2727AF),
01295 MKCOLOUR(0x4F27AF27),
01296 MKCOLOUR(0x4F27AF27),
01297 MKCOLOUR(0x4F27AFAF),
01298 MKCOLOUR(0x4F27AFAF),
01299 MKCOLOUR(0x4FAF2727),
01300 MKCOLOUR(0x4FAF2727),
01301 MKCOLOUR(0x4FAF27AF),
01302 MKCOLOUR(0x4FAF27AF),
01303 MKCOLOUR(0x4FAFAF27),
01304 MKCOLOUR(0x4FAFAF27),
01305 MKCOLOUR(0x4FAFAFAF),
01306 MKCOLOUR(0x4FAFAFAF),
01307 MKCOLOUR(0x4FAFAFCF),
01308 MKCOLOUR(0x4FAFAFCF),
01309 MKCOLOUR(0x4FAFCFAF),
01310 MKCOLOUR(0x4FCFAFAF),
01311
01312
01313 };
01314 assert_compile(lengthof(_violet_map_heights_extended) == MAX_TILE_HEIGHT_EXTENDED + 2);
01315
01319 static const uint32 _stuck_counter_colours[] = {
01320 MKCOLOUR(0xD0D0D0D0),
01321 MKCOLOUR(0xCECECECE),
01322 MKCOLOUR(0xBFBFBFBF),
01323 MKCOLOUR(0xBDBDBDBD),
01324 MKCOLOUR(0xBABABABA),
01325 MKCOLOUR(0xB8B8B8B8),
01326 MKCOLOUR(0xB6B6B6B6),
01327 MKCOLOUR(0xB4B4B4B4),
01328 };
01329 assert_compile(lengthof(_stuck_counter_colours) == 8);
01330
01332 struct SmallMapColourScheme {
01333 const uint32 *height_colours;
01334 uint32 default_colour;
01335 };
01336
01338 static const SmallMapColourScheme _heightmap_schemes_old[] = {
01339 {_green_map_heights_old, MKCOLOUR_XXXX(0x54)},
01340 {_dark_green_map_heights_old, MKCOLOUR_XXXX(0x62)},
01341 {_violet_map_heights_old, MKCOLOUR_XXXX(0x82)},
01342 };
01343
01345 static const SmallMapColourScheme _heightmap_schemes_extended[] = {
01346 {_green_map_heights_extended, MKCOLOUR(0x54545454)},
01347 {_dark_green_map_heights_extended, MKCOLOUR(0x62626262)},
01348 {_violet_map_heights_extended, MKCOLOUR(0x82828282)},
01349 };
01350
01354 void BuildLandLegend()
01355 {
01356 if (AllowMoreHeightlevels()) {
01357 for (LegendAndColour *lc = _legend_land_contours_extended; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
01358 lc->colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
01359 }
01360 } else {
01361 for (LegendAndColour *lc = _legend_land_contours_old; lc->legend == STR_TINY_BLACK_HEIGHT; lc++) {
01362 lc->colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].height_colours[lc->height];
01363 }
01364 }
01365 }
01366
01370 void BuildOwnerLegend()
01371 {
01372 if (AllowMoreHeightlevels()) {
01373 _legend_land_owners[1].colour = _heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour].default_colour;
01374 } else {
01375 _legend_land_owners[1].colour = _heightmap_schemes_old[_settings_client.gui.smallmap_land_colour].default_colour;
01376 }
01377
01378 int i = NUM_NO_COMPANY_ENTRIES;
01379 const Company *c;
01380 FOR_ALL_COMPANIES(c) {
01381 _legend_land_owners[i].colour = _colour_gradient[c->colour][5];
01382 _legend_land_owners[i].company = c->index;
01383 _legend_land_owners[i].show_on_map = true;
01384 _legend_land_owners[i].col_break = false;
01385 _legend_land_owners[i].end = false;
01386 _company_to_list_pos[c->index] = i;
01387 i++;
01388 }
01389
01390
01391 _legend_land_owners[i].end = true;
01392
01393
01394 _smallmap_company_count = i;
01395 }
01396
01397 struct AndOr {
01398 uint32 mor;
01399 uint32 mand;
01400 };
01401
01402 static inline uint32 ApplyMask(uint32 colour, const AndOr *mask)
01403 {
01404 return (colour & mask->mand) | mask->mor;
01405 }
01406
01408 static const AndOr _smallmap_contours_andor[] = {
01409 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01410 {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F},
01411 {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
01412 {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F},
01413 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01414 {MKCOLOUR_XXXX(PC_LIGHT_BLUE), MKCOLOUR_0000},
01415 {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000},
01416 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01417 {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000},
01418 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01419 {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F},
01420 {MKCOLOUR_0XX0(PC_GREY ), MKCOLOUR_F00F},
01421 };
01422
01424 static const AndOr _smallmap_vehicles_andor[] = {
01425 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01426 {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
01427 {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
01428 {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F},
01429 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01430 {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
01431 {MKCOLOUR_XXXX(PC_WATER ), MKCOLOUR_0000},
01432 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01433 {MKCOLOUR_XXXX(PC_DARK_RED ), MKCOLOUR_0000},
01434 {MKCOLOUR_0000 , MKCOLOUR_FFFF},
01435 {MKCOLOUR_0XX0(PC_DARK_RED ), MKCOLOUR_F00F},
01436 {MKCOLOUR_0XX0(PC_BLACK ), MKCOLOUR_F00F},
01437 };
01438
01440 static const byte _tiletype_importance[] = {
01441 2,
01442 8,
01443 7,
01444 5,
01445 2,
01446 9,
01447 2,
01448 1,
01449 6,
01450 8,
01451 2,
01452 0,
01453 };
01454
01455
01456 static inline TileType GetEffectiveTileType(TileIndex tile)
01457 {
01458 TileType t = GetTileType(tile);
01459
01460 if (t == MP_TUNNELBRIDGE) {
01461 TransportType tt = GetTunnelBridgeTransportType(tile);
01462
01463 switch (tt) {
01464 case TRANSPORT_RAIL: t = MP_RAILWAY; break;
01465 case TRANSPORT_ROAD: t = MP_ROAD; break;
01466 default: t = MP_WATER; break;
01467 }
01468 }
01469 return t;
01470 }
01471
01478 static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
01479 {
01480 uint tile_height = TileHeight(tile);
01481
01482 if (_settings_client.gui.smallmap_land_colour == 0) {
01483 if (AllowMoreHeightlevels()) {
01484 if(_settings_client.gui.smallmap_flood_warning) {
01485 return ApplyMask(_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
01486 } else {
01487 return ApplyMask(_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
01488 }
01489 } else {
01490 if(_settings_client.gui.smallmap_flood_warning) {
01491 return ApplyMask(_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
01492 } else {
01493 return ApplyMask(_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
01494 }
01495 }
01496 } else if (_settings_client.gui.smallmap_land_colour == 1) {
01497 if (AllowMoreHeightlevels()) {
01498 if(_settings_client.gui.smallmap_flood_warning) {
01499 return ApplyMask(_dark_green_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
01500 } else {
01501 return ApplyMask(_dark_green_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
01502 }
01503 } else {
01504 if(_settings_client.gui.smallmap_flood_warning) {
01505 return ApplyMask(_dark_green_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
01506 } else {
01507 return ApplyMask(_dark_green_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
01508 }
01509 }
01510 } else {
01511 if (AllowMoreHeightlevels()) {
01512 if(_settings_client.gui.smallmap_flood_warning) {
01513 return ApplyMask(_violet_map_heights_extended[tile_height], &_smallmap_contours_andor[t]);
01514 } else {
01515 return ApplyMask(_violet_map_heights_extended[tile_height + 1], &_smallmap_contours_andor[t]);
01516 }
01517 } else {
01518 if(_settings_client.gui.smallmap_flood_warning) {
01519 return ApplyMask(_violet_map_heights_old[tile_height], &_smallmap_contours_andor[t]);
01520 } else {
01521 return ApplyMask(_violet_map_heights_old[tile_height + 1], &_smallmap_contours_andor[t]);
01522 }
01523 }
01524 }
01525 }
01526
01534 static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
01535 {
01536 if (AllowMoreHeightlevels()) {
01537 const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
01538 return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
01539 } else {
01540 const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
01541 return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
01542 }
01543 }
01544
01552 static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
01553 {
01554 if (t == MP_INDUSTRY) {
01555
01556 if (_legend_from_industries[_industry_to_list_pos[Industry::GetByTile(tile)->type]].show_on_map) {
01557 return GetIndustrySpec(Industry::GetByTile(tile)->type)->map_colour * 0x01010101;
01558 } else {
01559
01560 t = (IsTileOnWater(tile) ? MP_WATER : MP_CLEAR);
01561 }
01562 }
01563
01564 if (_settings_client.gui.smallmap_land_colour == 0) {
01565 if (AllowMoreHeightlevels()) {
01566 if(_settings_client.gui.smallmap_flood_warning) {
01567 return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
01568 } else {
01569 return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
01570 }
01571 } else {
01572 if(_settings_client.gui.smallmap_flood_warning) {
01573 return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
01574 } else {
01575 return ApplyMask(_smallmap_show_heightmap ? _green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x54545454), &_smallmap_vehicles_andor[t]);
01576 }
01577 }
01578 } else if (_settings_client.gui.smallmap_land_colour == 1) {
01579 if (AllowMoreHeightlevels()) {
01580 if(_settings_client.gui.smallmap_flood_warning) {
01581 return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
01582 } else {
01583 return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
01584 }
01585 } else {
01586 if(_settings_client.gui.smallmap_flood_warning) {
01587 return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
01588 } else {
01589 return ApplyMask(_smallmap_show_heightmap ? _dark_green_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x62626262), &_smallmap_vehicles_andor[t]);
01590 }
01591 }
01592 } else {
01593 if (AllowMoreHeightlevels()) {
01594 if(_settings_client.gui.smallmap_flood_warning) {
01595 return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
01596 } else {
01597 return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_extended[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
01598 }
01599 } else {
01600 if(_settings_client.gui.smallmap_flood_warning) {
01601 return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile)] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
01602 } else {
01603 return ApplyMask(_smallmap_show_heightmap ? _violet_map_heights_old[TileHeight(tile) + 1] : MKCOLOUR(0x82828282), &_smallmap_vehicles_andor[t]);
01604 }
01605 }
01606 }
01607 }
01608
01616 static inline uint32 GetSmallMapStuckRoutesPixels(TileIndex tile, TileType t)
01617 {
01618 if (t == MP_STATION) {
01619 switch (GetStationType(tile)) {
01620 case STATION_RAIL: return MKCOLOUR(0x56565656);
01621 case STATION_AIRPORT: return MKCOLOUR(0xB8B8B8B8);
01622 case STATION_TRUCK: return MKCOLOUR(0xC2C2C2C2);
01623 case STATION_BUS: return MKCOLOUR(0xBFBFBFBF);
01624 case STATION_DOCK: return MKCOLOUR(0x98989898);
01625 default: return MKCOLOUR(0xFFFFFFFF);
01626 }
01627 } else if (t == MP_RAILWAY) {
01628 byte c = GetStuckCounter(tile);
01629 if (c==0) return 0;
01630 return _stuck_counter_colours[c/32];
01631 }
01632
01633
01634 if (AllowMoreHeightlevels()) {
01635 const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
01636 return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
01637 } else {
01638 const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
01639 return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
01640 }
01641 }
01642
01650 static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
01651 {
01652 if (t == MP_STATION) {
01653 switch (GetStationType(tile)) {
01654 case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
01655 case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
01656 case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
01657 case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
01658 case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
01659 default: return MKCOLOUR_FFFF;
01660 }
01661 } else if (t == MP_RAILWAY) {
01662 AndOr andor = {
01663 MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
01664 _smallmap_contours_andor[t].mand
01665 };
01666
01667 if (AllowMoreHeightlevels()) {
01668 const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
01669 return ApplyMask(cs->default_colour, &andor);
01670 } else {
01671 const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
01672 return ApplyMask(cs->default_colour, &andor);
01673 }
01674 }
01675
01676
01677 if (AllowMoreHeightlevels()) {
01678 const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
01679 return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
01680 } else {
01681 const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
01682 return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
01683 }
01684 }
01685
01693 static inline uint32 GetSmallMapLinkStatsPixels(TileIndex tile, TileType t)
01694 {
01695 return _smallmap_show_heightmap ? GetSmallMapContoursPixels(tile, t) : GetSmallMapRoutesPixels(tile, t);
01696 }
01697
01698 static const uint32 _vegetation_clear_bits[] = {
01699 MKCOLOUR_XXXX(PC_GRASS_LAND),
01700 MKCOLOUR_XXXX(PC_ROUGH_LAND),
01701 MKCOLOUR_XXXX(PC_GREY),
01702 MKCOLOUR_XXXX(PC_FIELDS),
01703 MKCOLOUR_XXXX(PC_LIGHT_BLUE),
01704 MKCOLOUR_XXXX(PC_ORANGE),
01705 MKCOLOUR_XXXX(PC_GRASS_LAND),
01706 MKCOLOUR_XXXX(PC_GRASS_LAND),
01707 };
01708
01716 static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
01717 {
01718 switch (t) {
01719 case MP_CLEAR:
01720 return (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) < 3) ? MKCOLOUR_XXXX(PC_BARE_LAND) : _vegetation_clear_bits[GetClearGround(tile)];
01721
01722 case MP_INDUSTRY:
01723 return GetIndustrySpec(Industry::GetByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR_XXXX(PC_GREEN) : MKCOLOUR_XXXX(PC_DARK_RED);
01724
01725 case MP_TREES:
01726 if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT || GetTreeGround(tile) == TREE_GROUND_ROUGH_SNOW) {
01727 return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
01728 }
01729 return MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
01730
01731 default:
01732 return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
01733 }
01734 }
01735
01743 static inline uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t)
01744 {
01745 Owner o;
01746
01747 switch (t) {
01748 case MP_INDUSTRY: return MKCOLOUR_XXXX(PC_DARK_GREY);
01749 case MP_HOUSE: return MKCOLOUR_XXXX(PC_DARK_RED);
01750 default: o = GetTileOwner(tile); break;
01751
01752
01753
01754
01755 }
01756
01757 if ((o < MAX_COMPANIES && !_legend_land_owners[_company_to_list_pos[o]].show_on_map) || o == OWNER_NONE || o == OWNER_WATER) {
01758 if (t == MP_WATER) return MKCOLOUR_XXXX(PC_WATER);
01759 if (AllowMoreHeightlevels()) {
01760 const SmallMapColourScheme *cs = &_heightmap_schemes_extended[_settings_client.gui.smallmap_land_colour];
01761 if(_settings_client.gui.smallmap_flood_warning) {
01762 return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
01763 } else {
01764 return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
01765
01766 }
01767 } else {
01768 const SmallMapColourScheme *cs = &_heightmap_schemes_old[_settings_client.gui.smallmap_land_colour];
01769 if(_settings_client.gui.smallmap_flood_warning) {
01770 return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour;
01771 } else {
01772 return _smallmap_show_heightmap ? cs->height_colours[TileHeight(tile) + 1] : cs->default_colour;
01773 }
01774 }
01775 } else if (o == OWNER_TOWN) {
01776 return MKCOLOUR_XXXX(PC_DARK_RED);
01777 }
01778
01779 return MKCOLOUR_XXXX(_legend_land_owners[_company_to_list_pos[o]].colour);
01780 }
01781
01782 static Point TileCoordFromScreenCoord(int x, int y)
01783 {
01784
01785
01786
01787 Point pt;
01788 pt.x = (2 * y - x) / 4;
01789 pt.y = (x + 2 * y) / 4;
01790 return pt;
01791 }
01792
01794 static const byte _vehicle_type_colours[6] = {
01795 PC_RED, PC_YELLOW, PC_LIGHT_BLUE, PC_WHITE, PC_BLACK, PC_RED
01796 };
01797
01806 void DrawVertex(int x, int y, int size, int colour, int border_colour)
01807 {
01808 size--;
01809 int w1 = size / 2;
01810 int w2 = size / 2 + size % 2;
01811
01812 GfxFillRect(x - w1, y - w1, x + w2, y + w2, colour);
01813
01814 w1++;
01815 w2++;
01816 GfxDrawLine(x - w1, y - w1, x + w2, y - w1, border_colour);
01817 GfxDrawLine(x - w1, y + w2, x + w2, y + w2, border_colour);
01818 GfxDrawLine(x - w1, y - w1, x - w1, y + w2, border_colour);
01819 GfxDrawLine(x + w2, y - w1, x + w2, y + w2, border_colour);
01820 }
01821
01823 class SmallMapWindow : public Window {
01825 enum SmallMapType {
01826 SMT_CONTOUR,
01827 SMT_VEHICLES,
01828 SMT_INDUSTRY,
01829 SMT_LINKSTATS,
01830 SMT_ROUTES,
01831 SMT_VEGETATION,
01832 SMT_OWNER,
01833 };
01834
01842 struct VehicleAndPosition {
01843 VehicleAndPosition(const Vehicle *v) : vehicle(v->index)
01844 {
01845 this->position.x = v->x_pos;
01846 this->position.y = v->y_pos;
01847 }
01848
01849 Point position;
01850 VehicleID vehicle;
01851 };
01852
01853 typedef std::list<VehicleAndPosition> VehicleList;
01854 VehicleList vehicles_on_map;
01855
01857 enum ZoomLevelChange {
01858 ZLC_INITIALIZE,
01859 ZLC_ZOOM_OUT,
01860 ZLC_ZOOM_IN,
01861 };
01862
01863 static SmallMapType map_type;
01864 static bool show_towns;
01865
01866 static const uint LEGEND_BLOB_WIDTH = 8;
01867 static const uint INDUSTRY_MIN_NUMBER_OF_COLUMNS = 2;
01868 uint min_number_of_fixed_rows;
01869 uint column_width;
01870
01871 bool HasButtons()
01872 {
01873 return this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER;
01874 }
01875
01876 Point cursor;
01877
01878 struct BaseCargoDetail {
01879 BaseCargoDetail()
01880 {
01881 this->Clear();
01882 }
01883
01884 void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow)
01885 {
01886 this->capacity += orig_link.Capacity();
01887 this->usage += orig_link.Usage();
01888 this->planned += orig_flow.Planned();
01889 this->sent += orig_flow.Sent();
01890 }
01891
01892 void Clear()
01893 {
01894 this->capacity = this->usage = this->planned = this->sent = 0;
01895 }
01896
01897 uint capacity;
01898 uint usage;
01899 uint planned;
01900 uint sent;
01901 };
01902
01903 struct CargoDetail : public BaseCargoDetail {
01904 CargoDetail(const LegendAndColour * c, const LinkStat &ls, const FlowStat &fs) : legend(c)
01905 {
01906 this->AddLink(ls, fs);
01907 }
01908
01909 const LegendAndColour *legend;
01910 };
01911
01912 typedef std::vector<CargoDetail> StatVector;
01913
01914 struct LinkDetails {
01915 LinkDetails() {this->Clear();}
01916
01917 StationID sta;
01918 StationID stb;
01919 StatVector a_to_b;
01920 StatVector b_to_a;
01921
01922 void Clear()
01923 {
01924 this->sta = INVALID_STATION;
01925 this->stb = INVALID_STATION;
01926 this->a_to_b.clear();
01927 this->b_to_a.clear();
01928 }
01929
01930 bool Empty() const
01931 {
01932 return this->sta == INVALID_STATION;
01933 }
01934 };
01935
01940 mutable LinkDetails link_details;
01941 mutable StationID supply_details;
01942
01943 int32 scroll_x;
01944 int32 scroll_y;
01945 int32 subscroll;
01946 int zoom;
01947
01948 static const uint8 FORCE_REFRESH_PERIOD = 0x1F;
01949 static const uint8 REFRESH_NEXT_TICK = 1;
01950 uint8 refresh;
01951
01958 FORCEINLINE Point RemapTile(int tile_x, int tile_y) const
01959 {
01960 if (this->zoom > 0) {
01961 int x_offset = tile_x - this->scroll_x / (int)TILE_SIZE;
01962 int y_offset = tile_y - this->scroll_y / (int)TILE_SIZE;
01963
01964
01965 if (x_offset < 0) x_offset -= this->zoom - 1;
01966 if (y_offset < 0) y_offset -= this->zoom - 1;
01967
01968 return RemapCoords(x_offset / this->zoom, y_offset / this->zoom, 0);
01969 } else {
01970 int x_offset = tile_x * (-this->zoom) - this->scroll_x * (-this->zoom) / (int)TILE_SIZE;
01971 int y_offset = tile_y * (-this->zoom) - this->scroll_y * (-this->zoom) / (int)TILE_SIZE;
01972
01973 return RemapCoords(x_offset, y_offset, 0);
01974 }
01975 }
01976
01987 FORCEINLINE Point PixelToWorld(int px, int py, int *sub, bool add_sub = true) const
01988 {
01989 if (add_sub) px += this->subscroll;
01990
01991
01992
01993 Point pt = {
01994 ((py >> 1) - (px >> 2)) * TILE_SIZE,
01995 ((py >> 1) + (px >> 2)) * TILE_SIZE
01996 };
01997
01998 if (this->zoom > 0) {
01999 pt.x *= this->zoom;
02000 pt.y *= this->zoom;
02001 } else {
02002 pt.x /= (-this->zoom);
02003 pt.y /= (-this->zoom);
02004 }
02005
02006 px &= 3;
02007
02008 if (py & 1) {
02009 int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
02010 if (px < 2) {
02011 pt.x += offset;
02012 px += 2;
02013 } else {
02014 pt.y += offset;
02015 px -= 2;
02016 }
02017 }
02018
02019 *sub = px;
02020 return pt;
02021 }
02022
02032 Point ComputeScroll(int tx, int ty, int x, int y, int *sub)
02033 {
02034 assert(x >= 0 && y >= 0);
02035
02036 int new_sub;
02037 Point tile_xy = PixelToWorld(x, y, &new_sub, false);
02038 tx -= tile_xy.x;
02039 ty -= tile_xy.y;
02040
02041 int offset = this->zoom < 0 ? TILE_SIZE / (-this->zoom) : this->zoom * TILE_SIZE;
02042
02043 Point scroll;
02044 if (new_sub == 0) {
02045 *sub = 0;
02046 scroll.x = tx + offset;
02047 scroll.y = ty - offset;
02048 } else {
02049 *sub = 4 - new_sub;
02050 scroll.x = tx + 2 * offset;
02051 scroll.y = ty - 2 * offset;
02052 }
02053 return scroll;
02054 }
02055
02062 void SetZoomLevel(ZoomLevelChange change, const Point *zoom_pt)
02063 {
02064 static const int zoomlevels[] = {-4, -2, 1, 2, 4, 6, 8};
02065 static const int MIN_ZOOM_INDEX = 0;
02066 static const int DEFAULT_ZOOM_INDEX = 2;
02067 static const int MAX_ZOOM_INDEX = lengthof(zoomlevels) - 1;
02068
02069 int new_index, cur_index, sub;
02070 Point position;
02071 switch (change) {
02072 case ZLC_INITIALIZE:
02073 cur_index = - 1;
02074 new_index = DEFAULT_ZOOM_INDEX;
02075 break;
02076
02077 case ZLC_ZOOM_IN:
02078 case ZLC_ZOOM_OUT:
02079 for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
02080 if (this->zoom == zoomlevels[cur_index]) break;
02081 }
02082 assert(cur_index <= MAX_ZOOM_INDEX);
02083
02084 position = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
02085 new_index = Clamp(cur_index + ((change == ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
02086 break;
02087
02088 default: NOT_REACHED();
02089 }
02090
02091 if (new_index != cur_index) {
02092 this->zoom = zoomlevels[new_index];
02093 if (cur_index >= 0) {
02094 Point new_pos = this->PixelToWorld(zoom_pt->x, zoom_pt->y, &sub);
02095 this->SetNewScroll(this->scroll_x + position.x - new_pos.x,
02096 this->scroll_y + position.y - new_pos.y, sub);
02097 }
02098 this->SetWidgetDisabledState(SM_WIDGET_ZOOM_IN, this->zoom == zoomlevels[MIN_ZOOM_INDEX]);
02099 this->SetWidgetDisabledState(SM_WIDGET_ZOOM_OUT, this->zoom == zoomlevels[MAX_ZOOM_INDEX]);
02100 this->SetDirty();
02101 }
02102 }
02103
02109 inline uint32 GetTileColours(const TileArea &ta) const
02110 {
02111 int importance = 0;
02112 TileIndex tile = INVALID_TILE;
02113 TileType et = MP_VOID;
02114
02115 TILE_AREA_LOOP(ti, ta) {
02116 TileType ttype = GetEffectiveTileType(ti);
02117 if (_tiletype_importance[ttype] > importance) {
02118 importance = _tiletype_importance[ttype];
02119 tile = ti;
02120 et = ttype;
02121 }
02122 }
02123
02124 switch (this->map_type) {
02125 case SMT_CONTOUR:
02126 return GetSmallMapContoursPixels(tile, et);
02127
02128 case SMT_VEHICLES:
02129 return GetSmallMapVehiclesPixels(tile, et);
02130
02131 case SMT_INDUSTRY:
02132 return GetSmallMapIndustriesPixels(tile, et);
02133
02134 case SMT_ROUTES:
02135 return GetSmallMapStuckRoutesPixels(tile, et);
02136
02137 case SMT_VEGETATION:
02138 return GetSmallMapVegetationPixels(tile, et);
02139
02140 case SMT_OWNER:
02141 return GetSmallMapOwnerPixels(tile, et);
02142
02143 case SMT_LINKSTATS:
02144 return GetSmallMapLinkStatsPixels(tile, et);
02145
02146 default: NOT_REACHED();
02147 }
02148 }
02149
02164 void DrawSmallMapColumn(void *dst, uint xc, uint yc, int pitch, int reps, int start_pos, int end_pos, Blitter *blitter) const
02165 {
02166 void *dst_ptr_abs_end = blitter->MoveTo(_screen.dst_ptr, 0, _screen.height);
02167 uint min_xy = _settings_game.construction.freeform_edges ? 1 : 0;
02168
02169 int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
02170 int extent = this->zoom > 0 ? this->zoom : 1;
02171
02172 do {
02173
02174 if (xc / TILE_SIZE >= MapMaxX() || yc / TILE_SIZE >= MapMaxY()) continue;
02175
02176
02177 if (dst < _screen.dst_ptr) continue;
02178 if (dst >= dst_ptr_abs_end) continue;
02179
02180
02181 TileArea ta;
02182 if (min_xy == 1 && (xc < TILE_SIZE || yc < TILE_SIZE)) {
02183 if (this->zoom <= 1) continue;
02184
02185 ta = TileArea(TileXY(max(min_xy, xc / TILE_SIZE), max(min_xy, yc / TILE_SIZE)), this->zoom - (xc < TILE_SIZE), this->zoom - (yc < TILE_SIZE));
02186 } else {
02187 ta = TileArea(TileXY(xc / TILE_SIZE, yc / TILE_SIZE), extent, extent);
02188 }
02189 ta.ClampToMap();
02190
02191 uint32 val = this->GetTileColours(ta);
02192 uint8 *val8 = (uint8 *)&val;
02193 int idx = max(0, -start_pos);
02194 for (int pos = max(0, start_pos); pos < end_pos; pos++) {
02195 blitter->SetPixel(dst, idx, 0, val8[idx]);
02196 idx++;
02197 }
02198
02199 } while (xc += increment, yc += increment, dst = blitter->MoveTo(dst, pitch, 0), --reps != 0);
02200 }
02201
02207 void DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) const
02208 {
02209 for(VehicleList::const_iterator i = this->vehicles_on_map.begin(); i != this->vehicles_on_map.end(); ++i) {
02210 const Vehicle *v = Vehicle::GetIfValid(i->vehicle);
02211 if (v == NULL) continue;
02212
02213
02214 Point pt = RemapTile(i->position.x / (int)TILE_SIZE, i->position.y / (int)TILE_SIZE);
02215
02216 int y = pt.y - dpi->top;
02217 int x = pt.x - this->subscroll - 3 - dpi->left;
02218
02219 int scale = this->zoom < 0 ? -this->zoom : 1;
02220
02221
02222 byte colour = (this->map_type == SMT_VEHICLES) ? _vehicle_type_colours[v->type] : PC_WHITE;
02223
02224
02225 for (int dy = 0; dy < scale; dy++) {
02226 for (int dx = 0; dx < scale; dx++) {
02227 Point pt = RemapCoords(dx, dy, 0);
02228 if (IsInsideMM(y + pt.y, 0, dpi->height)) {
02229 if (IsInsideMM(x + pt.x, 0, dpi->width)) {
02230 blitter->SetPixel(dpi->dst_ptr, x + pt.x, y + pt.y, colour);
02231 }
02232 if (IsInsideMM(x + pt.x + 1, 0, dpi->width)) {
02233 blitter->SetPixel(dpi->dst_ptr, x + pt.x + 1, y + pt.y, colour);
02234 }
02235 }
02236 }
02237 }
02238 }
02239 }
02240
02241 FORCEINLINE Point GetStationMiddle(const Station *st) const
02242 {
02243 int x = (st->rect.right + st->rect.left + 1) / 2;
02244 int y = (st->rect.bottom + st->rect.top + 1) / 2;
02245 Point ret = this->RemapTile(x, y);
02246 ret.x -= 3 + this->subscroll;
02247 if (this->zoom < 0) {
02248
02249 if (((st->rect.bottom - st->rect.top) & 1) == 0) {
02250 Point offset = RemapCoords(0, -this->zoom / 2, 0);
02251 ret.x += offset.x;
02252 ret.y += offset.y;
02253 }
02254 if (((st->rect.right - st->rect.left) & 1) == 0) {
02255 Point offset = RemapCoords(-this->zoom / 2, 0, 0);
02256 ret.x += offset.x;
02257 ret.y += offset.y;
02258 }
02259 }
02260 return ret;
02261 }
02262
02263 StationID DrawStationDots() const
02264 {
02265 const Station *supply_details = NULL;
02266
02267 const Station *st;
02268 FOR_ALL_STATIONS(st) {
02269 if (((st->owner != _local_company && Company::IsValidID(st->owner)) ||
02270 st->rect.IsEmpty()) && _settings_client.gui.linkgraph_companies == 0) continue;
02271
02272 Point pt = GetStationMiddle(st);
02273
02274 if (supply_details == NULL && CheckStationSelected(&pt)) {
02275 supply_details = st;
02276 }
02277
02278
02279 uint q = 0;
02280 int colour = 0;
02281 int numCargos = 0;
02282
02283 if (AllowMoreHeightlevels()) {
02284 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02285 const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
02286 if (!tbl.show_on_map && supply_details != st) continue;
02287 uint supply = st->goods[tbl.type].supply;
02288 if (supply > 0) {
02289 q += supply;
02290 colour += tbl.colour;
02291 numCargos++;
02292 }
02293 }
02294
02295 } else {
02296 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02297 const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
02298 if (!tbl.show_on_map && supply_details != st) continue;
02299 uint supply = st->goods[tbl.type].supply;
02300 if (supply > 0) {
02301 q += supply;
02302 colour += tbl.colour;
02303 numCargos++;
02304 }
02305 }
02306 }
02307
02308 if (numCargos > 1) colour /= numCargos;
02309
02310 uint r = 2;
02311 if (q >= 10) r++;
02312 if (q >= 20) r++;
02313 if (q >= 40) r++;
02314 if (q >= 80) r++;
02315 if (q >= 160) r++;
02316
02317 DrawVertex(pt.x, pt.y, r, colour, _colour_gradient[COLOUR_GREY][supply_details == st ? 3 : 1]);
02318 }
02319 return (supply_details == NULL) ? INVALID_STATION : supply_details->index;
02320 }
02321
02322 class LinkDrawer {
02323
02324 protected:
02325 virtual void DrawContent() = 0;
02326 virtual void Highlight() {}
02327 virtual void AddLink(const LinkStat &orig_link, const FlowStat &orig_flow, const LegendAndColour &cargo_entry) = 0;
02328
02329 FORCEINLINE bool IsLinkVisible()
02330 {
02331 const NWidgetBase *wi = this->window->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
02332 return !((this->pta.x < 0 && this->ptb.x < 0) ||
02333 (this->pta.y < 0 && this->ptb.y < 0) ||
02334 (this->pta.x > (int)wi->current_x && this->ptb.x > (int)wi->current_x) ||
02335 (this->pta.y > (int)wi->current_y && this->ptb.y > (int)wi->current_y));
02336 }
02337
02338 Point pta, ptb;
02339 bool search_link_details;
02340 LinkDetails link_details;
02341 const SmallMapWindow *window;
02342
02343 void DrawLink(StationID sta, StationID stb)
02344 {
02345 bool highlight_empty = this->search_link_details && this->link_details.Empty();
02346 bool highlight =
02347 (sta == this->link_details.sta && stb == this->link_details.stb) ||
02348 (highlight_empty && window->CheckLinkSelected(&this->pta, &this->ptb));
02349 bool reverse_empty = this->link_details.b_to_a.empty();
02350 bool reverse_highlight = (sta == this->link_details.stb && stb == this->link_details.sta);
02351 if (highlight_empty && highlight) {
02352 this->link_details.sta = sta;
02353 this->link_details.stb = stb;
02354 }
02355
02356 if (highlight || reverse_highlight) {
02357 this->Highlight();
02358 }
02359
02360 if (AllowMoreHeightlevels()) {
02361 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02362 const LegendAndColour &cargo_entry = _legend_table_extended[window->map_type][i];
02363 CargoID cargo = cargo_entry.type;
02364 if (cargo_entry.show_on_map || highlight || reverse_highlight) {
02365 GoodsEntry &ge = Station::Get(sta)->goods[cargo];
02366 FlowStat sum_flows = ge.GetSumFlowVia(stb);
02367 const LinkStatMap &ls_map = ge.link_stats;
02368 LinkStatMap::const_iterator i = ls_map.find(stb);
02369 if (i != ls_map.end()) {
02370 const LinkStat &link_stat = i->second;
02371 this->AddLink(link_stat, sum_flows, cargo_entry);
02372 if (highlight_empty && highlight) {
02373 this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
02374 } else if (reverse_empty && reverse_highlight) {
02375 this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
02376 }
02377 }
02378 }
02379 }
02380
02381 } else {
02382 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02383 const LegendAndColour &cargo_entry = _legend_table_old[window->map_type][i];
02384 CargoID cargo = cargo_entry.type;
02385 if (cargo_entry.show_on_map || highlight || reverse_highlight) {
02386 GoodsEntry &ge = Station::Get(sta)->goods[cargo];
02387 FlowStat sum_flows = ge.GetSumFlowVia(stb);
02388 const LinkStatMap &ls_map = ge.link_stats;
02389 LinkStatMap::const_iterator i = ls_map.find(stb);
02390 if (i != ls_map.end()) {
02391 const LinkStat &link_stat = i->second;
02392 this->AddLink(link_stat, sum_flows, cargo_entry);
02393 if (highlight_empty && highlight) {
02394 this->link_details.a_to_b.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
02395 } else if (reverse_empty && reverse_highlight) {
02396 this->link_details.b_to_a.push_back(CargoDetail(&cargo_entry, link_stat, sum_flows));
02397 }
02398 }
02399 }
02400 }
02401 }
02402 }
02403
02404 virtual void DrawForwBackLinks(StationID sta, StationID stb)
02405 {
02406 this->DrawLink(sta, stb);
02407 this->DrawContent();
02408 Swap(this->pta, this->ptb);
02409 this->DrawLink(stb, sta);
02410 this->DrawContent();
02411 }
02412
02413 public:
02414 virtual ~LinkDrawer() {}
02415
02416 LinkDetails DrawLinks(const SmallMapWindow * w, bool search)
02417 {
02418 this->link_details.Clear();
02419 this->window = w;
02420 this->search_link_details = search;
02421 std::set<StationID> seen_stations;
02422 std::set<std::pair<StationID, StationID> > seen_links;
02423
02424 const Station *sta;
02425 if (AllowMoreHeightlevels()) {
02426 FOR_ALL_STATIONS(sta) {
02427 if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue;
02428
02429 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02430 const LegendAndColour &tbl = _legend_table_extended[window->map_type][i];
02431 if (!tbl.show_on_map) continue;
02432
02433 CargoID c = tbl.type;
02434 const LinkStatMap &links = sta->goods[c].link_stats;
02435 for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
02436 StationID from = sta->index;
02437 StationID to = i->first;
02438 if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
02439 const Station *stb = Station::Get(to);
02440
02441 if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue;
02442 if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
02443 if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
02444
02445 this->pta = this->window->GetStationMiddle(sta);
02446 this->ptb = this->window->GetStationMiddle(stb);
02447 if (!this->IsLinkVisible()) continue;
02448
02449 this->DrawForwBackLinks(sta->index, stb->index);
02450 seen_stations.insert(to);
02451 }
02452 seen_links.insert(std::make_pair(from, to));
02453 }
02454 }
02455 seen_stations.clear();
02456 }
02457
02458 } else {
02459 FOR_ALL_STATIONS(sta) {
02460 if (sta->owner != _local_company && Company::IsValidID(sta->owner) && _settings_client.gui.linkgraph_companies == 0) continue;
02461
02462 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02463 const LegendAndColour &tbl = _legend_table_old[window->map_type][i];
02464 if (!tbl.show_on_map) continue;
02465
02466 CargoID c = tbl.type;
02467 const LinkStatMap &links = sta->goods[c].link_stats;
02468 for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
02469 StationID from = sta->index;
02470 StationID to = i->first;
02471 if (Station::IsValidID(to) && seen_stations.find(to) == seen_stations.end()) {
02472 const Station *stb = Station::Get(to);
02473
02474 if (stb->owner != _local_company && Company::IsValidID(stb->owner) && _settings_client.gui.linkgraph_companies == 0) continue;
02475 if (sta->rect.IsEmpty() || stb->rect.IsEmpty()) continue;
02476 if (seen_links.find(std::make_pair(to, from)) != seen_links.end()) continue;
02477
02478 this->pta = this->window->GetStationMiddle(sta);
02479 this->ptb = this->window->GetStationMiddle(stb);
02480 if (!this->IsLinkVisible()) continue;
02481
02482 this->DrawForwBackLinks(sta->index, stb->index);
02483 seen_stations.insert(to);
02484 }
02485 seen_links.insert(std::make_pair(from, to));
02486 }
02487 }
02488
02489 seen_stations.clear();
02490 }
02491 }
02492 return this->link_details;
02493 }
02494
02495 };
02496
02497 class LinkLineDrawer : public LinkDrawer {
02498 public:
02499 LinkLineDrawer() : highlight(false) {}
02500
02501 protected:
02502 typedef std::set<uint16> ColourSet;
02503 ColourSet colours;
02504 bool highlight;
02505
02506 virtual void DrawForwBackLinks(StationID sta, StationID stb)
02507 {
02508 this->DrawLink(sta, stb);
02509 this->DrawLink(stb, sta);
02510 this->DrawContent();
02511 }
02512
02513 virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
02514 {
02515 this->colours.insert(cargo_entry.colour);
02516 }
02517
02518 virtual void Highlight()
02519 {
02520 this->highlight = true;
02521 }
02522
02523 virtual void DrawContent()
02524 {
02525 uint colour = 0;
02526 uint num_colours = 0;
02527 for (ColourSet::iterator i = colours.begin(); i != colours.end(); ++i) {
02528 colour += *i;
02529 num_colours++;
02530 }
02531 colour /= num_colours;
02532 byte border_colour = _colour_gradient[COLOUR_GREY][highlight ? 3 : 1];
02533 GfxDrawLine(this->pta.x - 1, this->pta.y, this->ptb.x - 1, this->ptb.y, border_colour);
02534 GfxDrawLine(this->pta.x + 1, this->pta.y, this->ptb.x + 1, this->ptb.y, border_colour);
02535 GfxDrawLine(this->pta.x, this->pta.y - 1, this->ptb.x, this->ptb.y - 1, border_colour);
02536 GfxDrawLine(this->pta.x, this->pta.y + 1, this->ptb.x, this->ptb.y + 1, border_colour);
02537 GfxDrawLine(this->pta.x, this->pta.y, this->ptb.x, this->ptb.y, colour);
02538 this->colours.clear();
02539 this->highlight = false;
02540 }
02541 };
02542
02543 class LinkValueDrawer : public LinkDrawer, public BaseCargoDetail {
02544 protected:
02545
02546 virtual void AddLink(const LinkStat & orig_link, const FlowStat & orig_flow, const LegendAndColour &cargo_entry)
02547 {
02548 this->BaseCargoDetail::AddLink(orig_link, orig_flow);
02549 }
02550 };
02551
02552 class LinkTextDrawer : public LinkValueDrawer {
02553 protected:
02554 virtual void DrawContent()
02555 {
02556 Point ptm;
02557 ptm.x = (this->pta.x + 2*this->ptb.x) / 3;
02558 ptm.y = (this->pta.y + 2*this->ptb.y) / 3;
02559 int nums = 0;
02560 if (_legend_linkstats[_smallmap_cargo_count + STAT_CAPACITY].show_on_map) {
02561 SetDParam(nums++, this->capacity);
02562 }
02563 if (_legend_linkstats[_smallmap_cargo_count + STAT_USAGE].show_on_map) {
02564 SetDParam(nums++, this->usage);
02565 }
02566 if (_legend_linkstats[_smallmap_cargo_count + STAT_PLANNED].show_on_map) {
02567 SetDParam(nums++, this->planned);
02568 }
02569 if (_legend_linkstats[_smallmap_cargo_count + STAT_SENT].show_on_map) {
02570 SetDParam(nums++, this->sent);
02571 }
02572 StringID str;
02573 switch (nums) {
02574 case 0:
02575 str = STR_EMPTY; break;
02576 case 1:
02577 str = STR_NUM; break;
02578 case 2:
02579 str = STR_NUM_RELATION_2; break;
02580 case 3:
02581 str = STR_NUM_RELATION_3; break;
02582 case 4:
02583 str = STR_NUM_RELATION_4; break;
02584 default:
02585 NOT_REACHED();
02586 }
02587 DrawString(ptm.x, ptm.x + this->window->ColumnWidth(), ptm.y, str, TC_WHITE);
02588 this->Clear();
02589 }
02590 };
02591
02592 class LinkGraphDrawer : public LinkValueDrawer {
02593 typedef std::multimap<uint, byte, std::greater<uint> > SizeMap;
02594 protected:
02595 virtual void DrawContent()
02596 {
02597 Point ptm;
02598 SizeMap sizes;
02599
02600
02601
02602 const LegendAndColour *legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_USAGE;
02603 if (legend_entry->show_on_map && this->usage > 0) {
02604 sizes.insert(std::make_pair((uint)sqrt((float)this->usage), legend_entry->colour));
02605 }
02606 legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_CAPACITY;
02607 if (legend_entry->show_on_map && this->capacity > 0) {
02608 sizes.insert(std::make_pair((uint)sqrt((float)this->capacity), legend_entry->colour));
02609 }
02610 legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_PLANNED;
02611 if (legend_entry->show_on_map && this->planned > 0) {
02612 sizes.insert(std::make_pair((uint)sqrt((float)this->planned), legend_entry->colour));
02613 }
02614 legend_entry = _legend_linkstats + _smallmap_cargo_count + STAT_SENT;
02615 if (legend_entry->show_on_map && this->sent > 0) {
02616 sizes.insert(std::make_pair((uint)sqrt((float)this->sent), legend_entry->colour));
02617 }
02618
02619 ptm.x = (this->pta.x + this->ptb.x) / 2;
02620 ptm.y = (this->pta.y + this->ptb.y) / 2;
02621
02622 for (SizeMap::iterator i = sizes.begin(); i != sizes.end(); ++i) {
02623 if (this->pta.x > this->ptb.x) {
02624 ptm.x -= 1;
02625 GfxFillRect(ptm.x - i->first / 2, ptm.y - i->first * 2, ptm.x, ptm.y, i->second);
02626 } else {
02627 ptm.x += 1;
02628 GfxFillRect(ptm.x, ptm.y - i->first * 2, ptm.x + i->first / 2, ptm.y, i->second);
02629 }
02630 }
02631 this->Clear();
02632 }
02633 };
02634
02635 static const uint MORE_SPACE_NEEDED = 0x1000;
02636
02637 uint DrawLinkDetails(StatVector &details, uint x, uint y, uint right, uint bottom) const
02638 {
02639 uint x_orig = x;
02640 SetDParam(0, 9999);
02641 static uint entry_width = LEGEND_BLOB_WIDTH +
02642 GetStringBoundingBox(STR_ABBREV_PASSENGERS).width +
02643 GetStringBoundingBox(STR_SMALLMAP_LINK_CAPACITY).width +
02644 GetStringBoundingBox(STR_SMALLMAP_LINK_USAGE).width +
02645 GetStringBoundingBox(STR_SMALLMAP_LINK_PLANNED).width +
02646 GetStringBoundingBox(STR_SMALLMAP_LINK_SENT).width;
02647 uint entries_per_row = (right - x_orig) / entry_width;
02648 if (details.empty()) {
02649 DrawString(x, x + entry_width, y, STR_TINY_NOTHING, TC_BLACK);
02650 return y + FONT_HEIGHT_SMALL;
02651 }
02652 for (uint i = 0; i < details.size(); ++i) {
02653 CargoDetail &detail = details[i];
02654 if (x + entry_width >= right) {
02655 x = x_orig;
02656 y += FONT_HEIGHT_SMALL;
02657 if (y + 2 * FONT_HEIGHT_SMALL > bottom && details.size() - i > entries_per_row) {
02658 return y | MORE_SPACE_NEEDED;
02659 }
02660 }
02661 uint x_next = x + entry_width;
02662 if (detail.legend->show_on_map) {
02663 GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK);
02664 }
02665 GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, detail.legend->colour);
02666 x += LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
02667 TextColour textcol[4];
02668 for (int stat = STAT_CAPACITY; stat <= STAT_SENT; ++stat) {
02669 textcol[stat] = (detail.legend->show_on_map && _legend_linkstats[_smallmap_cargo_count + stat].show_on_map) ?
02670 TC_BLACK : TC_GREY;
02671 }
02672
02673 SetDParam(0, CargoSpec::Get(detail.legend->type)->abbrev);
02674 x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK, detail.legend->show_on_map ? TC_BLACK : TC_GREY);
02675 SetDParam(0, detail.capacity);
02676 x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_CAPACITY, textcol[STAT_CAPACITY]);
02677 SetDParam(0, detail.usage);
02678 x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_USAGE, textcol[STAT_USAGE]);
02679 SetDParam(0, detail.planned);
02680 x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_PLANNED, textcol[STAT_PLANNED]);
02681 SetDParam(0, detail.sent);
02682 x = DrawString(x, x_next - 1, y, STR_SMALLMAP_LINK_SENT, textcol[STAT_SENT]);
02683 x = x_next;
02684 }
02685 return y + FONT_HEIGHT_SMALL;
02686 }
02687
02688 uint DrawLinkDetailCaption(uint x, uint y, uint right, StationID sta, StationID stb) const
02689 {
02690 SetDParam(0, sta);
02691 SetDParam(1, stb);
02692 static uint height = GetStringBoundingBox(STR_SMALLMAP_LINK_CAPTION).height;
02693 DrawString(x, right - 1, y, STR_SMALLMAP_LINK_CAPTION, TC_BLACK);
02694 y += height;
02695 return y;
02696 }
02697
02698 void DrawLinkDetails(uint x, uint y, uint right, uint bottom) const
02699 {
02700 y = DrawLinkDetailCaption(x, y, right, this->link_details.sta, this->link_details.stb);
02701 if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
02702 DrawString(x, right, y, "...", TC_BLACK);
02703 return;
02704 }
02705 y = DrawLinkDetails(this->link_details.a_to_b, x, y, right, bottom);
02706 if (y + 3 * FONT_HEIGHT_SMALL > bottom) {
02707
02708 DrawString(x, right, y, "...", TC_BLACK);
02709 return;
02710 }
02711 y = DrawLinkDetailCaption(x, y + 2, right, this->link_details.stb, this->link_details.sta);
02712 if (y + 2 * FONT_HEIGHT_SMALL > bottom) {
02713 DrawString(x, right, y, "...", TC_BLACK);
02714 return;
02715 }
02716 y = DrawLinkDetails(this->link_details.b_to_a, x, y, right, bottom);
02717 if (y & MORE_SPACE_NEEDED) {
02718
02719 DrawString(x, right, y ^ MORE_SPACE_NEEDED, "...", TC_BLACK);
02720 return;
02721 }
02722 }
02723
02724 void DrawSupplyDetails(uint x, uint y_org, uint bottom) const
02725 {
02726 const Station *st = Station::GetIfValid(this->supply_details);
02727 if (st == NULL) return;
02728 SetDParam(0, this->supply_details);
02729 static uint height = GetStringBoundingBox(STR_SMALLMAP_SUPPLY_CAPTION).height;
02730 DrawString(x, x + 2 * this->column_width - 1, y_org, STR_SMALLMAP_SUPPLY_CAPTION, TC_BLACK);
02731 y_org += height;
02732 uint y = y_org;
02733 if (AllowMoreHeightlevels()) {
02734 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02735 if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
02736
02737
02738 x += this->column_width;
02739 y = y_org;
02740 }
02741
02742 const LegendAndColour &tbl = _legend_table_extended[this->map_type][i];
02743
02744 CargoID c = tbl.type;
02745 uint supply = st->goods[c].supply;
02746 if (supply > 0) {
02747 TextColour textcol = TC_BLACK;
02748 if (tbl.show_on_map) {
02749 GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK);
02750 } else {
02751 textcol = TC_GREY;
02752 }
02753 SetDParam(0, c);
02754 SetDParam(1, supply);
02755 DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
02756 GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour);
02757 y += FONT_HEIGHT_SMALL;
02758 }
02759 }
02760
02761 } else {
02762 for (int i = 0; i < _smallmap_cargo_count; ++i) {
02763 if (y + FONT_HEIGHT_SMALL - 1 >= bottom) {
02764
02765
02766 x += this->column_width;
02767 y = y_org;
02768 }
02769
02770 const LegendAndColour &tbl = _legend_table_old[this->map_type][i];
02771
02772 CargoID c = tbl.type;
02773 uint supply = st->goods[c].supply;
02774 if (supply > 0) {
02775 TextColour textcol = TC_BLACK;
02776 if (tbl.show_on_map) {
02777 GfxFillRect(x, y + 1, x + LEGEND_BLOB_WIDTH, y + FONT_HEIGHT_SMALL - 1, PC_BLACK);
02778 } else {
02779 textcol = TC_GREY;
02780 }
02781 SetDParam(0, c);
02782 SetDParam(1, supply);
02783 DrawString(x + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT, x + this->column_width - 1, y, STR_SMALLMAP_SUPPLY, textcol);
02784 GfxFillRect(x + 1, y + 2, x + LEGEND_BLOB_WIDTH - 1, y + FONT_HEIGHT_SMALL - 2, tbl.colour);
02785 y += FONT_HEIGHT_SMALL;
02786 }
02787 }
02788 }
02789 }
02790
02795 void DrawTowns(const DrawPixelInfo *dpi) const
02796 {
02797 const Town *t;
02798 FOR_ALL_TOWNS(t) {
02799
02800 Point pt = this->RemapTile(TileX(t->xy), TileY(t->xy));
02801 int x = pt.x - this->subscroll - (t->sign.width_small >> 1);
02802 int y = pt.y;
02803
02804
02805 if (x + t->sign.width_small > dpi->left &&
02806 x < dpi->left + dpi->width &&
02807 y + FONT_HEIGHT_SMALL > dpi->top &&
02808 y < dpi->top + dpi->height) {
02809
02810 SetDParam(0, t->index);
02811 DrawString(x, x + t->sign.width_small, y, STR_SMALLMAP_TOWN);
02812 }
02813 }
02814 }
02815
02822 static inline void DrawVertMapIndicator(int x, int y, int y2)
02823 {
02824 GfxFillRect(x, y, x, y + 3, PC_VERY_LIGHT_YELLOW);
02825 GfxFillRect(x, y2 - 3, x, y2, PC_VERY_LIGHT_YELLOW);
02826 }
02827
02834 static inline void DrawHorizMapIndicator(int x, int x2, int y)
02835 {
02836 GfxFillRect(x, y, x + 3, y, PC_VERY_LIGHT_YELLOW);
02837 GfxFillRect(x2 - 3, y, x2, y, PC_VERY_LIGHT_YELLOW);
02838 }
02839
02843 void DrawMapIndicators() const
02844 {
02845
02846 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
02847
02848 Point tile = InverseRemapCoords(vp->virtual_left, vp->virtual_top);
02849 Point tl = this->RemapTile(tile.x >> 4, tile.y >> 4);
02850 tl.x -= this->subscroll;
02851
02852 tile = InverseRemapCoords(vp->virtual_left + vp->virtual_width, vp->virtual_top + vp->virtual_height);
02853 Point br = this->RemapTile(tile.x >> 4, tile.y >> 4);
02854 br.x -= this->subscroll;
02855
02856 SmallMapWindow::DrawVertMapIndicator(tl.x, tl.y, br.y);
02857 SmallMapWindow::DrawVertMapIndicator(br.x, tl.y, br.y);
02858
02859 SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, tl.y);
02860 SmallMapWindow::DrawHorizMapIndicator(tl.x, br.x, br.y);
02861 }
02862
02874 void DrawSmallMap(DrawPixelInfo *dpi) const
02875 {
02876 Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
02877 DrawPixelInfo *old_dpi;
02878
02879 old_dpi = _cur_dpi;
02880 _cur_dpi = dpi;
02881
02882
02883 GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, PC_BLACK);
02884
02885
02886 int dx;
02887 Point position = this->PixelToWorld(dpi->left, dpi->top, &dx);
02888 int pos_x = this->scroll_x + position.x;
02889 int pos_y = this->scroll_y + position.y;
02890
02891 void *ptr = blitter->MoveTo(dpi->dst_ptr, -dx - 4, 0);
02892 int x = - dx - 4;
02893 int y = 0;
02894 int increment = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
02895
02896 for (;;) {
02897
02898 if (x >= -3) {
02899 if (x >= dpi->width) break;
02900
02901 int end_pos = min(dpi->width, x + 4);
02902 int reps = (dpi->height - y + 1) / 2;
02903 if (reps > 0) {
02904 this->DrawSmallMapColumn(ptr, pos_x, pos_y, dpi->pitch * 2, reps, x, end_pos, blitter);
02905 }
02906 }
02907
02908 if (y == 0) {
02909 pos_y += increment;
02910 y++;
02911 ptr = blitter->MoveTo(ptr, 0, 1);
02912 } else {
02913 pos_x -= increment;
02914 y--;
02915 ptr = blitter->MoveTo(ptr, 0, -1);
02916 }
02917 ptr = blitter->MoveTo(ptr, 2, 0);
02918 x += 2;
02919 }
02920
02921
02922 if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
02923
02924
02925 if (this->map_type == SMT_LINKSTATS && _game_mode == GM_NORMAL) {
02926 LinkLineDrawer lines;
02927 this->link_details = lines.DrawLinks(this, true);
02928
02929 this->supply_details = DrawStationDots();
02930
02931 if (_legend_linkstats[_smallmap_cargo_count + STAT_TEXT].show_on_map) {
02932 LinkTextDrawer text;
02933 text.DrawLinks(this, false);
02934 }
02935 if (_legend_linkstats[_smallmap_cargo_count + STAT_GRAPH].show_on_map) {
02936 LinkGraphDrawer graph;
02937 graph.DrawLinks(this, false);
02938 }
02939 }
02940
02941
02942 if (this->show_towns) this->DrawTowns(dpi);
02943
02944
02945 this->DrawMapIndicators();
02946
02947 _cur_dpi = old_dpi;
02948 }
02949
02950 bool CheckStationSelected(Point *pt) const
02951 {
02952 return abs(this->cursor.x - pt->x) < 7 && abs(this->cursor.y - pt->y) < 7;
02953 }
02954
02955 bool CheckLinkSelected(Point *pta, Point *ptb) const
02956 {
02957 if (this->cursor.x == -1 && this->cursor.y == -1) return false;
02958 if (CheckStationSelected(pta) || CheckStationSelected(ptb)) return false;
02959 if (pta->x > ptb->x) Swap(pta, ptb);
02960 int minx = min(pta->x, ptb->x);
02961 int maxx = max(pta->x, ptb->x);
02962 int miny = min(pta->y, ptb->y);
02963 int maxy = max(pta->y, ptb->y);
02964 if (!IsInsideMM(cursor.x, minx - 3, maxx + 3) || !IsInsideMM(cursor.y, miny - 3, maxy + 3)) {
02965 return false;
02966 }
02967
02968 if (pta->x == ptb->x || ptb->y == pta->y) {
02969 return true;
02970 } else {
02971 int incliney = (ptb->y - pta->y);
02972 int inclinex = (ptb->x - pta->x);
02973 int diff = (cursor.x - minx) * incliney / inclinex - (cursor.y - miny);
02974 if (incliney < 0) {
02975 diff += maxy - miny;
02976 }
02977 return abs(diff) < 4;
02978 }
02979 }
02980
02984 void RecalcVehiclePositions()
02985 {
02986 this->vehicles_on_map.clear();
02987 const Vehicle *v;
02988 const NWidgetCore *wi = this->GetWidget<NWidgetCore>(SM_WIDGET_MAP);
02989 int scale = this->zoom < 0 ? -this->zoom : 1;
02990
02991 FOR_ALL_VEHICLES(v) {
02992 if (v->type == VEH_EFFECT) continue;
02993 if (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) continue;
02994
02995
02996 Point pos = RemapTile(v->x_pos / (int)TILE_SIZE, v->y_pos / (int)TILE_SIZE);
02997
02998
02999 if (IsInsideMM(pos.x, -2 * scale, wi->current_x + 2 * scale) &&
03000 IsInsideMM(pos.y, -2 * scale, wi->current_y + 2 * scale)) {
03001
03002 this->vehicles_on_map.push_back(VehicleAndPosition(v));
03003 }
03004 }
03005 }
03006
03010 void SetupWidgetData()
03011 {
03012 StringID legend_tooltip;
03013 StringID enable_all_tooltip;
03014 StringID disable_all_tooltip;
03015 int plane;
03016 switch (this->map_type) {
03017 case SMT_INDUSTRY:
03018 legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
03019 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
03020 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
03021 plane = 0;
03022 break;
03023
03024 case SMT_LINKSTATS:
03025 legend_tooltip = STR_SMALLMAP_TOOLTIP_LINK_STATS_SELECTION;
03026 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_LINK_STATS;
03027 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_LINK_STATS;
03028 plane = 0;
03029 break;
03030
03031 case SMT_OWNER:
03032 legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
03033 enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
03034 disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
03035 plane = 0;
03036 break;
03037
03038 default:
03039 legend_tooltip = STR_NULL;
03040 enable_all_tooltip = STR_NULL;
03041 disable_all_tooltip = STR_NULL;
03042 plane = 1;
03043 break;
03044 }
03045
03046 this->GetWidget<NWidgetCore>(SM_WIDGET_LEGEND)->SetDataTip(STR_NULL, legend_tooltip);
03047 this->GetWidget<NWidgetCore>(SM_WIDGET_ENABLE_ALL)->SetDataTip(STR_SMALLMAP_ENABLE_ALL, enable_all_tooltip);
03048 this->GetWidget<NWidgetCore>(SM_WIDGET_DISABLE_ALL)->SetDataTip(STR_SMALLMAP_DISABLE_ALL, disable_all_tooltip);
03049 this->GetWidget<NWidgetStacked>(SM_WIDGET_SELECT_BUTTONS)->SetDisplayedPlane(plane);
03050 }
03051
03052 public:
03053 uint min_number_of_columns;
03054
03055 SmallMapWindow(const WindowDesc *desc, int window_number) : Window(), supply_details(INVALID_STATION), refresh(FORCE_REFRESH_PERIOD)
03056 {
03057 this->cursor.x = -1;
03058 this->cursor.y = -1;
03059 this->InitNested(desc, window_number);
03060 if (_smallmap_cargo_count == 0) {
03061 this->DisableWidget(SM_WIDGET_LINKSTATS);
03062 if (this->map_type == SMT_LINKSTATS) this->map_type = SMT_CONTOUR;
03063 }
03064
03065 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
03066
03067 BuildLandLegend();
03068 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_show_heightmap);
03069
03070 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
03071
03072 this->SetupWidgetData();
03073
03074 this->SetZoomLevel(ZLC_INITIALIZE, NULL);
03075 this->SmallMapCenterOnCurrentPos();
03076 }
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03091 inline uint GetMinLegendWidth() const
03092 {
03093 return WD_FRAMERECT_LEFT + this->min_number_of_columns * this->column_width;
03094 }
03095
03100 inline uint GetNumberColumnsLegend(uint width) const
03101 {
03102 return width / this->column_width;
03103 }
03104
03111 uint GetLegendHeight(uint num_columns) const
03112
03113 {
03114
03115
03116
03117 return WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + this->GetNumberRowsLegend(num_columns) * FONT_HEIGHT_SMALL;
03118 }
03119
03120 virtual void SetStringParameters(int widget) const
03121 {
03122 switch (widget) {
03123 case SM_WIDGET_CAPTION:
03124 SetDParam(0, STR_SMALLMAP_TYPE_CONTOURS + this->map_type);
03125 break;
03126 }
03127 }
03128
03129 virtual void OnInit()
03130 {
03131 uint min_width = 0;
03132 this->min_number_of_columns = INDUSTRY_MIN_NUMBER_OF_COLUMNS;
03133
03134 this->min_number_of_fixed_rows = lengthof(_legend_linkstats) / 2 + 1;
03135 if (AllowMoreHeightlevels()) {
03136 for (uint i = 0; i < lengthof(_legend_table_extended); i++) {
03137 uint height = 0;
03138 uint num_columns = 1;
03139 for (const LegendAndColour *tbl = _legend_table_extended[i]; !tbl->end; ++tbl) {
03140 StringID str;
03141 if (i == SMT_INDUSTRY) {
03142 SetDParam(0, tbl->legend);
03143 SetDParam(1, IndustryPool::MAX_SIZE);
03144 str = STR_SMALLMAP_INDUSTRY;
03145 } else if (i == SMT_LINKSTATS) {
03146 SetDParam(0, tbl->legend);
03147 str = STR_SMALLMAP_LINKSTATS;
03148 } else if (i == SMT_OWNER) {
03149 if (tbl->company != INVALID_COMPANY) {
03150 if (!Company::IsValidID(tbl->company)) {
03151
03152 BuildOwnerLegend();
03153 this->OnInit();
03154 return;
03155 }
03156
03157 SetDParam(0, tbl->company);
03158 str = STR_SMALLMAP_COMPANY;
03159 } else {
03160 str = tbl->legend;
03161 }
03162 } else {
03163 if (tbl->col_break) {
03164 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
03165 height = 0;
03166 num_columns++;
03167 }
03168 height++;
03169 str = tbl->legend;
03170 }
03171 min_width = max(GetStringBoundingBox(str).width, min_width);
03172 }
03173 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
03174 this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
03175 }
03176
03177 } else {
03178 for (uint i = 0; i < lengthof(_legend_table_old); i++) {
03179 uint height = 0;
03180 uint num_columns = 1;
03181 for (const LegendAndColour *tbl = _legend_table_old[i]; !tbl->end; ++tbl) {
03182 StringID str;
03183 if (i == SMT_INDUSTRY) {
03184 SetDParam(0, tbl->legend);
03185 SetDParam(1, IndustryPool::MAX_SIZE);
03186 str = STR_SMALLMAP_INDUSTRY;
03187 } else if (i == SMT_LINKSTATS) {
03188 SetDParam(0, tbl->legend);
03189 str = STR_SMALLMAP_LINKSTATS;
03190 } else if (i == SMT_OWNER) {
03191 if (tbl->company != INVALID_COMPANY) {
03192 if (!Company::IsValidID(tbl->company)) {
03193
03194 BuildOwnerLegend();
03195 this->OnInit();
03196 return;
03197 }
03198
03199 SetDParam(0, tbl->company);
03200 str = STR_SMALLMAP_COMPANY;
03201 } else {
03202 str = tbl->legend;
03203 }
03204 } else {
03205 if (tbl->col_break) {
03206 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
03207 height = 0;
03208 num_columns++;
03209 }
03210 height++;
03211 str = tbl->legend;
03212 }
03213 min_width = max(GetStringBoundingBox(str).width, min_width);
03214 }
03215 this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height);
03216 this->min_number_of_columns = max(this->min_number_of_columns, num_columns);
03217 }
03218 }
03219
03220
03221 this->column_width = min_width + LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
03222 }
03223
03224 virtual void OnPaint()
03225 {
03226 if (this->map_type == SMT_OWNER) {
03227 if (AllowMoreHeightlevels()) {
03228 for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
03229 if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
03230
03231 BuildOwnerLegend();
03232 this->InvalidateData(1);
03233 break;
03234 }
03235 }
03236 } else {
03237 for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
03238 if (tbl->company != INVALID_COMPANY && !Company::IsValidID(tbl->company)) {
03239
03240 BuildOwnerLegend();
03241 this->InvalidateData(1);
03242 break;
03243 }
03244 }
03245 }
03246 }
03247
03248 this->DrawWidgets();
03249 }
03250
03251 virtual void DrawWidget(const Rect &r, int widget) const
03252 {
03253 switch (widget) {
03254 case SM_WIDGET_MAP: {
03255 DrawPixelInfo new_dpi;
03256 if (!FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) return;
03257 this->DrawSmallMap(&new_dpi);
03258 break;
03259 }
03260
03261 case SM_WIDGET_LEGEND: {
03262 uint y_org = r.top + WD_FRAMERECT_TOP;
03263 uint x = r.left + WD_FRAMERECT_LEFT;
03264 if (this->supply_details != INVALID_STATION) {
03265 this->DrawSupplyDetails(x, y_org, r.bottom - WD_FRAMERECT_BOTTOM);
03266 } else if (!this->link_details.Empty()) {
03267 this->DrawLinkDetails(x, y_org, r.right - WD_FRAMERECT_RIGHT, r.bottom - WD_FRAMERECT_BOTTOM);
03268 } else {
03269 uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1);
03270 uint number_of_rows = this->GetNumberRowsLegend(columns);
03271 bool rtl = _current_text_dir == TD_RTL;
03272 uint y_org = r.top + WD_FRAMERECT_TOP;
03273 uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT;
03274 uint y = y_org;
03275 uint i = 0;
03276 uint row_height = FONT_HEIGHT_SMALL;
03277
03278 uint text_left = rtl ? 0 : LEGEND_BLOB_WIDTH + WD_FRAMERECT_LEFT;
03279 uint text_right = this->column_width - 1 - (rtl ? LEGEND_BLOB_WIDTH + WD_FRAMERECT_RIGHT : 0);
03280 uint blob_left = rtl ? this->column_width - 1 - LEGEND_BLOB_WIDTH : 0;
03281 uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH;
03282
03283 StringID string = STR_NULL;
03284 switch (this->map_type) {
03285 case SMT_INDUSTRY:
03286 string = STR_SMALLMAP_INDUSTRY;
03287 break;
03288 case SMT_LINKSTATS:
03289 string = STR_SMALLMAP_LINKSTATS;
03290 break;
03291 case SMT_OWNER:
03292 string = STR_SMALLMAP_COMPANY;
03293 break;
03294 default:
03295 break;
03296 }
03297
03298 if (AllowMoreHeightlevels()) {
03299 for (const LegendAndColour *tbl = _legend_table_extended[this->map_type]; !tbl->end; ++tbl) {
03300 if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
03301
03302
03303 x += rtl ? -(int)this->column_width : this->column_width;
03304 y = y_org;
03305 i = 1;
03306 }
03307
03308 switch(this->map_type) {
03309 case SMT_INDUSTRY:
03310
03311
03312 SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
03313 case SMT_LINKSTATS:
03314 SetDParam(0, tbl->legend);
03315 case SMT_OWNER:
03316 if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
03317 if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
03318 if (!tbl->show_on_map) {
03319
03320
03321 DrawString(x + text_left, x + text_right, y, string, TC_GREY);
03322 } else {
03323 DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
03324 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
03325 }
03326 break;
03327 }
03328 default:
03329 if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
03330
03331
03332 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
03333 DrawString(x + text_left, x + text_right, y, tbl->legend);
03334 break;
03335 }
03336 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour);
03337
03338 y += row_height;
03339 }
03340 } else {
03341 for (const LegendAndColour *tbl = _legend_table_old[this->map_type]; !tbl->end; ++tbl) {
03342 if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) {
03343
03344
03345 x += rtl ? -(int)this->column_width : this->column_width;
03346 y = y_org;
03347 i = 1;
03348 }
03349
03350 switch(this->map_type) {
03351 case SMT_INDUSTRY:
03352
03353
03354 SetDParam(1, Industry::GetIndustryTypeCount(tbl->type));
03355 case SMT_LINKSTATS:
03356 SetDParam(0, tbl->legend);
03357 case SMT_OWNER:
03358 if (this->map_type != SMT_OWNER || tbl->company != INVALID_COMPANY) {
03359 if (this->map_type == SMT_OWNER) SetDParam(0, tbl->company);
03360 if (!tbl->show_on_map) {
03361
03362
03363 DrawString(x + text_left, x + text_right, y, string, TC_GREY);
03364 } else {
03365 DrawString(x + text_left, x + text_right, y, string, TC_BLACK);
03366 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
03367 }
03368 break;
03369 }
03370 default:
03371 if (this->map_type == SMT_CONTOUR) SetDParam(0, tbl->height * TILE_HEIGHT_STEP);
03372
03373
03374 GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK);
03375 DrawString(x + text_left, x + text_right, y, tbl->legend);
03376 break;
03377 }
03378 GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, tbl->colour);
03379
03380 y += row_height;
03381 }
03382 }
03383 }
03384 } break;
03385 }
03386 }
03387
03396 uint GetNumberRowsLegend(uint columns) const
03397 {
03398
03399 uint num_rows_linkstats = CeilDiv(_smallmap_cargo_count, columns - 1);
03400
03401 uint num_rows_others = CeilDiv(max(_smallmap_industry_count,_smallmap_company_count), columns);
03402 return max(this->min_number_of_fixed_rows, max(num_rows_linkstats, num_rows_others));
03403 }
03404
03416 void SelectLegendItem(int click_pos, LegendAndColour *legend, int end_legend_item, int begin_legend_item = 0)
03417 {
03418 if (_ctrl_pressed) {
03419
03420 bool changes = false;
03421 for (int i = begin_legend_item; i != end_legend_item; i++) {
03422 bool new_state = (i == click_pos);
03423 if (legend[i].show_on_map != new_state) {
03424 changes = true;
03425 legend[i].show_on_map = new_state;
03426 }
03427 }
03428 if (!changes) {
03429
03430 for (int i = begin_legend_item; i != end_legend_item; i++) {
03431 legend[i].show_on_map = true;
03432 }
03433 }
03434 } else {
03435 legend[click_pos].show_on_map = !legend[click_pos].show_on_map;
03436 }
03437 }
03438
03443 void SwitchMapType(SmallMapType map_type)
03444 {
03445 this->RaiseWidget(this->map_type + SM_WIDGET_CONTOUR);
03446 this->map_type = map_type;
03447 this->LowerWidget(this->map_type + SM_WIDGET_CONTOUR);
03448
03449 this->SetupWidgetData();
03450
03451 this->SetDirty();
03452 }
03453
03454 virtual void OnClick(Point pt, int widget, int click_count)
03455 {
03456
03457 InvalidateWindowClassesData(WC_INDUSTRY_CARGOES, NUM_INDUSTRYTYPES);
03458
03459 switch (widget) {
03460 case SM_WIDGET_MAP: {
03461
03462
03463
03464
03465
03466
03467
03468
03469 _left_button_clicked = false;
03470
03471 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03472
03473
03474
03475
03476
03477
03478 int offset_inside_sm_x = _cursor.pos.x - this->left + wid->pos_x;
03479 int offset_inside_sm_y = _cursor.pos.y - this->top - wid->pos_y;
03480 int clicked_screen_x = offset_inside_sm_x * TILE_SIZE + pt.x;
03481 int clicked_screen_y = offset_inside_sm_y * TILE_SIZE + pt.y;
03482 Point clicked_tile = TileCoordFromScreenCoord(clicked_screen_x, clicked_screen_y);
03483 clicked_tile.x /= TILE_SIZE;
03484 clicked_tile.y /= TILE_SIZE;
03485 int clicked_tile_height = TileHeightOutsideMap(clicked_tile.x, clicked_tile.y);
03486
03487 DEBUG(map, 9, "clicked: offset_inside_sm (%i,%i), clicked_tile (%i,%i), clicked_screen (%i,%i), clicked_tile_height %i",
03488 offset_inside_sm_x, offset_inside_sm_y, clicked_tile.x, clicked_tile.y, clicked_screen_x, clicked_screen_y, clicked_tile_height);
03489
03490 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
03491 int sub;
03492 pt = this->PixelToWorld(pt.x - wid->pos_x, pt.y - wid->pos_y, &sub);
03493 int offset = this->zoom > 0 ? this->zoom * TILE_SIZE : TILE_SIZE / (-this->zoom);
03494 pt = RemapCoords(this->scroll_x + pt.x + offset - offset * sub / 4,
03495 this->scroll_y + pt.y + sub * offset / 4, 0);
03496
03497 w->viewport->follow_vehicle = INVALID_VEHICLE;
03498 w->viewport->dest_scrollpos_x = pt.x - (w->viewport->virtual_width >> 1);
03499 w->viewport->dest_scrollpos_y = pt.y - ((clicked_tile_height * TILE_HEIGHT) + (w->viewport->virtual_height >> 1));
03500
03501 DEBUG(map, 9, "OnClick: scroll_x, scroll_y = (%i,%i), pt = (%i,%i), dest_scrollpos = (%i,%i), cursor = (%i,%i), left/top = (%i, %i), virtual = (%i,%i)",
03502 this->scroll_x, this->scroll_y, pt.x, pt.y,
03503 w->viewport->dest_scrollpos_x, w->viewport->dest_scrollpos_y,
03504 _cursor.pos.x, _cursor.pos.y, this->left, this->top,
03505 w->viewport->virtual_width, w->viewport->virtual_height);
03506
03507 this->SetDirty();
03508 break;
03509 }
03510
03511 case SM_WIDGET_ZOOM_IN:
03512 case SM_WIDGET_ZOOM_OUT: {
03513 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03514 Point pt = {wid->current_x / 2, wid->current_y / 2};
03515 this->SetZoomLevel((widget == SM_WIDGET_ZOOM_IN) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
03516 SndPlayFx(SND_15_BEEP);
03517 break;
03518 }
03519
03520 case SM_WIDGET_CONTOUR:
03521 case SM_WIDGET_VEHICLES:
03522 case SM_WIDGET_INDUSTRIES:
03523 case SM_WIDGET_LINKSTATS:
03524 case SM_WIDGET_ROUTES:
03525 case SM_WIDGET_VEGETATION:
03526 case SM_WIDGET_OWNERS:
03527 this->SwitchMapType((SmallMapType)(widget - SM_WIDGET_CONTOUR));
03528 SndPlayFx(SND_15_BEEP);
03529 break;
03530
03531 case SM_WIDGET_CENTERMAP:
03532 this->SmallMapCenterOnCurrentPos();
03533 this->HandleButtonClick(SM_WIDGET_CENTERMAP);
03534 SndPlayFx(SND_15_BEEP);
03535 break;
03536
03537 case SM_WIDGET_TOGGLETOWNNAME:
03538 this->show_towns = !this->show_towns;
03539 this->SetWidgetLoweredState(SM_WIDGET_TOGGLETOWNNAME, this->show_towns);
03540
03541 this->SetDirty();
03542 SndPlayFx(SND_15_BEEP);
03543 break;
03544
03545 case SM_WIDGET_LEGEND:
03546
03547 if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_LINKSTATS || this->map_type == SMT_OWNER) {
03548
03549 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_LEGEND);
03550 uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL;
03551 uint columns = this->GetNumberColumnsLegend(wi->current_x);
03552 uint number_of_rows = this->GetNumberRowsLegend(columns);
03553 if (line >= number_of_rows) break;
03554
03555 bool rtl = _current_text_dir == TD_RTL;
03556 int x = pt.x - wi->pos_x;
03557 if (rtl) x = wi->current_x - x;
03558 uint column = (x - WD_FRAMERECT_LEFT) / this->column_width;
03559 int click_pos = (column * number_of_rows) + line;
03560
03561
03562 if (this->map_type == SMT_INDUSTRY) {
03563 if (click_pos < _smallmap_industry_count) {
03564 this->SelectLegendItem(click_pos, _legend_from_industries, _smallmap_industry_count);
03565 }
03566
03567 } else if (this->map_type == SMT_LINKSTATS) {
03568 if (click_pos < _smallmap_cargo_count) {
03569 this->SelectLegendItem(click_pos, _legend_linkstats, _smallmap_cargo_count);
03570 } else {
03571 uint stats_column = CeilDiv(_smallmap_cargo_count, number_of_rows);
03572 if (column == stats_column && line < NUM_STATS) {
03573 this->SelectLegendItem(_smallmap_cargo_count + line, _legend_linkstats,
03574 _smallmap_cargo_count + NUM_STATS, _smallmap_cargo_count);
03575 }
03576 }
03577
03578 } else if (this->map_type == SMT_OWNER) {
03579 if (click_pos < _smallmap_company_count) {
03580 this->SelectLegendItem(click_pos, _legend_land_owners, _smallmap_company_count, NUM_NO_COMPANY_ENTRIES);
03581 }
03582 }
03583 this->SetDirty();
03584 }
03585 break;
03586
03587 case SM_WIDGET_ENABLE_ALL:
03588 case SM_WIDGET_DISABLE_ALL: {
03589 LegendAndColour *tbl = NULL;
03590 switch (this->map_type) {
03591 case SMT_INDUSTRY:
03592 tbl = _legend_from_industries;
03593 break;
03594 case SMT_OWNER:
03595 tbl = &(_legend_land_owners[NUM_NO_COMPANY_ENTRIES]);
03596 break;
03597 case SMT_LINKSTATS:
03598 tbl = _legend_linkstats;
03599 break;
03600 default:
03601 NOT_REACHED();
03602 }
03603
03604 for (;!tbl->end; ++tbl) tbl->show_on_map = (widget == SM_WIDGET_ENABLE_ALL);
03605 this->SetDirty();
03606 break;
03607 }
03608
03609 case SM_WIDGET_SHOW_HEIGHT:
03610 _smallmap_show_heightmap = !_smallmap_show_heightmap;
03611 this->SetWidgetLoweredState(SM_WIDGET_SHOW_HEIGHT, _smallmap_show_heightmap);
03612 this->SetDirty();
03613 break;
03614 }
03615 }
03616
03617 virtual void OnMouseOver(Point pt, int widget)
03618 {
03619 static Point invalid = {-1, -1};
03620 if (widget == SM_WIDGET_MAP) {
03621 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03622 pt.x -= wid->pos_x;
03623 pt.y -= wid->pos_y;
03624 if (pt.x != cursor.x || pt.y != cursor.y) {
03625 this->refresh = 1;
03626 cursor = pt;
03627 }
03628 } else {
03629 cursor = invalid;
03630 }
03631 }
03632
03640 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
03641 {
03642 if (!gui_scope) return;
03643 switch (data) {
03644 case 1:
03645
03646 this->ReInit();
03647 break;
03648
03649 case 0: {
03650 extern uint64 _displayed_industries;
03651 if (this->map_type != SMT_INDUSTRY) this->SwitchMapType(SMT_INDUSTRY);
03652
03653 for (int i = 0; i != _smallmap_industry_count; i++) {
03654 _legend_from_industries[i].show_on_map = HasBit(_displayed_industries, _legend_from_industries[i].type);
03655 }
03656 break;
03657 }
03658
03659 default: NOT_REACHED();
03660 }
03661 this->SetDirty();
03662 }
03663
03664 virtual bool OnRightClick(Point pt, int widget)
03665 {
03666 if (widget != SM_WIDGET_MAP || _scrolling_viewport) return false;
03667
03668 _scrolling_viewport = true;
03669 return true;
03670 }
03671
03672 virtual void OnMouseWheel(int wheel)
03673 {
03674 if (_settings_client.gui.scrollwheel_scrolling == 0) {
03675 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03676 int cursor_x = _cursor.pos.x - this->left - wid->pos_x;
03677 int cursor_y = _cursor.pos.y - this->top - wid->pos_y;
03678 if (IsInsideMM(cursor_x, 0, wid->current_x) && IsInsideMM(cursor_y, 0, wid->current_y)) {
03679 Point pt = {cursor_x, cursor_y};
03680 this->SetZoomLevel((wheel < 0) ? ZLC_ZOOM_IN : ZLC_ZOOM_OUT, &pt);
03681 }
03682 }
03683 }
03684
03685 virtual void OnTick()
03686 {
03687
03688 if (--this->refresh != 0) return;
03689
03690 this->RecalcVehiclePositions();
03691
03692 this->refresh = FORCE_REFRESH_PERIOD;
03693 this->SetDirty();
03694 }
03695
03703 void SetNewScroll(int sx, int sy, int sub)
03704 {
03705 const NWidgetBase *wi = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03706 Point hv = InverseRemapCoords(wi->current_x * TILE_SIZE / 2, wi->current_y * TILE_SIZE / 2);
03707 if (this->zoom > 0) {
03708 hv.x *= this->zoom;
03709 hv.y *= this->zoom;
03710 } else {
03711 hv.x /= (-this->zoom);
03712 hv.y /= (-this->zoom);
03713 }
03714
03715 if (sx < -hv.x) {
03716 sx = -hv.x;
03717 sub = 0;
03718 }
03719 if (sx > (int)(MapMaxX() * TILE_SIZE) - hv.x) {
03720 sx = MapMaxX() * TILE_SIZE - hv.x;
03721 sub = 0;
03722 }
03723 if (sy < -hv.y) {
03724 sy = -hv.y;
03725 sub = 0;
03726 }
03727 if (sy > (int)(MapMaxY() * TILE_SIZE) - hv.y) {
03728 sy = MapMaxY() * TILE_SIZE - hv.y;
03729 sub = 0;
03730 }
03731
03732 this->scroll_x = sx;
03733 this->scroll_y = sy;
03734 this->subscroll = sub;
03735 }
03736
03737 virtual void OnScroll(Point delta)
03738 {
03739 _cursor.fix_at = true;
03740
03741
03742 int sub;
03743 Point pt = this->PixelToWorld(delta.x, delta.y, &sub);
03744 this->SetNewScroll(this->scroll_x + pt.x, this->scroll_y + pt.y, sub);
03745
03746 this->SetDirty();
03747 }
03748
03749 void SmallMapCenterOnCurrentPos()
03750 {
03751 const ViewPort *vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
03752 Point pt = InverseRemapCoords(vp->virtual_left + vp->virtual_width / 2, vp->virtual_top + vp->virtual_height / 2);
03753
03754 int sub;
03755 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(SM_WIDGET_MAP);
03756 Point sxy = this->ComputeScroll(pt.x, pt.y, max(0, (int)wid->current_x / 2 - 2), wid->current_y / 2, &sub);
03757 this->SetNewScroll(sxy.x, sxy.y, sub);
03758 this->SetDirty();
03759 }
03760
03761 uint ColumnWidth() const {return column_width;}
03762 };
03763
03764 SmallMapWindow::SmallMapType SmallMapWindow::map_type = SMT_CONTOUR;
03765 bool SmallMapWindow::show_towns = true;
03766
03775 class NWidgetSmallmapDisplay : public NWidgetContainer {
03776 const SmallMapWindow *smallmap_window;
03777 public:
03778 NWidgetSmallmapDisplay() : NWidgetContainer(NWID_VERTICAL)
03779 {
03780 this->smallmap_window = NULL;
03781 }
03782
03783 virtual void SetupSmallestSize(Window *w, bool init_array)
03784 {
03785 NWidgetBase *display = this->head;
03786 NWidgetBase *bar = display->next;
03787
03788 display->SetupSmallestSize(w, init_array);
03789 bar->SetupSmallestSize(w, init_array);
03790
03791 this->smallmap_window = dynamic_cast<SmallMapWindow *>(w);
03792 this->smallest_x = max(display->smallest_x, bar->smallest_x + smallmap_window->GetMinLegendWidth());
03793 this->smallest_y = display->smallest_y + max(bar->smallest_y, smallmap_window->GetLegendHeight(smallmap_window->min_number_of_columns));
03794
03795 this->fill_x = max(display->fill_x, bar->fill_x);
03796 this->fill_y = (display->fill_y == 0 && bar->fill_y == 0) ? 0 : min(display->fill_y, bar->fill_y);
03797 this->resize_x = max(display->resize_x, bar->resize_x);
03798 this->resize_y = min(display->resize_y, bar->resize_y);
03799 }
03800
03801 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
03802 {
03803 this->pos_x = x;
03804 this->pos_y = y;
03805 this->current_x = given_width;
03806 this->current_y = given_height;
03807
03808 NWidgetBase *display = this->head;
03809 NWidgetBase *bar = display->next;
03810
03811 if (sizing == ST_SMALLEST) {
03812 this->smallest_x = given_width;
03813 this->smallest_y = given_height;
03814
03815 display->AssignSizePosition(ST_SMALLEST, x, y, display->smallest_x, display->smallest_y, rtl);
03816 bar->AssignSizePosition(ST_SMALLEST, x, y + display->smallest_y, bar->smallest_x, bar->smallest_y, rtl);
03817 }
03818
03819
03820 uint bar_height = max(bar->smallest_y, this->smallmap_window->GetLegendHeight(given_width - bar->smallest_x));
03821 uint display_height = given_height - bar_height;
03822 display->AssignSizePosition(ST_RESIZE, x, y, given_width, display_height, rtl);
03823 bar->AssignSizePosition(ST_RESIZE, x, y + display_height, given_width, bar_height, rtl);
03824 }
03825
03826 virtual NWidgetCore *GetWidgetFromPos(int x, int y)
03827 {
03828 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
03829 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
03830 NWidgetCore *widget = child_wid->GetWidgetFromPos(x, y);
03831 if (widget != NULL) return widget;
03832 }
03833 return NULL;
03834 }
03835
03836 virtual void Draw(const Window *w)
03837 {
03838 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) child_wid->Draw(w);
03839 }
03840 };
03841
03843 static const NWidgetPart _nested_smallmap_display[] = {
03844 NWidget(WWT_PANEL, COLOUR_BROWN, SM_WIDGET_MAP_BORDER),
03845 NWidget(WWT_INSET, COLOUR_BROWN, SM_WIDGET_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(),
03846 EndContainer(),
03847 };
03848
03850 static const NWidgetPart _nested_smallmap_bar[] = {
03851 NWidget(WWT_PANEL, COLOUR_BROWN),
03852 NWidget(NWID_HORIZONTAL),
03853 NWidget(WWT_EMPTY, INVALID_COLOUR, SM_WIDGET_LEGEND), SetResize(1, 1),
03854 NWidget(NWID_VERTICAL),
03855
03856 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
03857 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_IN),
03858 SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), SetFill(1, 1),
03859 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_CENTERMAP),
03860 SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1),
03861 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_BLANK), SetMinimalSize(22, 22),
03862 SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1),
03863 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_CONTOUR),
03864 SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1),
03865 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEHICLES),
03866 SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1),
03867 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_INDUSTRIES),
03868 SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1),
03869 EndContainer(),
03870
03871 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
03872 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, SM_WIDGET_ZOOM_OUT),
03873 SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), SetFill(1, 1),
03874 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_TOGGLETOWNNAME),
03875 SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), SetFill(1, 1),
03876 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_LINKSTATS),
03877 SetDataTip(SPR_IMG_GRAPHS, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), SetFill(1, 1),
03878 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_ROUTES),
03879 SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), SetFill(1, 1),
03880 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_VEGETATION),
03881 SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), SetFill(1, 1),
03882 NWidget(WWT_IMGBTN, COLOUR_BROWN, SM_WIDGET_OWNERS),
03883 SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), SetFill(1, 1),
03884 EndContainer(),
03885 NWidget(NWID_SPACER), SetResize(0, 1),
03886 EndContainer(),
03887 EndContainer(),
03888 EndContainer(),
03889 };
03890
03891 static NWidgetBase *SmallMapDisplay(int *biggest_index)
03892 {
03893 NWidgetContainer *map_display = new NWidgetSmallmapDisplay;
03894
03895 MakeNWidgets(_nested_smallmap_display, lengthof(_nested_smallmap_display), biggest_index, map_display);
03896 MakeNWidgets(_nested_smallmap_bar, lengthof(_nested_smallmap_bar), biggest_index, map_display);
03897 return map_display;
03898 }
03899
03900
03901 static const NWidgetPart _nested_smallmap_widgets[] = {
03902 NWidget(NWID_HORIZONTAL),
03903 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
03904 NWidget(WWT_CAPTION, COLOUR_BROWN, SM_WIDGET_CAPTION), SetDataTip(STR_SMALLMAP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
03905 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
03906 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
03907 EndContainer(),
03908 NWidgetFunction(SmallMapDisplay),
03909
03910 NWidget(NWID_HORIZONTAL),
03911 NWidget(WWT_PANEL, COLOUR_BROWN),
03912 NWidget(NWID_HORIZONTAL),
03913 NWidget(NWID_SELECTION, INVALID_COLOUR, SM_WIDGET_SELECT_BUTTONS),
03914 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
03915 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, SM_WIDGET_ENABLE_ALL), SetDataTip(STR_SMALLMAP_ENABLE_ALL, STR_NULL),
03916 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, SM_WIDGET_DISABLE_ALL), SetDataTip(STR_SMALLMAP_DISABLE_ALL, STR_NULL),
03917 NWidget(WWT_TEXTBTN, COLOUR_BROWN, SM_WIDGET_SHOW_HEIGHT), SetDataTip(STR_SMALLMAP_SHOW_HEIGHT, STR_SMALLMAP_TOOLTIP_SHOW_HEIGHT),
03918 EndContainer(),
03919 NWidget(NWID_SPACER), SetFill(1, 1),
03920 EndContainer(),
03921 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
03922 EndContainer(),
03923 EndContainer(),
03924 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
03925 EndContainer(),
03926 };
03927
03928 static const WindowDesc _smallmap_desc(
03929 WDP_AUTO, 484, 314,
03930 WC_SMALLMAP, WC_NONE,
03931 WDF_UNCLICK_BUTTONS,
03932 _nested_smallmap_widgets, lengthof(_nested_smallmap_widgets)
03933 );
03934
03938 void ShowSmallMap()
03939 {
03940 AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
03941 }
03942
03951 bool ScrollMainWindowTo(int x, int y, int z, bool instant)
03952 {
03953 bool res = ScrollWindowTo(x, y, z, FindWindowById(WC_MAIN_WINDOW, 0), instant);
03954
03955
03956
03957
03958
03959 if (res) return res;
03960
03961 SmallMapWindow *w = dynamic_cast<SmallMapWindow*>(FindWindowById(WC_SMALLMAP, 0));
03962 if (w != NULL) w->SmallMapCenterOnCurrentPos();
03963
03964 return res;
03965 }