Avoid unnecessary redrawing of vehicle list windows

Redraw info section every tick if values have changed
pull/195/head
Jonathan G Rennison 4 years ago
parent 2c4808e239
commit bd2649c19e

@ -22,6 +22,7 @@
#include "window_func.h"
#include "date_func.h"
#include "vehicle_func.h"
#include "vehicle_gui.h"
#include "sound_func.h"
#include "cheat_type.h"
#include "company_base.h"
@ -471,7 +472,7 @@ void Aircraft::OnNewDay()
SubtractMoneyFromCompanyFract(this->owner, cost);
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
SetWindowClassesDirty(WC_AIRCRAFT_LIST);
DirtyVehicleListWindowForVehicle(this);
}
static void HelicopterTickHandler(Aircraft *v)
@ -1514,7 +1515,7 @@ void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
VehicleServiceInDepot(v);
SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
SetWindowClassesDirty(WC_AIRCRAFT_LIST);
DirtyVehicleListWindowForVehicle(v);
}
////////////////////////////////////////////////////////////////////////////////

@ -2158,7 +2158,7 @@ static void LoadUnloadVehicle(Vehicle *front)
}
if (dirty_vehicle) {
SetWindowDirty(GetWindowClassForVehicleType(front->type), front->owner);
DirtyVehicleListWindowForVehicle(front);
SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
front->MarkDirty();
}

@ -157,6 +157,10 @@ private:
Dimension column_size[VGC_END]; ///< Size of the columns in the group list.
Money money_this_year;
Money money_last_year;
uint32 occupancy_ratio;
/** return true if group has children */
void AddChildren(GUIGroupList *source, GroupID parent, int indent)
{
@ -377,6 +381,31 @@ private:
this->SetDirty();
}
bool RecalculateInfoTotals()
{
Money this_year = 0;
Money last_year = 0;
uint32 occupancy = 0;
size_t vehicle_count = this->vehicles.size();
for (uint i = 0; i < vehicle_count; i++) {
const Vehicle *v = this->vehicles[i];
assert(v->owner == this->owner);
this_year += v->GetDisplayProfitThisYear();
last_year += v->GetDisplayProfitLastYear();
occupancy += v->trip_occupancy;
}
uint32 occupancy_ratio = occupancy / vehicle_count;
bool ret = (this->money_this_year != this_year) || (this->money_last_year != last_year) || (occupancy_ratio != this->occupancy_ratio);
this->money_this_year = this_year;
this->money_last_year = last_year;
this->occupancy_ratio = occupancy_ratio;
return ret;
}
public:
VehicleGroupWindow(WindowDesc *desc, WindowNumber window_number) : BaseVehicleListWindow(desc, window_number)
{
@ -412,6 +441,8 @@ public:
this->BuildGroupList(vli.company);
this->group_sb->SetCount((uint)this->groups.size());
this->RecalculateInfoTotals();
this->GetWidget<NWidgetCore>(WID_GL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
this->GetWidget<NWidgetCore>(WID_GL_LIST_VEHICLE)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
@ -556,6 +587,7 @@ public:
{
/* If we select the all vehicles, this->list will contain all vehicles of the owner
* else this->list will contain all vehicles which belong to the selected group */
if (this->vehicles.NeedRebuild()) this->RecalculateInfoTotals();
this->BuildVehicleList();
this->SortVehicleList();
@ -621,37 +653,23 @@ public:
break;
case WID_GL_INFO: {
Money this_year = 0;
Money last_year = 0;
uint32 occupancy = 0;
size_t vehicle_count = this->vehicles.size();
for (uint i = 0; i < vehicle_count; i++) {
const Vehicle *v = this->vehicles[i];
assert(v->owner == this->owner);
this_year += v->GetDisplayProfitThisYear();
last_year += v->GetDisplayProfitLastYear();
occupancy += v->trip_occupancy;
}
const int left = r.left + WD_FRAMERECT_LEFT + 8;
const int right = r.right - WD_FRAMERECT_RIGHT - 8;
int y = r.top + WD_FRAMERECT_TOP;
DrawString(left, right, y, STR_GROUP_PROFIT_THIS_YEAR, TC_BLACK);
SetDParam(0, this_year);
SetDParam(0, this->money_this_year);
DrawString(left, right, y, STR_JUST_CURRENCY_LONG, TC_BLACK, SA_RIGHT);
y += FONT_HEIGHT_NORMAL;
DrawString(left, right, y, STR_GROUP_PROFIT_LAST_YEAR, TC_BLACK);
SetDParam(0, last_year);
SetDParam(0, this->money_last_year);
DrawString(left, right, y, STR_JUST_CURRENCY_LONG, TC_BLACK, SA_RIGHT);
y += FONT_HEIGHT_NORMAL;
DrawString(left, right, y, STR_GROUP_OCCUPANCY, TC_BLACK);
if (vehicle_count > 0) {
SetDParam(0, occupancy / vehicle_count);
if (this->vehicles.size() > 0) {
SetDParam(0, this->occupancy_ratio);
DrawString(left, right, y, STR_GROUP_OCCUPANCY_VALUE, TC_BLACK, SA_RIGHT);
}
@ -1024,7 +1042,10 @@ public:
void OnGameTick() override
{
if (this->groups.NeedResort() || this->vehicles.NeedResort()) {
this->SetDirty();
this->SetWidgetDirty(WID_GL_LIST_VEHICLE);
}
if (this->RecalculateInfoTotals()) {
this->SetWidgetDirty(WID_GL_INFO);
}
}

@ -1464,8 +1464,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
}
/* We have an aircraft/ship, they have a mini-schedule, so update them all */
if (v->type == VEH_AIRCRAFT) SetWindowClassesDirty(WC_AIRCRAFT_LIST);
if (v->type == VEH_SHIP) SetWindowClassesDirty(WC_SHIPS_LIST);
if (v->type == VEH_AIRCRAFT || v->type == VEH_SHIP) DirtyVehicleListWindowForVehicle(v);
return CommandCost();
}
@ -2958,7 +2957,7 @@ bool ProcessOrders(Vehicle *v)
case VEH_AIRCRAFT:
case VEH_SHIP:
SetWindowClassesDirty(GetWindowClassForVehicleType(v->type));
DirtyVehicleListWindowForVehicle(v);
break;
}

@ -1833,7 +1833,7 @@ void RoadVehicle::OnNewDay()
SubtractMoneyFromCompanyFract(this->owner, cost);
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
SetWindowClassesDirty(WC_ROADVEH_LIST);
DirtyVehicleListWindowForVehicle(this);
}
Trackdir RoadVehicle::GetVehicleTrackdir() const

@ -24,6 +24,7 @@
#include "window_func.h"
#include "date_func.h"
#include "vehicle_func.h"
#include "vehicle_gui.h"
#include "sound_func.h"
#include "ai/ai.hpp"
#include "game/game.hpp"
@ -254,7 +255,7 @@ void Ship::OnNewDay()
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
/* we need this for the profit */
SetWindowClassesDirty(WC_SHIPS_LIST);
DirtyVehicleListWindowForVehicle(this);
}
Trackdir Ship::GetVehicleTrackdir() const
@ -414,7 +415,7 @@ static bool CheckShipLeaveDepot(Ship *v)
PlayShipSound(v);
VehicleServiceInDepot(v);
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
SetWindowClassesDirty(WC_SHIPS_LIST);
DirtyVehicleListWindowForVehicle(v);
return false;
}

@ -169,8 +169,6 @@ public:
virtual_train = nullptr;
}
SetWindowClassesDirty(WC_TRAINS_LIST);
/* more cleanup */
*create_window_open = false;
DeleteWindowById(WC_BUILD_VIRTUAL_TRAIN, this->window_number);

@ -2972,6 +2972,7 @@ void ShowTraceRestrictProgramWindow(TileIndex tile, Track track)
/** Slot GUI widget IDs */
enum TraceRestrictSlotWindowWidgets {
WID_TRSL_LIST_VEHICLE, // this must be first, see: DirtyVehicleListWindowForVehicle
WID_TRSL_CAPTION,
WID_TRSL_ALL_VEHICLES,
WID_TRSL_LIST_SLOTS,
@ -2984,7 +2985,6 @@ enum TraceRestrictSlotWindowWidgets {
WID_TRSL_SORT_BY_DROPDOWN,
WID_TRSL_FILTER_BY_CARGO,
WID_TRSL_FILTER_BY_CARGO_SEL,
WID_TRSL_LIST_VEHICLE,
WID_TRSL_LIST_VEHICLE_SCROLLBAR,
};

@ -2378,8 +2378,7 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32
SetWindowDirty(WC_VEHICLE_DEPOT, front->tile);
SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
SetWindowDirty(WC_VEHICLE_VIEW, front->index);
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
DirtyVehicleListWindowForVehicle(front);
}
} else {
/* turn the whole train around */
@ -2609,8 +2608,6 @@ static bool CheckTrainStayInDepot(Train *v)
if (v->force_proceed == TFP_NONE) {
/* force proceed was not pressed */
if (++v->wait_counter < 37) {
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
return true;
}
@ -2619,8 +2616,6 @@ static bool CheckTrainStayInDepot(Train *v)
seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
if (seg_state == SIGSEG_FULL || HasDepotReservation(v->tile)) {
/* Full and no PBS signal in block or depot reserved, can't exit. */
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
return true;
}
} else {
@ -2684,8 +2679,6 @@ static bool CheckTrainStayInDepot(Train *v)
/* Only leave when we can reserve a path to our destination. */
if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
/* No path and no force proceed. */
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
MarkTrainAsStuck(v);
return true;
}
@ -2694,8 +2687,7 @@ static bool CheckTrainStayInDepot(Train *v)
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile, VMDF_NOT_MAP_MODE);
VehicleServiceInDepot(v);
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
DirtyVehicleListWindowForVehicle(v);
v->PlayLeaveStationSound();
v->track = TRACK_BIT_X;
@ -5244,8 +5236,7 @@ void Train::OnNewDay()
SubtractMoneyFromCompanyFract(this->owner, cost);
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
DirtyVehicleListWindowForVehicle(this);
}
}
if (IsEngine() || IsMultiheaded()) {

@ -2172,8 +2172,6 @@ void VehicleEnterDepot(Vehicle *v)
switch (v->type) {
case VEH_TRAIN: {
Train *t = Train::From(v);
SetWindowClassesDirty(WC_TRAINS_LIST);
SetWindowClassesDirty(WC_TRACE_RESTRICT_SLOTS);
/* Clear path reservation */
SetDepotReservation(t->tile, false);
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(t->tile, VMDF_NOT_MAP_MODE);
@ -2188,11 +2186,9 @@ void VehicleEnterDepot(Vehicle *v)
}
case VEH_ROAD:
SetWindowClassesDirty(WC_ROADVEH_LIST);
break;
case VEH_SHIP: {
SetWindowClassesDirty(WC_SHIPS_LIST);
Ship *ship = Ship::From(v);
ship->state = TRACK_BIT_DEPOT;
ship->UpdateCache();
@ -2202,12 +2198,12 @@ void VehicleEnterDepot(Vehicle *v)
}
case VEH_AIRCRAFT:
SetWindowClassesDirty(WC_AIRCRAFT_LIST);
HandleAircraftEnterHangar(Aircraft::From(v));
break;
default: NOT_REACHED();
}
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
DirtyVehicleListWindowForVehicle(v);
if (v->type != VEH_TRAIN) {
/* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
@ -2935,7 +2931,7 @@ void Vehicle::BeginLoading()
PrepareUnload(this);
}
SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
DirtyVehicleListWindowForVehicle(this);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
SetWindowDirty(WC_STATION_VIEW, this->last_station_visited);

@ -659,7 +659,7 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
v->MarkDirty();
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
SetWindowClassesDirty(GetWindowClassForVehicleType(v->type));
DirtyVehicleListWindowForVehicle(v);
InvalidateWindowData(WC_VEHICLE_VIEW, v->index);
}
return CommandCost();

@ -2287,6 +2287,24 @@ void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileInde
ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_airport_index);
}
void DirtyVehicleListWindowForVehicle(const Vehicle *v)
{
WindowClass cls = static_cast<WindowClass>(WC_TRAINS_LIST + v->type);
WindowClass cls2 = (v->type == VEH_TRAIN) ? WC_TRACE_RESTRICT_SLOTS : cls;
Window *w;
FOR_ALL_WINDOWS_FROM_BACK(w) {
if (w->window_class == cls || w->window_class == cls2) {
BaseVehicleListWindow *listwin = static_cast<BaseVehicleListWindow *>(w);
uint max = min(listwin->vscroll->GetPosition() + listwin->vscroll->GetCapacity(), (uint)listwin->vehicles.size());
for (uint i = listwin->vscroll->GetPosition(); i < max; ++i) {
if (v == listwin->vehicles[i]) {
listwin->SetWidgetDirty(0);
break;
}
}
}
}
}
/* Unified vehicle GUI - Vehicle Details Window */

@ -61,6 +61,8 @@ void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type);
void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station);
void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile);
void DirtyVehicleListWindowForVehicle(const Vehicle *v);
/**
* Get the height of a single vehicle in the GUIs.
* @param type the vehicle type to look at

@ -12,12 +12,12 @@
/** Widgets of the #VehicleGroupWindow class. */
enum GroupListWidgets {
WID_GL_LIST_VEHICLE, ///< List of the vehicles, this must be first, see: DirtyVehicleListWindowForVehicle
WID_GL_CAPTION, ///< Caption of the window.
WID_GL_SORT_BY_ORDER, ///< Sort order.
WID_GL_SORT_BY_DROPDOWN, ///< Sort by dropdown list.
WID_GL_FILTER_BY_CARGO, ///< Filter vehicle by cargo type.
WID_GL_FILTER_BY_CARGO_SEL, ///< Filter vehicle by cargo type panel selector.
WID_GL_LIST_VEHICLE, ///< List of the vehicles.
WID_GL_LIST_VEHICLE_SCROLLBAR, ///< Scrollbar for the list.
WID_GL_AVAILABLE_VEHICLES, ///< Available vehicles.
WID_GL_MANAGE_VEHICLES_DROPDOWN, ///< Manage vehicles dropdown list.

@ -60,12 +60,12 @@ enum VehicleDetailsWidgets {
/** Widgets of the #VehicleListWindow class. */
enum VehicleListWidgets {
WID_VL_LIST, ///< List of the vehicles, this must be first, see: DirtyVehicleListWindowForVehicle
WID_VL_CAPTION, ///< Caption of window.
WID_VL_SORT_ORDER, ///< Sort order.
WID_VL_SORT_BY_PULLDOWN, ///< Sort by dropdown list.
WID_VL_FILTER_BY_CARGO, ///< Cargo filter dropdown list
WID_VL_FILTER_BY_CARGO_SEL, ///< Cargo filter dropdown list panel selector
WID_VL_LIST, ///< List of the vehicles.
WID_VL_SCROLLBAR, ///< Scrollbar for the list.
WID_VL_HIDE_BUTTONS, ///< Selection to hide the buttons.
WID_VL_AVAILABLE_VEHICLES, ///< Available vehicles.

Loading…
Cancel
Save