Viewport: Refactor handling of vehicle route overlays

pull/519/head
Jonathan G Rennison 1 year ago
parent 31f476220d
commit 4c2244cc21

@ -182,7 +182,7 @@ public:
~CargoTypeOrdersWindow()
{
if (!FocusWindowById(WC_VEHICLE_ORDERS, this->window_number)) {
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
@ -297,16 +297,14 @@ public:
virtual void OnFocus(Window *previously_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
virtual void OnFocusLost(Window *newly_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
@ -1859,7 +1857,7 @@ public:
DeleteWindowById(WC_VEHICLE_CARGO_TYPE_LOAD_ORDERS, this->window_number, false);
DeleteWindowById(WC_VEHICLE_CARGO_TYPE_UNLOAD_ORDERS, this->window_number, false);
if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) {
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
@ -3486,16 +3484,14 @@ public:
virtual void OnFocus(Window *previously_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
virtual void OnFocusLost(Window *newly_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}

@ -211,7 +211,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
~SchdispatchWindow()
{
if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) {
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
@ -900,8 +900,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
virtual void OnFocus(Window *previously_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}

@ -386,7 +386,7 @@ struct TimetableWindow : GeneralVehicleWindow {
~TimetableWindow()
{
if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) {
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
@ -1173,16 +1173,14 @@ struct TimetableWindow : GeneralVehicleWindow {
virtual void OnFocus(Window *previously_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}
virtual void OnFocusLost(Window *newly_focused_window) override
{
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
MarkAllRoutePathsDirty(this->vehicle);
MarkAllRouteStepsDirty(this->vehicle);
MarkDirtyFocusedRoutePaths(this->vehicle);
}
}

@ -910,8 +910,7 @@ struct RefitWindow : public Window {
if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -922,8 +921,7 @@ struct RefitWindow : public Window {
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -933,8 +931,7 @@ struct RefitWindow : public Window {
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -2227,8 +2224,7 @@ private:
{
if (this->vli.type == VL_SHARED_ORDERS) {
const Vehicle *v = Vehicle::GetIfValid(this->vli.index);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
@ -2893,8 +2889,7 @@ struct VehicleDetailsWindow : Window {
if (!FocusWindowById(WC_VEHICLE_VIEW, this->window_number)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -3399,8 +3394,7 @@ struct VehicleDetailsWindow : Window {
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -3410,8 +3404,7 @@ struct VehicleDetailsWindow : Window {
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -3685,8 +3678,7 @@ public:
{
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number, false);
DeleteWindowById(WC_VEHICLE_REFIT, this->window_number, false);
@ -3699,8 +3691,7 @@ public:
if (HasFocusedVehicleChanged(this->window_number, previously_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}
@ -3710,8 +3701,7 @@ public:
if (HasFocusedVehicleChanged(this->window_number, newly_focused_window)) {
if (this->window_number != INVALID_VEHICLE) {
const Vehicle *v = Vehicle::Get(this->window_number);
MarkAllRoutePathsDirty(v);
MarkAllRouteStepsDirty(v);
MarkDirtyFocusedRoutePaths(v);
}
}
}

@ -341,8 +341,6 @@ static std::vector<Rect> _viewport_coverage_rects;
std::vector<Rect> _viewport_vehicle_normal_redraw_rects;
std::vector<Rect> _viewport_vehicle_map_redraw_rects;
RouteStepsMap _vp_route_steps;
RouteStepsMap _vp_route_steps_last_mark_dirty;
uint _vp_route_step_sprite_width = 0;
uint _vp_route_step_base_width = 0;
uint _vp_route_step_height_top = 0;
@ -370,8 +368,27 @@ struct DrawnPathRouteTileLine {
}
};
std::vector<DrawnPathRouteTileLine> _vp_route_paths;
std::vector<DrawnPathRouteTileLine> _vp_route_paths_last_mark_dirty;
struct ViewportRouteOverlay {
private:
RouteStepsMap route_steps;
RouteStepsMap route_steps_last_mark_dirty;
std::vector<DrawnPathRouteTileLine> route_paths;
std::vector<DrawnPathRouteTileLine> route_paths_last_mark_dirty;
bool PrepareVehicleRouteSteps(const Vehicle *veh);
bool PrepareVehicleRoutePaths(const Vehicle *veh);
void MarkAllRouteStepsDirty(const Vehicle *veh);
void MarkAllRoutePathsDirty(const Vehicle *veh);
public:
void PrepareVehicleRoute(const Vehicle *veh);
void DrawVehicleRouteSteps(const Viewport *vp);
void DrawVehicleRoutePath(const Viewport *vp, ViewportDrawerDynamic *vdd);
void MarkAllDirty(const Vehicle *veh);
inline bool HasVehicleRouteSteps() const { return !this->route_steps.empty(); }
};
static ViewportRouteOverlay _vp_focused_window_route_overlay;
static void MarkRoutePathsDirty(const std::vector<DrawnPathRouteTileLine> &lines);
@ -520,8 +537,7 @@ void InitializeWindowViewport(Window *w, int x, int y,
vp->follow_vehicle = (VehicleID)(follow_flags & 0xFFFFF);
veh = Vehicle::Get(vp->follow_vehicle);
pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
MarkAllRoutePathsDirty(veh);
MarkAllRouteStepsDirty(veh);
MarkDirtyFocusedRoutePaths(veh);
} else {
x = TileX(follow_flags) * TILE_SIZE;
y = TileY(follow_flags) * TILE_SIZE;
@ -2364,11 +2380,11 @@ static inline std::pair<const Order *, bool> GetFinalOrder(const Vehicle *veh, c
return std::pair<const Order *, bool>(order, is_conditional);
}
static bool ViewportMapPrepareVehicleRoute(const Vehicle * const veh)
bool ViewportRouteOverlay::PrepareVehicleRoutePaths(const Vehicle *veh)
{
if (!veh) return false;
if (veh == nullptr) return false;
if (_vp_route_paths.size() == 0) {
if (this->route_paths.empty()) {
TileIndex from_tile = GetLastValidOrderLocation(veh);
if (from_tile == INVALID_TILE) return false;
@ -2387,27 +2403,27 @@ static bool ViewportMapPrepareVehicleRoute(const Vehicle * const veh)
if (from_tile != INVALID_TILE) {
DrawnPathRouteTileLine path = { from_tile, to_tile, !conditional };
if (path.from_tile > path.to_tile) std::swap(path.from_tile, path.to_tile);
_vp_route_paths.push_back(path);
this->route_paths.push_back(path);
}
const OrderType ot = order->GetType();
if (ot == OT_GOTO_STATION || ot == OT_GOTO_DEPOT || ot == OT_GOTO_WAYPOINT || ot == OT_IMPLICIT) from_tile = to_tile;
}
// remove duplicate lines
std::sort(_vp_route_paths.begin(), _vp_route_paths.end());
_vp_route_paths.erase(std::unique(_vp_route_paths.begin(), _vp_route_paths.end()), _vp_route_paths.end());
std::sort(this->route_paths.begin(), this->route_paths.end());
this->route_paths.erase(std::unique(this->route_paths.begin(), this->route_paths.end()), this->route_paths.end());
}
return true;
}
/** Draw the route of a vehicle. */
static void ViewportMapDrawVehicleRoute(const Viewport *vp, ViewportDrawerDynamic *vdd)
void ViewportRouteOverlay::DrawVehicleRoutePath(const Viewport *vp, ViewportDrawerDynamic *vdd)
{
if (_vp_route_paths.empty()) return;
if (this->route_paths.empty()) return;
DrawPixelInfo dpi_for_text = vdd->MakeDPIForText();
for (const auto &iter : _vp_route_paths) {
for (const auto &iter : this->route_paths) {
const int from_tile_x = TileX(iter.from_tile) * TILE_SIZE + TILE_SIZE / 2;
const int from_tile_y = TileY(iter.from_tile) * TILE_SIZE + TILE_SIZE / 2;
Point from_pt = RemapCoords(from_tile_x, from_tile_y, 0);
@ -2435,6 +2451,11 @@ static void ViewportMapDrawVehicleRoute(const Viewport *vp, ViewportDrawerDynami
}
}
static void ViewportDrawVehicleRoutePath(const Viewport *vp, ViewportDrawerDynamic *vdd)
{
_vp_focused_window_route_overlay.DrawVehicleRoutePath(vp, vdd);
}
static inline void DrawRouteStep(const Viewport * const vp, const TileIndex tile, const RankOrderTypeList list)
{
if (tile == INVALID_TILE) return;
@ -2523,11 +2544,11 @@ static inline void DrawRouteStep(const Viewport * const vp, const TileIndex tile
}
}
static bool ViewportPrepareVehicleRouteSteps(const Vehicle * const veh)
bool ViewportRouteOverlay::PrepareVehicleRouteSteps(const Vehicle *veh)
{
if (!veh) return false;
if (veh == nullptr) return false;
if (_vp_route_steps.size() == 0) {
if (this->route_steps.empty()) {
/* Prepare data. */
int order_rank = 0;
for (const Order *order : veh->Orders()) {
@ -2535,7 +2556,7 @@ static bool ViewportPrepareVehicleRouteSteps(const Vehicle * const veh)
if (ViewportVehicleRouteShouldSkipOrder(order)) continue;
const TileIndex tile = order->GetLocation(veh, veh->type == VEH_AIRCRAFT);
if (tile == INVALID_TILE) continue;
_vp_route_steps[tile].push_back(std::pair<int, OrderType>(order_rank, order->GetType()));
this->route_steps[tile].push_back(std::pair<int, OrderType>(order_rank, order->GetType()));
}
}
@ -2546,52 +2567,65 @@ void ViewportPrepareVehicleRoute()
{
if (_settings_client.gui.show_vehicle_route_mode == 0) return;
if (!_settings_client.gui.show_vehicle_route_steps && !_settings_client.gui.show_vehicle_route) return;
const Vehicle * const veh = GetVehicleFromWindow(_focused_window);
if (_settings_client.gui.show_vehicle_route_steps && veh && ViewportPrepareVehicleRouteSteps(veh)) {
if (_vp_route_steps != _vp_route_steps_last_mark_dirty) {
for (RouteStepsMap::const_iterator cit = _vp_route_steps.begin(); cit != _vp_route_steps.end(); cit++) {
_vp_focused_window_route_overlay.PrepareVehicleRoute(GetVehicleFromWindow(_focused_window));
}
void ViewportRouteOverlay::PrepareVehicleRoute(const Vehicle *veh)
{
if (_settings_client.gui.show_vehicle_route_steps && veh != nullptr && this->PrepareVehicleRouteSteps(veh)) {
if (this->route_steps != this->route_steps_last_mark_dirty) {
for (RouteStepsMap::const_iterator cit = this->route_steps.begin(); cit != this->route_steps.end(); cit++) {
MarkRouteStepDirty(cit);
}
_vp_route_steps_last_mark_dirty = _vp_route_steps;
this->route_steps_last_mark_dirty = this->route_steps;
}
}
if (_settings_client.gui.show_vehicle_route) {
if (!veh) {
if (!_vp_route_paths.empty()) {
// make sure we remove any leftover paths
MarkRoutePathsDirty(_vp_route_paths);
_vp_route_paths.clear();
_vp_route_paths_last_mark_dirty.clear();
if (veh == nullptr) {
if (!this->route_paths.empty()) {
/* make sure we remove any leftover paths */
MarkRoutePathsDirty(this->route_paths);
this->route_paths.clear();
this->route_paths_last_mark_dirty.clear();
}
return;
} else {
if (ViewportMapPrepareVehicleRoute(veh)) {
if (_vp_route_paths_last_mark_dirty != _vp_route_paths) {
// make sure we're not drawing a partial path
MarkRoutePathsDirty(_vp_route_paths);
_vp_route_paths_last_mark_dirty = _vp_route_paths;
if (this->PrepareVehicleRoutePaths(veh)) {
if (this->route_paths_last_mark_dirty != this->route_paths) {
/* make sure we're not drawing a partial path */
MarkRoutePathsDirty(this->route_paths);
this->route_paths_last_mark_dirty = this->route_paths;
}
} else {
if (!_vp_route_paths.empty()) {
// make sure we remove any leftover paths
MarkRoutePathsDirty(_vp_route_paths);
_vp_route_paths.clear();
_vp_route_paths_last_mark_dirty.clear();
if (!this->route_paths.empty()) {
/* make sure we remove any leftover paths */
MarkRoutePathsDirty(this->route_paths);
this->route_paths.clear();
this->route_paths_last_mark_dirty.clear();
}
return;
}
}
}
}
/** Draw the route steps of a vehicle. */
static void ViewportDrawVehicleRouteSteps(const Viewport * const vp)
void ViewportRouteOverlay::DrawVehicleRouteSteps(const Viewport *vp)
{
for (RouteStepsMap::const_iterator cit = _vp_route_steps.begin(); cit != _vp_route_steps.end(); cit++) {
for (RouteStepsMap::const_iterator cit = this->route_steps.begin(); cit != this->route_steps.end(); cit++) {
DrawRouteStep(vp, cit->first, cit->second);
}
}
static bool ViewportDrawHasVehicleRouteSteps()
{
return _vp_focused_window_route_overlay.HasVehicleRouteSteps();
}
/** Draw the route steps of a vehicle. */
static void ViewportDrawVehicleRouteSteps(const Viewport * const vp)
{
_vp_focused_window_route_overlay.DrawVehicleRouteSteps(vp);
}
void ViewportDrawPlans(const Viewport *vp)
{
if (Plan::GetNumItems() == 0 && !(_current_plan && _current_plan->temp_line->tiles.size() > 1)) return;
@ -3800,7 +3834,7 @@ static void ViewportDoDrawPhase2(Viewport *vp, ViewportDrawerDynamic *vdd)
vp->overlay->Draw(&dp);
}
if (_settings_client.gui.show_vehicle_route_mode != 0 && _settings_client.gui.show_vehicle_route) ViewportMapDrawVehicleRoute(vp, vdd);
if (_settings_client.gui.show_vehicle_route_mode != 0 && _settings_client.gui.show_vehicle_route) ViewportDrawVehicleRoutePath(vp, vdd);
}
/* This is run in the main thread */
@ -3818,7 +3852,7 @@ static void ViewportDoDrawPhase3(Viewport *vp)
dp.top = UnScaleByZoom(_vdd->dpi.top, zoom);
ViewportDrawStrings(_vdd.get(), zoom, &_vdd->string_sprites_to_draw);
}
if (_settings_client.gui.show_vehicle_route_mode != 0 && _settings_client.gui.show_vehicle_route_steps && !_vp_route_steps.empty()) {
if (_settings_client.gui.show_vehicle_route_mode != 0 && _settings_client.gui.show_vehicle_route_steps && ViewportDrawHasVehicleRouteSteps()) {
dp.left = _vdd->offset_x + vp->left;
dp.top = _vdd->offset_y + vp->top;
ViewportDrawVehicleRouteSteps(vp);
@ -4159,14 +4193,14 @@ static void MarkRouteStepDirty(const TileIndex tile, uint order_nr)
}
}
void MarkAllRouteStepsDirty(const Vehicle *veh)
void ViewportRouteOverlay::MarkAllRouteStepsDirty(const Vehicle *veh)
{
ViewportPrepareVehicleRouteSteps(veh);
for (RouteStepsMap::const_iterator cit = _vp_route_steps.begin(); cit != _vp_route_steps.end(); cit++) {
this->PrepareVehicleRouteSteps(veh);
for (RouteStepsMap::const_iterator cit = this->route_steps.begin(); cit != this->route_steps.end(); ++cit) {
MarkRouteStepDirty(cit);
}
_vp_route_steps_last_mark_dirty.swap(_vp_route_steps);
_vp_route_steps.clear();
this->route_steps_last_mark_dirty.swap(this->route_steps);
this->route_steps.clear();
}
/**
@ -4354,24 +4388,34 @@ static void MarkRoutePathsDirty(const std::vector<DrawnPathRouteTileLine> &lines
}
}
void MarkAllRoutePathsDirty(const Vehicle *veh)
void ViewportRouteOverlay::MarkAllRoutePathsDirty(const Vehicle *veh)
{
if (_settings_client.gui.show_vehicle_route) {
ViewportMapPrepareVehicleRoute(veh);
this->PrepareVehicleRoutePaths(veh);
}
for (const auto &iter : _vp_route_paths) {
for (const auto &iter : this->route_paths) {
MarkTileLineDirty(iter.from_tile, iter.to_tile, VMDF_NOT_LANDSCAPE);
}
_vp_route_paths_last_mark_dirty.swap(_vp_route_paths);
_vp_route_paths.clear();
this->route_paths_last_mark_dirty.swap(this->route_paths);
this->route_paths.clear();
}
void ViewportRouteOverlay::MarkAllDirty(const Vehicle *veh)
{
this->MarkAllRoutePathsDirty(veh);
this->MarkAllRouteStepsDirty(veh);
}
void MarkDirtyFocusedRoutePaths(const Vehicle *veh)
{
_vp_focused_window_route_overlay.MarkAllDirty(veh);
}
void CheckMarkDirtyFocusedRoutePaths(const Vehicle *veh)
{
const Vehicle *focused_veh = GetVehicleFromWindow(_focused_window);
if (focused_veh != nullptr && veh == focused_veh) {
MarkAllRoutePathsDirty(veh);
MarkAllRouteStepsDirty(veh);
MarkDirtyFocusedRoutePaths(veh);
}
}
@ -4379,8 +4423,7 @@ void CheckMarkDirtyFocusedRoutePaths()
{
const Vehicle *focused_veh = GetVehicleFromWindow(_focused_window);
if (focused_veh != nullptr) {
MarkAllRoutePathsDirty(focused_veh);
MarkAllRouteStepsDirty(focused_veh);
MarkDirtyFocusedRoutePaths(focused_veh);
}
}

@ -41,10 +41,9 @@ void MarkAllViewportMapsDirty(int left, int top, int right, int bottom);
void MarkAllViewportMapLandscapesDirty();
void MarkWholeNonMapViewportsDirty();
void MarkAllViewportOverlayStationLinksDirty(const Station *st);
void MarkAllRouteStepsDirty(const Vehicle *veh);
void MarkViewportLineDirty(Viewport * const vp, const Point from_pt, const Point to_pt, const int block_radius, ViewportMarkDirtyFlags flags);
void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile, ViewportMarkDirtyFlags flags);
void MarkAllRoutePathsDirty(const Vehicle *veh);
void MarkDirtyFocusedRoutePaths(const Vehicle *veh);
void CheckMarkDirtyFocusedRoutePaths(const Vehicle *veh);
void CheckMarkDirtyFocusedRoutePaths();

Loading…
Cancel
Save