Ensure that timetable and scheduled dispatch windows redrawn as required
Reduce inefficient window and shared order list iteration
This commit is contained in:
@@ -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 */
|
||||
|
Reference in New Issue
Block a user