Ensure that timetable and scheduled dispatch windows redrawn as required

Reduce inefficient window and shared order list iteration
pull/362/head
Jonathan G Rennison 2 years ago
parent fe522f193b
commit 543433218c

@ -639,7 +639,7 @@ public:
void RemoveScheduledDispatch(uint32 offset);
void ClearScheduledDispatch() { this->scheduled_dispatch.clear(); }
bool UpdateScheduledDispatchToDate(DateTicksScaled now);
void UpdateScheduledDispatch();
void UpdateScheduledDispatch(const Vehicle *v);
/**
* Set the scheduled dispatch duration, in scaled tick

@ -338,6 +338,7 @@ Order::Order(uint64 packed)
void InvalidateVehicleOrder(const Vehicle *v, int data)
{
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
if (data != 0) {
/* Calls SetDirty() too */

@ -15,6 +15,7 @@
#include "settings_type.h"
void ShowSchdispatchWindow(const Vehicle *v);
void SchdispatchInvalidateWindows(const Vehicle *v);
/**
* Convert date and full date fraction to DateTicksScaled

@ -59,9 +59,8 @@ CommandCost CmdScheduledDispatch(TileIndex tile, DoCommandFlag flags, uint32 p1,
} else {
ClrBit(v2->vehicle_flags, VF_SCHEDULED_DISPATCH);
}
SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v2->index);
}
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -106,7 +105,7 @@ CommandCost CmdScheduledDispatchAdd(TileIndex tile, DoCommandFlag flags, uint32
p2 += offset;
ds.AddScheduledDispatch(p2);
}
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -138,7 +137,7 @@ CommandCost CmdScheduledDispatchRemove(TileIndex tile, DoCommandFlag flags, uint
if (flags & DC_EXEC) {
v->orders.list->GetDispatchScheduleByIndex(schedule_index).RemoveScheduledDispatch(p2);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -172,8 +171,8 @@ CommandCost CmdScheduledDispatchSetDuration(TileIndex tile, DoCommandFlag flags,
if (flags & DC_EXEC) {
DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(schedule_index);
ds.SetScheduledDispatchDuration(p2);
ds.UpdateScheduledDispatch();
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
ds.UpdateScheduledDispatch(nullptr);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -217,8 +216,8 @@ CommandCost CmdScheduledDispatchSetStartDate(TileIndex tile, DoCommandFlag flags
if (flags & DC_EXEC) {
DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(schedule_index);
ds.SetScheduledDispatchStartDate(date, full_date_fract);
ds.UpdateScheduledDispatch();
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
ds.UpdateScheduledDispatch(nullptr);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -251,7 +250,7 @@ CommandCost CmdScheduledDispatchSetDelay(TileIndex tile, DoCommandFlag flags, ui
if (flags & DC_EXEC) {
v->orders.list->GetDispatchScheduleByIndex(schedule_index).SetScheduledDispatchDelay(p2);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -289,7 +288,7 @@ CommandCost CmdScheduledDispatchResetLastDispatch(TileIndex tile, DoCommandFlag
if (flags & DC_EXEC) {
v->orders.list->GetDispatchScheduleByIndex(schedule_index).SetScheduledDispatchLastDispatch(0);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -322,7 +321,7 @@ CommandCost CmdScheduledDispatchClear(TileIndex tile, DoCommandFlag flags, uint3
if (flags & DC_EXEC) {
v->orders.list->GetDispatchScheduleByIndex(schedule_index).ClearScheduledDispatch();
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -362,9 +361,8 @@ CommandCost CmdScheduledDispatchAddNewSchedule(TileIndex tile, DoCommandFlag fla
DispatchSchedule &ds = v->orders.list->GetScheduledDispatchScheduleSet().back();
ds.SetScheduledDispatchDuration(p2);
ds.SetScheduledDispatchStartDate(date, full_date_fract);
ds.UpdateScheduledDispatch();
SetWindowClassesDirty(WC_VEHICLE_TIMETABLE);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v->index);
ds.UpdateScheduledDispatch(nullptr);
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -406,8 +404,7 @@ CommandCost CmdScheduledDispatchRemoveSchedule(TileIndex tile, DoCommandFlag fla
o->SetDispatchScheduleIndex(idx - 1);
}
}
SetWindowClassesDirty(WC_VEHICLE_TIMETABLE);
InvalidateWindowClassesData(WC_SCHDISPATCH_SLOTS, VIWD_MODIFY_ORDERS);
SchdispatchInvalidateWindows(v);
}
return CommandCost();
@ -421,7 +418,7 @@ void DispatchSchedule::SetScheduledDispatch(std::vector<uint32> dispatch_list)
{
this->scheduled_dispatch = std::move(dispatch_list);
assert(std::is_sorted(this->scheduled_dispatch.begin(), this->scheduled_dispatch.end()));
if (this->IsScheduledDispatchValid()) this->UpdateScheduledDispatch();
if (this->IsScheduledDispatchValid()) this->UpdateScheduledDispatch(nullptr);
}
/**
@ -436,7 +433,7 @@ void DispatchSchedule::AddScheduledDispatch(uint32 offset)
return;
}
this->scheduled_dispatch.insert(insert_position, offset);
this->UpdateScheduledDispatch();
this->UpdateScheduledDispatch(nullptr);
}
/**
@ -496,9 +493,9 @@ bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now)
/**
* Update the scheduled dispatch start time to be the most recent possible.
*/
void DispatchSchedule::UpdateScheduledDispatch()
void DispatchSchedule::UpdateScheduledDispatch(const Vehicle *v)
{
if (this->UpdateScheduledDispatchToDate(_scaled_date_ticks)) {
InvalidateWindowClassesData(WC_SCHDISPATCH_SLOTS, VIWD_MODIFY_ORDERS);
if (this->UpdateScheduledDispatchToDate(_scaled_date_ticks) && v != nullptr) {
SetTimetableWindowsDirty(v, true);
}
}

@ -184,8 +184,7 @@ static void AddNewScheduledDispatchSchedule(VehicleID vindex)
DoCommandPEx(0, vindex, duration, p3, CMD_SCHEDULED_DISPATCH_ADD_NEW_SCHEDULE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), CcAddNewSchDispatchSchedule, nullptr, 0);
}
struct SchdispatchWindow : Window {
const Vehicle *vehicle; ///< Vehicle monitored by the window.
struct SchdispatchWindow : GeneralVehicleWindow {
int schedule_index;
int clicked_widget; ///< The widget that was clicked (used to determine what to do in OnQueryTextFinished)
Scrollbar *vscroll; ///< Verticle scrollbar
@ -197,8 +196,7 @@ struct SchdispatchWindow : Window {
bool no_order_warning_pad = false;
SchdispatchWindow(WindowDesc *desc, WindowNumber window_number) :
Window(desc),
vehicle(Vehicle::Get(window_number))
GeneralVehicleWindow(desc, Vehicle::Get(window_number))
{
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_SCHDISPATCH_V_SCROLL);
@ -1151,3 +1149,16 @@ void ShowScheduledDispatchAddSlotsWindow(SchdispatchWindow *parent, int window_n
new ScheduledDispatchAddSlotsWindow(&_scheduled_dispatch_add_desc, window_number, parent);
}
void SchdispatchInvalidateWindows(const Vehicle *v)
{
v = v->FirstShared();
for (Window *w : Window::IterateFromBack()) {
if (w->window_class == WC_VEHICLE_TIMETABLE) {
if (static_cast<GeneralVehicleWindow *>(w)->vehicle->FirstShared() == v) w->SetDirty();
}
if (w->window_class == WC_SCHDISPATCH_SLOTS) {
if (static_cast<GeneralVehicleWindow *>(w)->vehicle->FirstShared() == v) w->InvalidateData(VIWD_MODIFY_ORDERS, false);
}
}
}

@ -18,6 +18,7 @@
void ShowTimetableWindow(const Vehicle *v);
void UpdateVehicleTimetable(Vehicle *v, bool travelling);
void SetTimetableParams(int first_param, Ticks ticks, bool long_mode = false);
void SetTimetableWindowsDirty(const Vehicle *v, bool include_scheduled_dispatch = false);
struct TimetableProgress {
VehicleID id;

@ -102,6 +102,8 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val,
v->orders.list->UpdateTotalDuration(total_delta);
v->orders.list->UpdateTimetableDuration(timetable_delta);
SetTimetableWindowsDirty(v, mtf == MTF_ASSIGN_SCHEDULE);
for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
switch (mtf) {
@ -139,7 +141,6 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint32 val,
NOT_REACHED();
}
}
SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
}
}
@ -469,8 +470,10 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1,
for (Vehicle *w = v->orders.list->GetFirstSharedVehicle(); w != nullptr; w = w->NextShared()) {
vehs.push_back(w);
}
SetTimetableWindowsDirty(v);
} else {
vehs.push_back(v);
SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
}
int total_duration = v->orders.list->GetTimetableTotalDuration();
@ -483,7 +486,6 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1,
int idx = vehs.begin() - std::find(vehs.begin(), vehs.end(), v);
for (Vehicle *w : vehs) {
w->lateness_counter = 0;
ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
/* Do multiplication, then division to reduce rounding errors. */
@ -493,7 +495,6 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1,
}
w->timetable_start = tt_start / _settings_game.economy.day_length_factor;
w->timetable_start_subticks = tt_start % _settings_game.economy.day_length_factor;
SetWindowDirty(WC_VEHICLE_TIMETABLE, w->index);
++idx;
}
@ -551,8 +552,8 @@ CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1,
ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
}
SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
}
SetTimetableWindowsDirty(v);
}
return CommandCost();
@ -608,8 +609,8 @@ CommandCost CmdAutomateTimetable(TileIndex index, DoCommandFlag flags, uint32 p1
v2->current_loading_time = 0;
}
}
SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
}
SetTimetableWindowsDirty(v);
if (!HasBit(p2, 0) && !HasBit(p2, 1)) {
OrderList *orders = v->orders.list;
if (orders != nullptr) {
@ -652,9 +653,8 @@ CommandCost CmdTimetableSeparation(TileIndex tile, DoCommandFlag flags, uint32 p
ClrBit(v2->vehicle_flags, VF_TIMETABLE_SEPARATION);
}
v2->ClearSeparation();
SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
SetWindowDirty(WC_SCHDISPATCH_SLOTS, v2->index);
}
SetTimetableWindowsDirty(v, true);
}
return CommandCost();
@ -847,7 +847,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(real_implicit_order->GetDispatchScheduleIndex());
/* Update scheduled information */
ds.UpdateScheduledDispatch();
ds.UpdateScheduledDispatch(v);
const int wait_offset = real_current_order->GetTimetabledWait();
DateTicksScaled slot = GetScheduledDispatchTime(ds, _scaled_date_ticks + wait_offset);
@ -867,9 +867,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
/* If the lateness is set by scheduled dispatch above, do not reset */
if (!HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) v->lateness_counter = 0;
if (HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION)) UpdateSeparationOrder(v);
for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
}
SetTimetableWindowsDirty(v);
return;
}
@ -969,8 +967,8 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
/* Clear VF_TIMETABLE_STARTED but do not call ClearSeparation */
ClrBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
v2->lateness_counter = 0;
SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
}
SetTimetableWindowsDirty(v);
return;
} else if (new_time >= (int32)timetabled / 2) {
/* Compute running average, with sign conversion to avoid negative overflow.
@ -1037,9 +1035,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
}
}
for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
}
SetTimetableWindowsDirty(v);
}
void SetOrderFixedWaitTime(Vehicle *v, VehicleOrderID order_number, uint32 wait_time, bool wait_timetabled) {

@ -289,9 +289,8 @@ void ProcessTimetableWarnings(const Vehicle *v, std::function<void(StringID, boo
}
struct TimetableWindow : Window {
struct TimetableWindow : GeneralVehicleWindow {
int sel_index;
const Vehicle *vehicle; ///< Vehicle monitored by the window.
bool show_expected; ///< Whether we show expected arrival or scheduled
uint deparr_time_width; ///< The width of the departure/arrival time
uint deparr_abbr_width; ///< The width of the departure/arrival abbreviation
@ -307,9 +306,8 @@ struct TimetableWindow : Window {
};
TimetableWindow(WindowDesc *desc, WindowNumber window_number) :
Window(desc),
GeneralVehicleWindow(desc, Vehicle::Get(window_number)),
sel_index(-1),
vehicle(Vehicle::Get(window_number)),
show_expected(true)
{
this->CreateNestedTree();
@ -1197,3 +1195,13 @@ void ShowTimetableWindow(const Vehicle *v)
DeleteWindowById(WC_VEHICLE_ORDERS, v->index, false);
AllocateWindowDescFront<TimetableWindow>(&_timetable_desc, v->index);
}
void SetTimetableWindowsDirty(const Vehicle *v, bool include_scheduled_dispatch)
{
v = v->FirstShared();
for (Window *w : Window::IterateFromBack()) {
if (w->window_class == WC_VEHICLE_TIMETABLE || (include_scheduled_dispatch && w->window_class == WC_SCHDISPATCH_SLOTS)) {
if (static_cast<GeneralVehicleWindow *>(w)->vehicle->FirstShared() == v) w->SetDirty();
}
}
}

@ -2139,6 +2139,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
DeleteWindowById(WC_VEHICLE_REFIT, src->index);
DeleteWindowById(WC_VEHICLE_DETAILS, src->index);
DeleteWindowById(WC_VEHICLE_TIMETABLE, src->index);
DeleteWindowById(WC_SCHDISPATCH_SLOTS, src->index);
DeleteNewGRFInspectWindow(GSF_TRAINS, src->index);
SetWindowDirty(WC_COMPANY, _current_company);

@ -1102,4 +1102,10 @@ inline bool MayBeShown(const Window *w)
}
}
struct GeneralVehicleWindow : public Window {
const Vehicle *vehicle;
GeneralVehicleWindow(WindowDesc *desc, const Vehicle *v) : Window(desc), vehicle(v) {}
};
#endif /* WINDOW_GUI_H */

Loading…
Cancel
Save