diff options
Diffstat (limited to 'src/smallmap_gui.cpp')
-rw-r--r-- | src/smallmap_gui.cpp | 238 |
1 files changed, 218 insertions, 20 deletions
diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 4a573f3a9..fa1c6f6c7 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -26,6 +26,10 @@ #include "sound_func.h" #include "window_func.h" #include "company_base.h" +#include "station_base.h" +#include "company_func.h" +#include "cargotype.h" +#include "core/smallmap_type.hpp" #include "widgets/smallmap_widget.h" @@ -33,6 +37,7 @@ static int _smallmap_industry_count; ///< Number of used industries static int _smallmap_company_count; ///< Number of entries in the owner legend. +static int _smallmap_cargo_count; ///< Number of entries in the cargo legend. static const int NUM_NO_COMPANY_ENTRIES = 4; ///< Number of entries in the owner legend that are not companies. @@ -44,25 +49,25 @@ static const uint8 PC_TREES = 0x57; ///< Green palette colour for tree static const uint8 PC_WATER = 0xCA; ///< Dark blue palette colour for water. /** Macro for ordinary entry of LegendAndColour */ -#define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false} +#define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, INVALID_CARGO, true, false, false} /** Macro for a height legend entry with configurable colour. */ -#define MC(height) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, true, false, false} +#define MC(height) {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, height, INVALID_COMPANY, INVALID_CARGO, true, false, false} /** Macro for non-company owned property entry of LegendAndColour */ -#define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false} +#define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, INVALID_CARGO, true, false, false} /** Macro used for forcing a rebuild of the owner legend the first time it is used. */ -#define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false} +#define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, INVALID_CARGO, true, true, false} /** Macro for end of list marker in arrays of LegendAndColour */ -#define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false} +#define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, INVALID_CARGO, true, true, false} /** * Macro for break marker in arrays of LegendAndColour. * It will have valid data, though */ -#define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true} +#define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, INVALID_CARGO, true, false, true} /** Structure for holding relevant data for legends in small map */ struct LegendAndColour { @@ -71,6 +76,7 @@ struct LegendAndColour { IndustryType type; ///< Type of industry. Only valid for industry entries. uint8 height; ///< Height in tiles. Only valid for height legend entries. CompanyID company; ///< Company to display. Only valid for company entries of the owner legend. + CargoID cid; ///< Cargo type to display. Only valid for entries of the cargo legend. bool show_on_map; ///< For filtering industries, if \c true, industry is shown on the map in colour. bool end; ///< This is the end of the list. bool col_break; ///< Perform a column break and go further at the next column. @@ -156,6 +162,10 @@ static LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIE static LegendAndColour _legend_from_industries[NUM_INDUSTRYTYPES + 1]; /** For connecting industry type to position in industries list(small map legend) */ static uint _industry_to_list_pos[NUM_INDUSTRYTYPES]; +/** Legend text for the cargo types in the route link legend. */ +static LegendAndColour _legend_from_cargoes[NUM_CARGO + 1]; +/** For connecting cargo type to position in route link legend. */ +static uint _cargotype_to_list_pos[NUM_CARGO]; /** Show heightmap in industry and owner mode of smallmap window. */ static bool _smallmap_show_heightmap = false; /** Highlight a specific industry type */ @@ -196,10 +206,38 @@ void BuildIndustriesLegend() _smallmap_industry_count = j; } +/** Fills the array for the route link legend. */ +void BuildCargoTypesLegend() +{ + uint j = 0; + + /* Add all standard cargo types. */ + const CargoSpec *cs; + FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { + _legend_from_cargoes[j].legend = cs->name; + _legend_from_cargoes[j].colour = cs->legend_colour; + _legend_from_cargoes[j].cid = cs->Index(); + _legend_from_cargoes[j].show_on_map = true; + _legend_from_cargoes[j].col_break = false; + _legend_from_cargoes[j].end = false; + + /* Store widget number for this cargo type. */ + _cargotype_to_list_pos[cs->Index()] = j; + j++; + } + + /* Terminate list. */ + _legend_from_cargoes[j].end = true; + + /* Store number of enabled cargoes. */ + _smallmap_cargo_count = j; +} + static const LegendAndColour * const _legend_table[] = { _legend_land_contours, _legend_vehicles, _legend_from_industries, + _legend_from_cargoes, _legend_routes, _legend_vegetation, _legend_land_owners, @@ -242,6 +280,21 @@ static const uint32 _green_map_heights[] = { }; assert_compile(lengthof(_green_map_heights) == MAX_TILE_HEIGHT + 1); +/** + * Colour Coding for Stuck Counter + */ +static const uint32 _stuck_counter_colours[] = { + MKCOLOUR(0xD0D0D0D0), + MKCOLOUR(0xCECECECE), + MKCOLOUR(0xBFBFBFBF), + MKCOLOUR(0xBDBDBDBD), + MKCOLOUR(0xBABABABA), + MKCOLOUR(0xB8B8B8B8), + MKCOLOUR(0xB6B6B6B6), + MKCOLOUR(0xB4B4B4B4), +}; +assert_compile(lengthof(_stuck_counter_colours) == 8); + /** Height map colours for the dark green colour scheme, ordered by height. */ static const uint32 _dark_green_map_heights[] = { MKCOLOUR_XXXX(0x60), @@ -464,9 +517,10 @@ static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t) * * @param tile The tile of which we would like to get the colour. * @param t Effective tile type of the tile (see #GetEffectiveTileType). + * @param show_height Whether to show the height of plain tiles. * @return The colour of tile in the small map in mode "Routes" */ -static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t) +static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t, bool show_height = false) { if (t == MP_STATION) { switch (GetStationType(tile)) { @@ -478,18 +532,14 @@ static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t) default: return MKCOLOUR_FFFF; } } else if (t == MP_RAILWAY) { - AndOr andor = { - MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour), - _smallmap_contours_andor[t].mand - }; - - const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour]; - return ApplyMask(cs->default_colour, &andor); + byte c = GetStuckCounter(tile); + if (c==0) return 0; + return _stuck_counter_colours[c/32]; } /* Ground colour */ const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour]; - return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]); + return ApplyMask(show_height ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_contours_andor[t]); } @@ -576,6 +626,7 @@ class SmallMapWindow : public Window { SMT_CONTOUR, SMT_VEHICLES, SMT_INDUSTRY, + SMT_ROUTE_LINKS, SMT_ROUTES, SMT_VEGETATION, SMT_OWNER, @@ -774,6 +825,9 @@ class SmallMapWindow : public Window { case SMT_INDUSTRY: return GetSmallMapIndustriesPixels(tile, et); + case SMT_ROUTE_LINKS: + return GetSmallMapRoutesPixels(tile, et, _smallmap_show_heightmap); + case SMT_ROUTES: return GetSmallMapRoutesPixels(tile, et); @@ -901,6 +955,92 @@ class SmallMapWindow : public Window { } /** + * Adds the route links to the smallmap. + */ + void DrawRouteLinks() const + { + /* Iterate all shown cargo types. */ + for (int i = 0; i < _smallmap_cargo_count; i++) { + if (_legend_from_cargoes[i].show_on_map) { + CargoID cid = _legend_from_cargoes[i].cid; + + /* Iterate all stations. */ + const Station *st; + FOR_ALL_STATIONS(st) { + Point src_pt = this->RemapTile(TileX(st->xy), TileY(st->xy)); + src_pt.x -= this->subscroll; + + /* Collect waiting cargo per destination station. */ + std::map<StationID, uint> links; + for (RouteLinkList::const_iterator l = st->goods[cid].routes.begin(); l != st->goods[cid].routes.end(); ++l) { + if (IsInteractiveCompany((*l)->GetOwner())) links[(*l)->GetDestination()] += st->goods[cid].cargo.CountForNextHop((*l)->GetOriginOrderId()); + } + + /* Add cargo count on back-links. */ + for (std::map<StationID, uint>::iterator itr = links.begin(); itr != links.end(); ++itr) { + /* Get destination location. */ + const Station *dest = Station::Get(itr->first); + Point dest_pt = this->RemapTile(TileX(dest->xy), TileY(dest->xy)); + dest_pt.x -= this->subscroll; + + /* Get total count including back-links. */ + uint count = itr->second; + for (RouteLinkList::const_iterator j = dest->goods[cid].routes.begin(); j != dest->goods[cid].routes.end(); ++j) { + if ((*j)->GetDestination() == st->index && IsInteractiveCompany((*j)->GetOwner())) count += dest->goods[cid].cargo.CountForNextHop((*j)->GetOriginOrderId()); + } + + /* Calculate line size from waiting cargo. */ + int size = 1; + if (count >= 400) size++; + if (count >= 800) size++; + if (count >= 1600) size++; + if (count >= 3200) size++; + + /* Draw black border and cargo coloured line. */ + GfxDrawLine(src_pt.x, src_pt.y, dest_pt.x, dest_pt.y, PC_BLACK, size + 2); + GfxDrawLine(src_pt.x, src_pt.y, dest_pt.x, dest_pt.y, _legend_from_cargoes[i].colour, size); + } + } + } + } + + /* Draw station rect. */ + const Station *st; + FOR_ALL_STATIONS(st) { + /* Count total cargo and check for links for all shown cargo types. */ + uint total = 0; + bool show = false; + for (CargoID cid = 0; cid < NUM_CARGO; cid++) { + if (_legend_from_cargoes[_cargotype_to_list_pos[cid]].show_on_map) { + total += st->goods[cid].cargo.Count(); + show |= !st->goods[cid].routes.empty(); + } + } + + if (!show) continue; + + /* Get rect size from total cargo count. */ + int d = 1; + if (total >= 200) d++; + if (total >= 400) d++; + if (total >= 800) d++; + if (total >= 1600) d++; + if (total >= 3200) d++; + if (total >= 6400) d++; + + /* Get top-left corner of the rect. */ + Point dest_pt = this->RemapTile(TileX(st->xy), TileY(st->xy)); + dest_pt.x -= this->subscroll + d/2; + dest_pt.y -= d/2; + + /* Draw black border and company-colour inset. */ + byte colour = _colour_gradient[Company::IsValidID(st->owner) ? Company::Get(st->owner)->colour : (byte)COLOUR_GREY][6]; + GfxFillRect(dest_pt.x - 1, dest_pt.y - 1, dest_pt.x + d + 1, dest_pt.y + d + 1, PC_BLACK); // Draw black frame + GfxFillRect(dest_pt.x, dest_pt.y, dest_pt.x + d, dest_pt.y + d, colour); // Draw colour insert + } + } + + /** * Draws vertical part of map indicator * @param x X coord of left/right border of main viewport * @param y Y coord of top border of main viewport @@ -1007,6 +1147,9 @@ class SmallMapWindow : public Window { /* Draw vehicles */ if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter); + /* Draw route links. */ + if (this->map_type == SMT_ROUTE_LINKS) this->DrawRouteLinks(); + /* Draw town names */ if (this->show_towns) this->DrawTowns(dpi); @@ -1040,6 +1183,13 @@ class SmallMapWindow : public Window { plane = 0; break; + case SMT_ROUTE_LINKS: + legend_tooltip = STR_SMALLMAP_TOOLTIP_ROUTELINK_SELECTION; + enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_ROUTELINKS; + disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_ROUTELINKS; + plane = 0; + break; + default: legend_tooltip = STR_NULL; enable_all_tooltip = STR_NULL; @@ -1140,6 +1290,9 @@ public: } else { str = tbl->legend; } + } else if (i == SMT_ROUTE_LINKS) { + SetDParam(0, tbl->legend); + str = STR_SMALLMAP_CARGO; } else { if (tbl->col_break) { this->min_number_of_fixed_rows = max(this->min_number_of_fixed_rows, height); @@ -1187,7 +1340,7 @@ public: case WID_SM_LEGEND: { uint columns = this->GetNumberColumnsLegend(r.right - r.left + 1); - uint number_of_rows = max((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) ? CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), columns) : 0, this->min_number_of_fixed_rows); + uint number_of_rows = max((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_ROUTE_LINKS) ? CeilDiv(max(_smallmap_company_count, max(_smallmap_industry_count, _smallmap_cargo_count)), columns) : 0, this->min_number_of_fixed_rows); bool rtl = _current_text_dir == TD_RTL; uint y_org = r.top + WD_FRAMERECT_TOP; uint x = rtl ? r.right - this->column_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT; @@ -1201,7 +1354,7 @@ public: uint blob_right = rtl ? this->column_width - 1 : LEGEND_BLOB_WIDTH; for (const LegendAndColour *tbl = _legend_table[this->map_type]; !tbl->end; ++tbl) { - if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) && i++ >= number_of_rows)) { + if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_ROUTE_LINKS) && i++ >= number_of_rows)) { /* Column break needed, continue at top, COLUMN_WIDTH pixels * (one "row") to the right. */ x += rtl ? -(int)this->column_width : this->column_width; @@ -1227,6 +1380,16 @@ public: DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_INDUSTRY, TC_BLACK); GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour } + } else if (this->map_type == SMT_ROUTE_LINKS) { + /* Cargo name needs formatting for tiny font. */ + SetDParam(0, tbl->legend); + if (!tbl->show_on_map) { + /* Draw only the string and not the border of the legend colour. */ + DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_CARGO, TC_GREY); + } else { + DrawString(x + text_left, x + text_right, y, STR_SMALLMAP_CARGO, TC_BLACK); + GfxFillRect(x + blob_left, y + 1, x + blob_right, y + row_height - 1, PC_BLACK); // Outer border of the legend colour + } } else if (this->map_type == SMT_OWNER && tbl->company != INVALID_COMPANY) { SetDParam(0, tbl->company); if (!tbl->show_on_map) { @@ -1277,7 +1440,7 @@ public: const NWidgetBase *wi = this->GetWidget<NWidgetBase>(WID_SM_LEGEND); uint line = (pt.y - wi->pos_y - WD_FRAMERECT_TOP) / FONT_HEIGHT_SMALL; uint columns = this->GetNumberColumnsLegend(wi->current_x); - uint number_of_rows = max(CeilDiv(max(_smallmap_company_count, _smallmap_industry_count), columns), this->min_number_of_fixed_rows); + uint number_of_rows = max(CeilDiv(max(_smallmap_company_count, max(_smallmap_industry_count, _smallmap_cargo_count)), columns), this->min_number_of_fixed_rows); if (line >= number_of_rows) return -1; bool rtl = _current_text_dir == TD_RTL; @@ -1349,6 +1512,7 @@ public: case WID_SM_CONTOUR: // Show land contours case WID_SM_VEHICLES: // Show vehicles case WID_SM_INDUSTRIES: // Show industries + case WID_SM_ROUTE_LINKS:// Show route links case WID_SM_ROUTES: // Show transport routes case WID_SM_VEGETATION: // Show vegetation case WID_SM_OWNERS: // Show land owners @@ -1371,7 +1535,7 @@ public: break; case WID_SM_LEGEND: // Legend - if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER) { + if (this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_ROUTE_LINKS) { /* If industry type small map*/ if (this->map_type == SMT_INDUSTRY) { /* If click on industries label, find right industry type and enable/disable it. */ @@ -1422,6 +1586,30 @@ public: _legend_land_owners[company_pos].show_on_map = !_legend_land_owners[company_pos].show_on_map; } } + } else if (this->map_type == SMT_ROUTE_LINKS) { + /* If click on cargo label, find right cargo type and enable/disable it. */ + int cargo_pos = GetPositionOnLegend(pt); + if (cargo_pos < _smallmap_cargo_count) { + if (_ctrl_pressed) { + /* Disable all, except the clicked one */ + bool changes = false; + for (int i = 0; i != _smallmap_cargo_count; i++) { + bool new_state = i == cargo_pos; + if (_legend_from_cargoes[i].show_on_map != new_state) { + changes = true; + _legend_from_cargoes[i].show_on_map = new_state; + } + } + if (!changes) { + /* Nothing changed? Then show all (again). */ + for (int i = 0; i != _smallmap_cargo_count; i++) { + _legend_from_cargoes[i].show_on_map = true; + } + } + } else { + _legend_from_cargoes[cargo_pos].show_on_map = !_legend_from_cargoes[cargo_pos].show_on_map; + } + } } this->SetDirty(); } @@ -1436,6 +1624,10 @@ public: for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) { _legend_land_owners[i].show_on_map = true; } + } else if (this->map_type == SMT_ROUTE_LINKS) { + for (int i = 0; i != _smallmap_cargo_count; i++) { + _legend_from_cargoes[i].show_on_map = true; + } } this->SetDirty(); break; @@ -1445,10 +1637,14 @@ public: for (int i = 0; i != _smallmap_industry_count; i++) { _legend_from_industries[i].show_on_map = false; } - } else { + } else if (this->map_type == SMT_OWNER) { for (int i = NUM_NO_COMPANY_ENTRIES; i != _smallmap_company_count; i++) { _legend_land_owners[i].show_on_map = false; } + } else if (this->map_type == SMT_ROUTE_LINKS) { + for (int i = 0; i != _smallmap_cargo_count; i++) { + _legend_from_cargoes[i].show_on_map = false; + } } this->SetDirty(); break; @@ -1686,6 +1882,8 @@ static const NWidgetPart _nested_smallmap_bar[] = { SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), SetFill(1, 1), NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_INDUSTRIES), SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), SetFill(1, 1), + NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_ROUTE_LINKS), + SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_ROUTE_LINKS_ON_MAP), SetFill(1, 1), EndContainer(), /* Bottom button row. */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), |