Merge pull request #293 from VacuumBreather/station_cargo_history
Add station cargo history
This commit is contained in:
@@ -90,6 +90,15 @@ struct CargoSpec {
|
||||
return this - CargoSpec::array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine CargoTypes bit of this cargospec
|
||||
* @return CargoTypes bit
|
||||
*/
|
||||
inline CargoTypes CargoTypesBit() const
|
||||
{
|
||||
return static_cast<CargoTypes>(1) << this->Index();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for validity of this cargospec
|
||||
* @return is this cargospec valid?
|
||||
|
@@ -184,6 +184,7 @@ extern void CompaniesMonthlyLoop();
|
||||
extern void EnginesMonthlyLoop();
|
||||
extern void TownsMonthlyLoop();
|
||||
extern void IndustryMonthlyLoop();
|
||||
extern void StationDailyLoop();
|
||||
extern void StationMonthlyLoop();
|
||||
extern void SubsidyMonthlyLoop();
|
||||
|
||||
@@ -276,6 +277,7 @@ static void OnNewDay()
|
||||
|
||||
DisasterDailyLoop();
|
||||
IndustryDailyLoop();
|
||||
StationDailyLoop();
|
||||
|
||||
if (!_settings_time.time_in_minutes || _settings_client.gui.date_with_time > 0) {
|
||||
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "safeguards.h"
|
||||
#include "station_base.h"
|
||||
|
||||
/* Bitmasks of company and cargo indices that shouldn't be drawn. */
|
||||
static CompanyMask _legend_excluded_companies;
|
||||
@@ -1649,3 +1650,277 @@ void InitializeGraphGui()
|
||||
_legend_excluded_companies = 0;
|
||||
_legend_excluded_cargo = 0;
|
||||
}
|
||||
|
||||
/*************************/
|
||||
/* STATION CARGO HISTORY */
|
||||
/*************************/
|
||||
struct StationCargoGraphWindow final : BaseGraphWindow {
|
||||
StationID station_id;
|
||||
uint line_height {}; ///< Pixel height of each cargo type row.
|
||||
Scrollbar *vscroll; ///< Cargo list scrollbar.
|
||||
uint legend_width {}; ///< Width of legend 'blob'.
|
||||
CargoTypes legend_excluded_cargo;
|
||||
CargoTypes present_cargoes;
|
||||
|
||||
StationCargoGraphWindow(WindowDesc *desc, WindowNumber window) :
|
||||
BaseGraphWindow(desc, WID_SCG_GRAPH, STR_JUST_COMMA)
|
||||
{
|
||||
station_id = static_cast<uint16>(window);
|
||||
|
||||
this->num_on_x_axis = MAX_STATION_CARGO_HISTORY_DAYS; // Four weeks
|
||||
this->num_vert_lines = MAX_STATION_CARGO_HISTORY_DAYS;
|
||||
this->month = 0xFF;
|
||||
this->x_values_start = 2;
|
||||
this->x_values_increment = 2;
|
||||
|
||||
this->CreateNestedTree();
|
||||
this->vscroll = this->GetScrollbar(WID_SCG_MATRIX_SCROLLBAR);
|
||||
|
||||
/* Initialise the data set */
|
||||
this->FillGraphData();
|
||||
|
||||
this->FinishInitNested(window);
|
||||
}
|
||||
|
||||
void OnInit() override
|
||||
{
|
||||
/* Width of the legend blob. */
|
||||
this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5;
|
||||
this->legend_excluded_cargo = 0;
|
||||
}
|
||||
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
if (widget == WID_SCG_CAPTION) {
|
||||
SetDParam(0, this->station_id);
|
||||
}
|
||||
if (widget == WID_SCG_FOOTER) {
|
||||
SetDParam(0, 48);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateExcludedData()
|
||||
{
|
||||
this->excluded_data = 0;
|
||||
|
||||
uint8 i = 0;
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||
if (HasBit(legend_excluded_cargo, cs->Index())) SetBit(this->excluded_data, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
if (widget < WID_SCG_MATRIX) {
|
||||
BaseGraphWindow::UpdateWidgetSize(widget, size, padding, fill, resize);
|
||||
return;
|
||||
}
|
||||
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
SetDParam(0, cs->name);
|
||||
Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO);
|
||||
d.width += this->legend_width + 4; // color field
|
||||
d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||
*size = maxdim(d, *size);
|
||||
}
|
||||
|
||||
this->line_height = size->height;
|
||||
size->height = this->line_height * 11; /* Default number of cargo types in most climates. */
|
||||
resize->width = 0;
|
||||
resize->height = this->line_height;
|
||||
}
|
||||
|
||||
void DrawWidget(const Rect &r, int widget) const override
|
||||
{
|
||||
if (widget < WID_SCG_MATRIX) {
|
||||
BaseGraphWindow::DrawWidget(r, widget);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool rtl = _current_text_dir == TD_RTL;
|
||||
|
||||
int x = r.left + WD_FRAMERECT_LEFT;
|
||||
int y = r.top;
|
||||
const uint row_height = FONT_HEIGHT_SMALL;
|
||||
const int padding = ScaleFontTrad(1);
|
||||
|
||||
int pos = this->vscroll->GetPosition();
|
||||
int max = pos + this->vscroll->GetCapacity();
|
||||
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||
if (pos-- > 0) continue;
|
||||
if (--max < 0) break;
|
||||
|
||||
const bool lowered = !HasBit(legend_excluded_cargo, cs->Index());
|
||||
|
||||
/* Redraw box if lowered */
|
||||
if (lowered) DrawFrameRect(r.left, y, r.right, y + this->line_height - 1, COLOUR_BROWN, lowered ? FR_LOWERED : FR_NONE);
|
||||
|
||||
const byte clk_dif = lowered ? 1 : 0;
|
||||
const int rect_x = clk_dif + (rtl ? r.right - this->legend_width - WD_FRAMERECT_RIGHT : r.left + WD_FRAMERECT_LEFT);
|
||||
|
||||
GfxFillRect(rect_x, y + padding + clk_dif, rect_x + this->legend_width, y + row_height - 1 + clk_dif, PC_BLACK);
|
||||
GfxFillRect(rect_x + 1, y + padding + 1 + clk_dif, rect_x + this->legend_width - 1, y + row_height - 2 + clk_dif, cs->legend_colour);
|
||||
SetDParam(0, cs->name);
|
||||
DrawString(rtl ? r.left : x + this->legend_width + 4 + clk_dif, (rtl ? r.right - this->legend_width - 4 + clk_dif : r.right), y + clk_dif, STR_GRAPH_CARGO_PAYMENT_CARGO);
|
||||
|
||||
y += this->line_height;
|
||||
}
|
||||
}
|
||||
|
||||
void OnClick(Point pt, int widget, int click_count) override
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_SCG_ENABLE_CARGOES:
|
||||
/* Remove all cargoes from the excluded lists. */
|
||||
this->legend_excluded_cargo = 0;
|
||||
this->excluded_data = 0;
|
||||
this->SetDirty();
|
||||
break;
|
||||
|
||||
case WID_SCG_DISABLE_CARGOES: {
|
||||
/* Add all cargoes to the excluded lists. */
|
||||
this->legend_excluded_cargo = ~static_cast<CargoTypes>(0);
|
||||
int i = 0;
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||
SetBit(this->excluded_data, i);
|
||||
i++;
|
||||
}
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_SCG_MATRIX: {
|
||||
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCG_MATRIX);
|
||||
if (row >= this->vscroll->GetCount()) return;
|
||||
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||
if (row-- > 0) continue;
|
||||
|
||||
ToggleBit(legend_excluded_cargo, cs->Index());
|
||||
this->UpdateExcludedData();
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnResize() override
|
||||
{
|
||||
this->vscroll->SetCapacityFromWidget(this, WID_SCG_MATRIX);
|
||||
}
|
||||
|
||||
void OnGameTick() override
|
||||
{
|
||||
/* Override default OnGameTick */
|
||||
}
|
||||
|
||||
/**
|
||||
* Some data on this window has become invalid.
|
||||
* @param data Information about the changed data.
|
||||
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
||||
*/
|
||||
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
||||
{
|
||||
if (!gui_scope) return;
|
||||
this->FillGraphData();
|
||||
}
|
||||
|
||||
void FillGraphData()
|
||||
{
|
||||
const Station* station = Station::GetIfValid(this->station_id);
|
||||
if (station == nullptr) return;
|
||||
|
||||
this->present_cargoes = station->station_cargo_history_cargoes;
|
||||
this->vscroll->SetCount(CountBits(this->present_cargoes));
|
||||
|
||||
this->UpdateExcludedData();
|
||||
|
||||
uint8 i = 0;
|
||||
const CargoSpec *cs;
|
||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||
this->colours[i] = cs->legend_colour;
|
||||
|
||||
const auto &history = station->station_cargo_history[CountBits(this->present_cargoes & (cs->CargoTypesBit() - 1))];
|
||||
|
||||
uint offset = station->station_cargo_history_offset;
|
||||
for (uint j = 0; j < MAX_STATION_CARGO_HISTORY_DAYS; j++) {
|
||||
this->cost[i][j] = history[offset];
|
||||
offset++;
|
||||
if (offset == MAX_STATION_CARGO_HISTORY_DAYS) offset = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
this->num_dataset = i;
|
||||
|
||||
this->SetDirty();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const NWidgetPart _nested_station_cargo_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCG_CAPTION), SetDataTip(STR_GRAPH_STATION_CARGO_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_SCG_BACKGROUND), SetMinimalSize(568, 128),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_SCG_HEADER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_STATION_CARGO_TITLE, STR_NULL),
|
||||
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCG_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 0), SetResize(0, 1),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SCG_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SCG_DISABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_SCG_MATRIX), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_SCG_MATRIX_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_SCG_MATRIX_SCROLLBAR),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1), SetResize(0, 1),
|
||||
EndContainer(),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(WD_RESIZEBOX_WIDTH, 0), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_TEXT, COLOUR_GREY, WID_SCG_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_STATION_CARGO_X_LABEL, STR_NULL),
|
||||
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY, WID_SCG_RESIZE),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
static WindowDesc _station_cargo_desc(
|
||||
WDP_AUTO, "graph_station_cargo", 0, 0,
|
||||
WC_STATION_CARGO, WC_NONE,
|
||||
0,
|
||||
_nested_station_cargo_widgets, lengthof(_nested_station_cargo_widgets)
|
||||
);
|
||||
|
||||
|
||||
void ShowStationCargo(StationID station_id)
|
||||
{
|
||||
AllocateWindowDescFront<StationCargoGraphWindow>(&_station_cargo_desc, station_id);
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,8 @@
|
||||
|
||||
extern uint8 _cargo_payment_x_mode;
|
||||
|
||||
typedef uint16 StationID;
|
||||
|
||||
void ShowOperatingProfitGraph();
|
||||
void ShowIncomeGraph();
|
||||
void ShowDeliveredCargoGraph();
|
||||
@@ -20,5 +22,6 @@ void ShowCompanyValueGraph();
|
||||
void ShowCargoPaymentRates();
|
||||
void ShowCompanyLeagueTable();
|
||||
void ShowPerformanceRatingDetail();
|
||||
void ShowStationCargo(StationID);
|
||||
|
||||
#endif /* GRAPH_GUI_H */
|
||||
|
@@ -613,6 +613,10 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Display
|
||||
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Toggle graph for cargo type on/off
|
||||
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
||||
|
||||
STR_GRAPH_STATION_CARGO_CAPTION :{WHITE}{STATION} - Waiting Cargo History
|
||||
STR_GRAPH_STATION_CARGO_X_LABEL :{TINY_FONT}{BLACK}Development over the last {NUM} days
|
||||
STR_GRAPH_STATION_CARGO_TITLE :{TINY_FONT}{BLACK}Units of cargo waiting at the station
|
||||
|
||||
STR_GRAPH_CARGO_DAYS_MODE :{TINY_FONT}{BLACK}Days in transit
|
||||
STR_GRAPH_CARGO_SPEED_MODE :{TINY_FONT}{BLACK}Average speed
|
||||
STR_GRAPH_CARGO_TOOLTIP_DAYS_MODE :{BLACK}Display days in transit on the x-axis of the graph
|
||||
@@ -4184,6 +4188,9 @@ STR_STATION_VIEW_GROUP_D_V_S :Destination-Via
|
||||
STR_STATION_VIEW_DEPARTURES_BUTTON :{BLACK}Departures
|
||||
STR_STATION_VIEW_DEPARTURES_TOOLTIP :{BLACK}Show list of scheduled departures
|
||||
|
||||
STR_STATION_VIEW_HISTORY_BUTTON :{BLACK}History
|
||||
STR_STATION_VIEW_HISTORY_TOOLTIP :{BLACK}Show waiting cargo history
|
||||
|
||||
############ range for rating starts
|
||||
STR_CARGO_RATING_APPALLING :Appalling
|
||||
STR_CARGO_RATING_VERY_POOR :Very Poor
|
||||
|
@@ -151,6 +151,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
||||
{ XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_CUSTOM_TOWN_ZONE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "custom_town_zone", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_STATION_CARGO_HISTORY, XSCF_NULL, 1, 1, "station_cargo_history", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||
};
|
||||
|
||||
|
@@ -105,6 +105,7 @@ enum SlXvFeatureIndex {
|
||||
XSLFI_WATER_FLOODING, ///< Water flooding map bit
|
||||
XSLFI_MORE_HOUSES, ///< More house types
|
||||
XSLFI_CUSTOM_TOWN_ZONE, ///< Custom town zones
|
||||
XSLFI_STATION_CARGO_HISTORY, ///< Station waiting cargo history
|
||||
|
||||
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
||||
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk
|
||||
|
@@ -459,6 +459,7 @@ static const SaveLoad _station_desc[] = {
|
||||
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES),
|
||||
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(32 * 24, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_22)),
|
||||
SLE_CONDVAR_X(Station, station_cargo_history_cargoes, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATION_CARGO_HISTORY)),
|
||||
|
||||
SLE_END()
|
||||
};
|
||||
@@ -547,6 +548,17 @@ static void RealSave_STNN(BaseStation *bst)
|
||||
SlObjectSaveFiltered(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc); // _cargo_list_desc has no conditionals
|
||||
}
|
||||
}
|
||||
|
||||
assert(st->station_cargo_history.size() == CountBits(st->station_cargo_history_cargoes));
|
||||
dumper->CheckBytes(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2);
|
||||
for (const auto &history : st->station_cargo_history) {
|
||||
uint i = st->station_cargo_history_offset;
|
||||
do {
|
||||
dumper->RawWriteUint16(history[i]);
|
||||
i++;
|
||||
if (i == MAX_STATION_CARGO_HISTORY_DAYS) i = 0;
|
||||
} while (i != st->station_cargo_history_offset);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < bst->num_specs; i++) {
|
||||
@@ -656,6 +668,15 @@ static void Load_STNN()
|
||||
}
|
||||
if (SlXvIsFeatureMissing(XSLFI_ST_LAST_VEH_TYPE)) st->goods[i].last_vehicle_type = _old_last_vehicle_type;
|
||||
}
|
||||
|
||||
st->station_cargo_history.resize(CountBits(st->station_cargo_history_cargoes));
|
||||
buffer->CheckBytes(st->station_cargo_history.size() * MAX_STATION_CARGO_HISTORY_DAYS * 2);
|
||||
for (auto &history : st->station_cargo_history) {
|
||||
for (uint16 &amount : history) {
|
||||
amount = buffer->RawReadUint16();
|
||||
}
|
||||
}
|
||||
st->station_cargo_history_offset = 0;
|
||||
}
|
||||
|
||||
if (bst->num_specs != 0) {
|
||||
|
@@ -62,6 +62,7 @@ BaseStation::~BaseStation()
|
||||
DeleteWindowById(WC_SHIPS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_SHIP, this->owner, this->index).Pack());
|
||||
DeleteWindowById(WC_AIRCRAFT_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_AIRCRAFT, this->owner, this->index).Pack());
|
||||
DeleteWindowById(WC_DEPARTURES_BOARD, this->index);
|
||||
DeleteWindowById(WC_STATION_CARGO, this->index);
|
||||
|
||||
if (HasBit(_display_opt, Station::IsExpected(this) ? DO_SHOW_STATION_NAMES : DO_SHOW_WAYPOINT_NAMES) &&
|
||||
!(_local_company != this->owner && this->owner != OWNER_NONE && !HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS))) {
|
||||
@@ -76,7 +77,9 @@ Station::Station(TileIndex tile) :
|
||||
ship_station(INVALID_TILE, 0, 0),
|
||||
indtype(IT_INVALID),
|
||||
time_since_load(255),
|
||||
time_since_unload(255)
|
||||
time_since_unload(255),
|
||||
station_cargo_history_cargoes(0),
|
||||
station_cargo_history_offset(0)
|
||||
{
|
||||
/* this->random_bits is set in Station::AddFacility() */
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "core/endian_type.hpp"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
@@ -808,6 +809,10 @@ public:
|
||||
IndustryList industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
|
||||
Industry *industry; ///< NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
|
||||
|
||||
CargoTypes station_cargo_history_cargoes; ///< Bitmask of cargoes in station_cargo_history
|
||||
uint8 station_cargo_history_offset; ///< Start offset in station_cargo_history cargo ring buffer
|
||||
std::vector<std::array<uint16, MAX_STATION_CARGO_HISTORY_DAYS>> station_cargo_history; ///< Station history of waiting cargo.
|
||||
|
||||
Station(TileIndex tile = INVALID_TILE);
|
||||
~Station();
|
||||
|
||||
@@ -817,6 +822,8 @@ public:
|
||||
|
||||
void UpdateVirtCoord() override;
|
||||
|
||||
void UpdateCargoHistory();
|
||||
|
||||
void MoveSign(TileIndex new_xy) override;
|
||||
|
||||
void AfterStationTileSetChange(bool adding, StationType type);
|
||||
|
@@ -404,6 +404,33 @@ void Station::GetTileArea(TileArea *ta, StationType type) const
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cargo history.
|
||||
*/
|
||||
void Station::UpdateCargoHistory()
|
||||
{
|
||||
uint storage_offset = 0;
|
||||
bool update_window = false;
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
uint amount = this->goods[cs->Index()].cargo.TotalCount();
|
||||
if (!HasBit(this->station_cargo_history_cargoes, cs->Index())) {
|
||||
if (amount == 0) {
|
||||
/* No cargo present, and no history stored for this cargo, no work to do */
|
||||
continue;
|
||||
} else {
|
||||
if (this->station_cargo_history_cargoes == 0) update_window = true;
|
||||
SetBit(this->station_cargo_history_cargoes, cs->Index());
|
||||
this->station_cargo_history.emplace(this->station_cargo_history.begin() + storage_offset);
|
||||
}
|
||||
}
|
||||
this->station_cargo_history[storage_offset][this->station_cargo_history_offset] = static_cast<uint16>(std::clamp<uint>(amount, (uint)0, (uint)UINT16_MAX));
|
||||
storage_offset++;
|
||||
}
|
||||
this->station_cargo_history_offset++;
|
||||
if (this->station_cargo_history_offset == MAX_STATION_CARGO_HISTORY_DAYS) this->station_cargo_history_offset = 0;
|
||||
if (update_window) InvalidateWindowData(WC_STATION_VIEW, this->index, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the virtual coords needed to draw the station sign.
|
||||
*/
|
||||
@@ -4240,6 +4267,18 @@ void OnTick_Station()
|
||||
}
|
||||
}
|
||||
|
||||
/** Daily loop for stations. */
|
||||
void StationDailyLoop()
|
||||
{
|
||||
// Only record cargo history every second day.
|
||||
if (_date % 2 != 0) {
|
||||
for (Station *st : Station::Iterate()) {
|
||||
st->UpdateCargoHistory();
|
||||
}
|
||||
InvalidateWindowClassesData(WC_STATION_CARGO);
|
||||
}
|
||||
}
|
||||
|
||||
/** Monthly loop for stations. */
|
||||
void StationMonthlyLoop()
|
||||
{
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "linkgraph/linkgraph.h"
|
||||
#include "zoom_func.h"
|
||||
#include "departures_gui.h"
|
||||
#include "graph_gui.h"
|
||||
#include "zoning.h"
|
||||
#include "newgrf_debug.h"
|
||||
|
||||
@@ -831,6 +832,8 @@ static const NWidgetPart _nested_station_view_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_ACCEPTS_RATINGS), SetMinimalSize(46, 12), SetResize(1, 0), SetFill(1, 1),
|
||||
SetDataTip(STR_STATION_VIEW_RATINGS_BUTTON, STR_STATION_VIEW_RATINGS_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_HISTORY), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1),
|
||||
SetDataTip(STR_STATION_VIEW_HISTORY_BUTTON, STR_STATION_VIEW_HISTORY_TOOLTIP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_DEPARTURES), SetMinimalSize(46, 12), SetResize(1, 0), SetFill(1, 1),
|
||||
SetDataTip(STR_STATION_VIEW_DEPARTURES_BUTTON, STR_STATION_VIEW_DEPARTURES_TOOLTIP),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SV_CLOSE_AIRPORT), SetMinimalSize(45, 12), SetResize(1, 0), SetFill(1, 1),
|
||||
@@ -1363,6 +1366,12 @@ struct StationViewWindow : public Window {
|
||||
SetViewportCatchmentStation(Station::Get(this->window_number), false);
|
||||
}
|
||||
|
||||
void OnInit() override
|
||||
{
|
||||
const Station *st = Station::Get(this->window_number);
|
||||
SetWidgetDisabledState(WID_SV_HISTORY, st->station_cargo_history_cargoes == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a certain cargo entry characterized by source/next/dest station, cargo ID and amount of cargo at the
|
||||
* right place in the cargo view. I.e. update as many rows as are expanded following that characterization.
|
||||
@@ -2052,6 +2061,11 @@ struct StationViewWindow : public Window {
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_SV_HISTORY: {
|
||||
ShowStationCargo((StationID)this->window_number);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_SV_DEPARTURES: {
|
||||
ShowStationDepartures((StationID)this->window_number);
|
||||
break;
|
||||
|
@@ -27,6 +27,8 @@ struct Waypoint;
|
||||
static const StationID NEW_STATION = 0xFFFE;
|
||||
static const StationID INVALID_STATION = 0xFFFF;
|
||||
|
||||
static const uint MAX_STATION_CARGO_HISTORY_DAYS = 24;
|
||||
|
||||
typedef SmallStack<StationID, StationID, INVALID_STATION, 8, 0xFFFD> StationIDStack;
|
||||
|
||||
/** Station types */
|
||||
|
@@ -53,6 +53,20 @@ enum CargoPaymentRatesWidgets {
|
||||
WID_CPR_SPEED, ///< Speed mode.
|
||||
};
|
||||
|
||||
/** Widget of the #StationCargoGraphWindow class. */
|
||||
enum StationCargoWidgets {
|
||||
WID_SCG_CAPTION, ///< Window title
|
||||
WID_SCG_BACKGROUND, ///< Background of the window.
|
||||
WID_SCG_HEADER, ///< Header.
|
||||
WID_SCG_GRAPH, ///< Graph itself.
|
||||
WID_SCG_RESIZE, ///< Resize button.
|
||||
WID_SCG_FOOTER, ///< Footer.
|
||||
WID_SCG_ENABLE_CARGOES, ///< Enable cargoes button.
|
||||
WID_SCG_DISABLE_CARGOES, ///< Disable cargoes button.
|
||||
WID_SCG_MATRIX, ///< Cargo list.
|
||||
WID_SCG_MATRIX_SCROLLBAR, ///< Cargo list scrollbar.
|
||||
};
|
||||
|
||||
/** Widget of the #CompanyLeagueWindow class. */
|
||||
enum CompanyLeagueWidgets {
|
||||
WID_CL_BACKGROUND, ///< Background of the window.
|
||||
|
@@ -30,6 +30,7 @@ enum StationViewWidgets {
|
||||
WID_SV_PLANES, ///< List of scheduled planes button.
|
||||
WID_SV_CATCHMENT, ///< Toggle catchment area highlight.
|
||||
WID_SV_DEPARTURES, ///< Departures button.
|
||||
WID_SV_HISTORY, ///< Cargo history button.
|
||||
};
|
||||
|
||||
/** Widgets of the #CompanyStationsWindow class. */
|
||||
|
@@ -581,6 +581,12 @@ enum WindowClass {
|
||||
*/
|
||||
WC_PAYMENT_RATES,
|
||||
|
||||
/**
|
||||
* Station cargo graph; %Window numbers:
|
||||
* - #StationID = #StationCargoWidgets
|
||||
*/
|
||||
WC_STATION_CARGO,
|
||||
|
||||
/**
|
||||
* Performance detail window; %Window numbers:
|
||||
* - 0 = #PerformanceRatingDetailsWidgets
|
||||
|
Reference in New Issue
Block a user