Improve performance of departures window

See: #119
This commit is contained in:
Jonathan G Rennison
2019-12-17 22:47:16 +00:00
parent abfb141afd
commit ec0b5e0ed0
7 changed files with 130 additions and 95 deletions

View File

@@ -195,14 +195,14 @@ static void ScheduledDispatchDepartureLocalFix(DepartureList *departure_list)
/** /**
* Compute an up-to-date list of departures for a station. * Compute an up-to-date list of departures for a station.
* @param station the station to compute the departures of * @param station the station to compute the departures of
* @param show_vehicle_types the types of vehicles to include in the departure list * @param vehicles set of all the vehicles stopping at this station, of all vehicles types that we are interested in
* @param type the type of departures to get (departures or arrivals) * @param type the type of departures to get (departures or arrivals)
* @param show_vehicles_via whether to include vehicles that have this station in their orders but do not stop at it * @param show_vehicles_via whether to include vehicles that have this station in their orders but do not stop at it
* @param show_pax whether to include passenger vehicles * @param show_pax whether to include passenger vehicles
* @param show_freight whether to include freight vehicles * @param show_freight whether to include freight vehicles
* @return a list of departures, which is empty if an error occurred * @return a list of departures, which is empty if an error occurred
*/ */
DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], DepartureType type, bool show_vehicles_via, bool show_pax, bool show_freight) DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type, bool show_vehicles_via, bool show_pax, bool show_freight)
{ {
/* This function is the meat of the departure boards functionality. */ /* This function is the meat of the departure boards functionality. */
/* As an overview, it works by repeatedly considering the best possible next departure to show. */ /* As an overview, it works by repeatedly considering the best possible next departure to show. */
@@ -231,24 +231,7 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5],
/* Cache for scheduled departure time */ /* Cache for scheduled departure time */
schdispatch_cache_t schdispatch_last_planned_dispatch; schdispatch_cache_t schdispatch_last_planned_dispatch;
/* Get all the vehicles stopping at this station. */ {
/* We do this to get the order which is the first time they will stop at this station. */
/* This order is stored along with some more information. */
/* We keep a pointer to the `least' order (the one with the soonest expected completion time). */
for (uint i = 0; i < 4; ++i) {
VehicleList vehicles;
if (!show_vehicle_types[i]) {
/* Don't show vehicles whose type we're not interested in. */
continue;
}
/* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station))) {
/* Something went wrong: panic! */
return result;
}
/* Get the first order for each vehicle for the station we're interested in that doesn't have No Loading set. */ /* Get the first order for each vehicle for the station we're interested in that doesn't have No Loading set. */
/* We find the least order while we're at it. */ /* We find the least order while we're at it. */
for (const Vehicle *v : vehicles) { for (const Vehicle *v : vehicles) {

View File

@@ -16,7 +16,9 @@
#include "core/smallvec_type.hpp" #include "core/smallvec_type.hpp"
#include "departures_type.h" #include "departures_type.h"
DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[4], DepartureType type = D_DEPARTURE, #include <vector>
DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type = D_DEPARTURE,
bool show_vehicles_via = false, bool show_pax = true, bool show_freight = true); bool show_vehicles_via = false, bool show_pax = true, bool show_freight = true);
#endif /* DEPARTURES_FUNC_H */ #endif /* DEPARTURES_FUNC_H */

View File

@@ -74,9 +74,16 @@ static WindowDesc _departures_desc(
static uint cached_date_width = 0; ///< The cached maximum width required to display a date. static uint cached_date_width = 0; ///< The cached maximum width required to display a date.
static uint cached_status_width = 0; ///< The cached maximum width required to show the status field. static uint cached_status_width = 0; ///< The cached maximum width required to show the status field.
static uint cached_date_arrow_width = 0; ///< The cached width of the red/green arrows that may be displayed alongside times. static uint cached_date_arrow_width = 0; ///< The cached width of the red/green arrows that may be displayed alongside times.
static uint cached_veh_type_width = 0; ///< The cached width of the vehicle type icon.
static bool cached_date_display_method; ///< Whether the above cached values refers to original (d,m,y) dates or the 24h clock. static bool cached_date_display_method; ///< Whether the above cached values refers to original (d,m,y) dates or the 24h clock.
static bool cached_arr_dep_display_method; ///< Whether to show departures and arrivals on a single line. static bool cached_arr_dep_display_method; ///< Whether to show departures and arrivals on a single line.
void FlushDeparturesWindowTextCaches()
{
cached_date_width = cached_status_width = cached_date_arrow_width = cached_veh_type_width = 0;
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
}
template<bool Twaypoint = false> template<bool Twaypoint = false>
struct DeparturesWindow : public Window { struct DeparturesWindow : public Window {
protected: protected:
@@ -93,6 +100,10 @@ protected:
bool cargo_buttons_disabled;///< Show pax/freight buttons disabled bool cargo_buttons_disabled;///< Show pax/freight buttons disabled
uint min_width; ///< The minimum width of this window. uint min_width; ///< The minimum width of this window.
Scrollbar *vscroll; Scrollbar *vscroll;
std::vector<const Vehicle *> vehicles; /// current set of vehicles
int veh_width; /// current width of vehicle field
int group_width; /// current width of group field
int toc_width; /// current width of company field
virtual uint GetMinWidth() const; virtual uint GetMinWidth() const;
static void RecomputeDateWidth(); static void RecomputeDateWidth();
@@ -122,6 +133,81 @@ protected:
} }
} }
void FillVehicleList()
{
this->vehicles.clear();
this->veh_width = 0;
this->group_width = 0;
this->toc_width = 0;
btree::btree_set<GroupID> groups;
CompanyMask companies = 0;
int unitnumber_max[4] = { -1, -1, -1, -1 };
const Vehicle *v;
FOR_ALL_VEHICLES(v) {
if (v->type < 4 && this->show_types[v->type] && v->IsPrimaryVehicle()) {
const Order *order;
FOR_VEHICLE_ORDERS(v, order) {
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT))
&& order->GetDestination() == this->station) {
this->vehicles.push_back(v);
if (v->name == nullptr) {
if (v->unitnumber > unitnumber_max[v->type]) unitnumber_max[v->type] = v->unitnumber;
} else {
SetDParam(0, (uint64)(v->index));
int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
if (width > this->veh_width) this->veh_width = width;
}
if (v->group_id != INVALID_GROUP && v->group_id != DEFAULT_GROUP) {
groups.insert(v->group_id);
}
SetBit(companies, v->owner);
break;
}
}
}
}
for (uint i = 0; i < 4; i++) {
if (unitnumber_max[i] >= 0) {
uint unitnumber_digits = 2;
if (unitnumber_max[i] >= 10000) {
unitnumber_digits = 5;
} else if (unitnumber_max[i] >= 1000) {
unitnumber_digits = 4;
} else if (unitnumber_max[i] >= 100) {
unitnumber_digits = 3;
}
SetDParamMaxDigits(0, unitnumber_digits);
int width = (GetStringBoundingBox(STR_SV_TRAIN_NAME + i)).width;
if (width > this->veh_width) this->veh_width = width;
}
}
for (GroupID gid : groups) {
SetDParam(0, (uint64)gid);
int width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
if (width > this->group_width) this->group_width = width;
}
uint owner;
FOR_EACH_SET_BIT(owner, companies) {
SetDParam(0, owner);
int width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
if (width > this->toc_width) this->toc_width = width;
}
}
void RefreshVehicleList() {
this->FillVehicleList();
this->calc_tick_countdown = 0;
}
public: public:
DeparturesWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc), DeparturesWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc),
@@ -171,6 +257,12 @@ public:
this->LowerWidget(WID_DB_SHOW_VIA); this->LowerWidget(WID_DB_SHOW_VIA);
} }
if (cached_veh_type_width == 0) {
cached_veh_type_width = GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE).width;
}
this->RefreshVehicleList();
if (_pause_mode != PM_UNPAUSED) this->OnGameTick(); if (_pause_mode != PM_UNPAUSED) this->OnGameTick();
} }
@@ -227,7 +319,7 @@ public:
this->SetWidgetDirty(widget); this->SetWidgetDirty(widget);
} }
/* We need to recompute the departures list. */ /* We need to recompute the departures list. */
this->calc_tick_countdown = 0; this->RefreshVehicleList();
/* We need to redraw the button that was pressed. */ /* We need to redraw the button that was pressed. */
if (_pause_mode != PM_UNPAUSED) this->OnGameTick(); if (_pause_mode != PM_UNPAUSED) this->OnGameTick();
break; break;
@@ -349,8 +441,8 @@ public:
this->DeleteDeparturesList(this->arrivals); this->DeleteDeparturesList(this->arrivals);
bool show_pax = _settings_client.gui.departure_only_passengers ? true : this->show_pax; bool show_pax = _settings_client.gui.departure_only_passengers ? true : this->show_pax;
bool show_freight = _settings_client.gui.departure_only_passengers ? false : this->show_freight; bool show_freight = _settings_client.gui.departure_only_passengers ? false : this->show_freight;
this->departures = (this->departure_types[0] ? MakeDepartureList(this->station, this->show_types, D_DEPARTURE, Twaypoint || this->departure_types[2], show_pax, show_freight) : new DepartureList()); this->departures = (this->departure_types[0] ? MakeDepartureList(this->station, this->vehicles, D_DEPARTURE, Twaypoint || this->departure_types[2], show_pax, show_freight) : new DepartureList());
this->arrivals = (this->departure_types[1] && !_settings_client.gui.departure_show_both ? MakeDepartureList(this->station, this->show_types, D_ARRIVAL, false, show_pax, show_freight) : new DepartureList()); this->arrivals = (this->departure_types[1] && !_settings_client.gui.departure_show_both ? MakeDepartureList(this->station, this->vehicles, D_ARRIVAL, false, show_pax, show_freight) : new DepartureList());
this->SetWidgetDirty(WID_DB_LIST); this->SetWidgetDirty(WID_DB_LIST);
} }
@@ -400,6 +492,16 @@ public:
this->vscroll->SetCapacityFromWidget(this, WID_DB_LIST); this->vscroll->SetCapacityFromWidget(this, WID_DB_LIST);
this->GetWidget<NWidgetCore>(WID_DB_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START); this->GetWidget<NWidgetCore>(WID_DB_LIST)->widget_data = (this->vscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
} }
/**
* 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
{
this->RefreshVehicleList();
}
}; };
/** /**
@@ -459,49 +561,12 @@ uint DeparturesWindow<Twaypoint>::GetMinWidth() const
result = cached_date_width; result = cached_date_width;
/* Vehicle type icon */ /* Vehicle type icon */
result += _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0; result += _settings_client.gui.departure_show_vehicle_type ? cached_veh_type_width : 0;
/* Status */ /* Status */
result += cached_status_width; result += cached_status_width;
/* Find the maximum company name width. */ result += this->toc_width + this->veh_width + this->group_width;
int toc_width = 0;
/* Find the maximum company name width. */
int group_width = 0;
/* Find the maximum vehicle name width. */
int veh_width = 0;
if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
for (uint i = 0; i < 4; ++i) {
VehicleList vehicles;
/* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station))) {
/* Something went wrong: panic! */
continue;
}
for (const Vehicle *v : vehicles) {
SetDParam(0, (uint64)(v->index));
int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
if (v->group_id != INVALID_GROUP && v->group_id != DEFAULT_GROUP) {
SetDParam(0, (uint64)(v->group_id));
width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
}
SetDParam(0, (uint64)(v->owner));
width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
}
}
}
result += toc_width + veh_width + group_width;
return result + 140; return result + 140;
} }
@@ -588,7 +653,7 @@ void DeparturesWindow<Twaypoint>::DrawDeparturesListItems(const Rect &r) const
} }
/* Vehicle type icon */ /* Vehicle type icon */
int type_width = _settings_client.gui.departure_show_vehicle_type ? (GetStringBoundingBox(STR_DEPARTURES_TYPE_PLANE)).width : 0; int type_width = _settings_client.gui.departure_show_vehicle_type ? cached_veh_type_width : 0;
/* Find the maximum width of the status field */ /* Find the maximum width of the status field */
int status_width = cached_status_width; int status_width = cached_status_width;
@@ -597,41 +662,13 @@ void DeparturesWindow<Twaypoint>::DrawDeparturesListItems(const Rect &r) const
int calling_at_width = (GetStringBoundingBox(_settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)).width; int calling_at_width = (GetStringBoundingBox(_settings_client.gui.departure_larger_font ? STR_DEPARTURES_CALLING_AT_LARGE : STR_DEPARTURES_CALLING_AT)).width;
/* Find the maximum company name width. */ /* Find the maximum company name width. */
int toc_width = 0; int toc_width = _settings_client.gui.departure_show_company ? this->toc_width : 0;
/* Find the maximum group name width. */ /* Find the maximum group name width. */
int group_width = 0; int group_width = _settings_client.gui.departure_show_group ? this->group_width : 0;
/* Find the maximum vehicle name width. */ /* Find the maximum vehicle name width. */
int veh_width = 0; int veh_width = _settings_client.gui.departure_show_vehicle ? this->veh_width : 0;
if (_settings_client.gui.departure_show_vehicle || _settings_client.gui.departure_show_company || _settings_client.gui.departure_show_group) {
for (uint i = 0; i < 4; ++i) {
VehicleList vehicles;
/* MAX_COMPANIES is probably the wrong thing to put here, but it works. GenerateVehicleSortList doesn't check the company when the type of list is VL_STATION_LIST (r20801). */
if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station))) {
/* Something went wrong: panic! */
continue;
}
for (const Vehicle *v : vehicles) {
SetDParam(0, (uint64)(v->index));
int width = (GetStringBoundingBox(STR_DEPARTURES_VEH)).width;
if (_settings_client.gui.departure_show_vehicle && width > veh_width) veh_width = width;
if (v->group_id != INVALID_GROUP && v->group_id != DEFAULT_GROUP) {
SetDParam(0, (uint64)(v->group_id));
width = (GetStringBoundingBox(STR_DEPARTURES_GROUP)).width;
if (_settings_client.gui.departure_show_group && width > group_width) group_width = width;
}
SetDParam(0, (uint64)(v->owner));
width = (GetStringBoundingBox(STR_DEPARTURES_TOC)).width;
if (_settings_client.gui.departure_show_company && width > toc_width) toc_width = width;
}
}
}
uint departure = 0; uint departure = 0;
uint arrival = 0; uint arrival = 0;

View File

@@ -1228,6 +1228,7 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
/* Make sure to rebuild the whole list */ /* Make sure to rebuild the whole list */
InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
} }
/** /**
@@ -1246,6 +1247,7 @@ static CommandCost DecloneOrder(Vehicle *dst, DoCommandFlag flags)
DeleteVehicleOrders(dst); DeleteVehicleOrders(dst);
InvalidateVehicleOrder(dst, VIWD_REMOVE_ALL_ORDERS); InvalidateVehicleOrder(dst, VIWD_REMOVE_ALL_ORDERS);
InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
CheckMarkDirtyFocusedRoutePaths(dst); CheckMarkDirtyFocusedRoutePaths(dst);
} }
return CommandCost(); return CommandCost();
@@ -1383,6 +1385,7 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
} }
InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
} }
/** /**
@@ -2056,6 +2059,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
CheckMarkDirtyFocusedRoutePaths(dst); CheckMarkDirtyFocusedRoutePaths(dst);
CheckAdvanceVehicleOrdersAfterClone(dst, flags); CheckAdvanceVehicleOrdersAfterClone(dst, flags);
@@ -2159,6 +2163,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
InvalidateVehicleOrder(dst, VIWD_REMOVE_ALL_ORDERS); InvalidateVehicleOrder(dst, VIWD_REMOVE_ALL_ORDERS);
InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
CheckMarkDirtyFocusedRoutePaths(dst); CheckMarkDirtyFocusedRoutePaths(dst);
CheckAdvanceVehicleOrdersAfterClone(dst, flags); CheckAdvanceVehicleOrdersAfterClone(dst, flags);

View File

@@ -41,6 +41,7 @@
#include "safeguards.h" #include "safeguards.h"
extern void FlushDeparturesWindowTextCaches();
static const StringID _driveside_dropdown[] = { static const StringID _driveside_dropdown[] = {
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
@@ -529,6 +530,7 @@ struct GameOptionsWindow : Window {
ClearAllCachedNames(); ClearAllCachedNames();
UpdateAllVirtCoords(); UpdateAllVirtCoords();
ReInitAllWindows(); ReInitAllWindows();
FlushDeparturesWindowTextCaches();
break; break;
case WID_GO_RESOLUTION_DROPDOWN: // Change resolution case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
@@ -544,6 +546,7 @@ struct GameOptionsWindow : Window {
UpdateAllVirtCoords(); UpdateAllVirtCoords();
FixTitleGameZoom(); FixTitleGameZoom();
ReInitAllWindows(); ReInitAllWindows();
FlushDeparturesWindowTextCaches();
break; break;
case WID_GO_FONT_ZOOM_DROPDOWN: case WID_GO_FONT_ZOOM_DROPDOWN:
@@ -554,6 +557,7 @@ struct GameOptionsWindow : Window {
UpdateFontHeightCache(); UpdateFontHeightCache();
LoadStringWidthTable(); LoadStringWidthTable();
UpdateAllVirtCoords(); UpdateAllVirtCoords();
FlushDeparturesWindowTextCaches();
break; break;
case WID_GO_BASE_GRF_DROPDOWN: case WID_GO_BASE_GRF_DROPDOWN:

View File

@@ -1009,6 +1009,7 @@ void Vehicle::PreDestructor()
OrderBackup::ClearVehicle(this); OrderBackup::ClearVehicle(this);
} }
InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
this->cargo.Truncate(); this->cargo.Truncate();
DeleteVehicleOrders(this); DeleteVehicleOrders(this);

View File

@@ -168,6 +168,7 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
InvalidateWindowClassesData(GetWindowClassForVehicleType(type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
SetWindowDirty(WC_COMPANY, _current_company); SetWindowDirty(WC_COMPANY, _current_company);
if (IsLocalCompany()) { if (IsLocalCompany()) {
InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the auto replace window (must be called before incrementing num_engines) InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the auto replace window (must be called before incrementing num_engines)
@@ -560,6 +561,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (!free_wagon) { if (!free_wagon) {
InvalidateWindowData(WC_VEHICLE_DETAILS, front->index); InvalidateWindowData(WC_VEHICLE_DETAILS, front->index);
InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
} }
/* virtual vehicles get their cargo changed by the TemplateCreateWindow, so set this dirty instead of a depot window */ /* virtual vehicles get their cargo changed by the TemplateCreateWindow, so set this dirty instead of a depot window */
if (HasBit(v->subtype, GVSF_VIRTUAL)) { if (HasBit(v->subtype, GVSF_VIRTUAL)) {
@@ -1616,6 +1618,7 @@ CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
free(v->name); free(v->name);
v->name = reset ? nullptr : stredup(text); v->name = reset ? nullptr : stredup(text);
InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 1); InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 1);
InvalidateWindowClassesData(WC_DEPARTURES_BOARD, 0);
MarkWholeScreenDirty(); MarkWholeScreenDirty();
} }