diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index cef9403570..17f0a32057 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -422,6 +422,7 @@ struct BuildRailToolbarWindow : Window { void Close() override { if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); + if (this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT)) SetViewportCatchmentWaypoint(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) CloseWindowById(WC_SCEN_LAND_GEN, 0, false); CloseWindowById(WC_SELECT_STATION, 0); this->Window::Close(); @@ -731,6 +732,7 @@ struct BuildRailToolbarWindow : Window { void OnPlaceObjectAbort() override { if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); + if (this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT)) SetViewportCatchmentWaypoint(nullptr, true); this->RaiseButtons(); this->DisableWidget(WID_RAT_REMOVE); @@ -757,6 +759,11 @@ struct BuildRailToolbarWindow : Window { return ES_NOT_HANDLED; } + void OnRealtimeTick(uint delta_ms) override + { + if (this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT)) CheckRedrawWaypointCoverage(this); + } + static HotkeyList hotkeys; }; @@ -2176,6 +2183,11 @@ struct BuildRailWaypointWindow : PickerWindowBase { this->InvalidateData(); } } + + void OnRealtimeTick(uint delta_ms) override + { + CheckRedrawWaypointCoverage(this); + } }; /* static */ QueryString BuildRailWaypointWindow::editbox(BuildRailWaypointWindow::FILTER_LENGTH * MAX_CHAR_LENGTH, BuildRailWaypointWindow::FILTER_LENGTH); diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 4a8cf9b958..236b8fc7dc 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -80,11 +80,12 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageTyp * Find stations adjacent to the current tile highlight area, so that existing coverage * area can be drawn. */ -static void FindStationsAroundSelection() +template +void FindStationsAroundSelection() { /* With distant join we don't know which station will be selected, so don't show any */ if (_ctrl_pressed) { - SetViewportCatchmentStation(nullptr, true); + SetViewportCatchmentSpecializedStation(nullptr, true); return; } @@ -95,15 +96,16 @@ static void FindStationsAroundSelection() uint x = TileX(location.tile); uint y = TileY(location.tile); - int max_c = 1; + /* Waypoints can only be built on existing rail tiles, so don't extend area if not highlighting a rail tile. */ + int max_c = T::EXPECTED_FACIL == FACIL_WAYPOINT && !IsTileType(location.tile, MP_RAILWAY) ? 0 : 1; TileArea ta(TileXY(std::max(0, x - max_c), std::max(0, y - max_c)), TileXY(std::min(Map::MaxX(), x + location.w + max_c), std::min(Map::MaxY(), y + location.h + max_c))); - Station *adjacent = nullptr; + T *adjacent = nullptr; /* Direct loop instead of ForAllStationsAroundTiles as we are not interested in catchment area */ for (TileIndex tile : ta) { if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) { - Station *st = Station::GetByTile(tile); + T *st = T::GetByTile(tile); if (st == nullptr) continue; if (adjacent != nullptr && st != adjacent) { /* Multiple nearby, distant join is required. */ @@ -113,7 +115,7 @@ static void FindStationsAroundSelection() adjacent = st; } } - SetViewportCatchmentStation(adjacent, true); + SetViewportCatchmentSpecializedStation(adjacent, true); } /** @@ -135,7 +137,25 @@ void CheckRedrawStationCoverage(const Window *w) w->SetDirty(); if (_settings_client.gui.station_show_coverage && _thd.drawstyle == HT_RECT) { - FindStationsAroundSelection(); + FindStationsAroundSelection(); + } + } +} + +void CheckRedrawWaypointCoverage(const Window *w) +{ + /* Test if ctrl state changed */ + static bool _last_ctrl_pressed; + if (_ctrl_pressed != _last_ctrl_pressed) { + _thd.dirty = 0xff; + _last_ctrl_pressed = _ctrl_pressed; + } + + if (_thd.dirty & 1) { + _thd.dirty &= ~1; + + if (_thd.drawstyle == HT_RECT) { + FindStationsAroundSelection(); } } } @@ -2255,7 +2275,7 @@ struct SelectStationWindow : Window { void Close() override { - if (_settings_client.gui.station_show_coverage) SetViewportCatchmentStation(nullptr, true); + SetViewportCatchmentSpecializedStation(nullptr, true); _thd.freeze = false; this->Window::Close(); @@ -2342,15 +2362,15 @@ struct SelectStationWindow : Window { void OnMouseOver(Point pt, int widget) override { - if (widget != WID_JS_PANEL || T::EXPECTED_FACIL == FACIL_WAYPOINT) { - SetViewportCatchmentStation(nullptr, true); + if (widget != WID_JS_PANEL) { + SetViewportCatchmentSpecializedStation(nullptr, true); return; } /* Show coverage area of station under cursor */ auto it = this->vscroll->GetScrolledItemFromWidget(_stations_nearby_list, pt.y, this, WID_JS_PANEL, WidgetDimensions::scaled.framerect.top); - const Station *st = it == _stations_nearby_list.end() || *it == NEW_STATION ? nullptr : Station::Get(*it); - SetViewportCatchmentStation(st, true); + const T *st = it == _stations_nearby_list.end() || *it == NEW_STATION ? nullptr : T::Get(*it); + SetViewportCatchmentSpecializedStation(st, true); } }; diff --git a/src/station_gui.h b/src/station_gui.h index 503f2f88ab..009bcd7bb9 100644 --- a/src/station_gui.h +++ b/src/station_gui.h @@ -25,6 +25,7 @@ enum StationCoverageType { int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageType sct, int rad, bool supplies); void CheckRedrawStationCoverage(const Window *w); +void CheckRedrawWaypointCoverage(const Window *w); using StationPickerCmdProc = std::function; diff --git a/src/viewport.cpp b/src/viewport.cpp index d76ad65475..30f69ba7c7 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -992,7 +992,8 @@ enum TileHighlightType { }; const Station *_viewport_highlight_station; ///< Currently selected station for coverage area highlight -const Town *_viewport_highlight_town; ///< Currently selected town for coverage area highlight +const Waypoint *_viewport_highlight_waypoint; ///< Currently selected waypoint for coverage area highlight +const Town *_viewport_highlight_town; ///< Currently selected town for coverage area highlight /** * Get tile highlight type of coverage area for a given tile. @@ -1005,6 +1006,9 @@ static TileHighlightType GetTileHighlightType(TileIndex t) if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_station->index) return THT_WHITE; if (_viewport_highlight_station->TileIsInCatchment(t)) return THT_BLUE; } + if (_viewport_highlight_waypoint != nullptr) { + if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_waypoint->index) return THT_BLUE; + } if (_viewport_highlight_town != nullptr) { if (IsTileType(t, MP_HOUSE)) { @@ -3511,11 +3515,18 @@ void MarkCatchmentTilesDirty() } } } + if (_viewport_highlight_waypoint != nullptr) { + if (!_viewport_highlight_waypoint->IsInUse()) { + _viewport_highlight_waypoint = nullptr; + } + MarkWholeScreenDirty(); + } } static void SetWindowDirtyForViewportCatchment() { if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index); + if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index); if (_viewport_highlight_town != nullptr) SetWindowDirty(WC_TOWN_VIEW, _viewport_highlight_town->index); } @@ -3523,6 +3534,7 @@ static void ClearViewportCatchment() { MarkCatchmentTilesDirty(); _viewport_highlight_station = nullptr; + _viewport_highlight_waypoint = nullptr; _viewport_highlight_town = nullptr; } @@ -3546,6 +3558,26 @@ void SetViewportCatchmentStation(const Station *st, bool sel) if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index); } +/** + * Select or deselect waypoint for coverage area highlight. + * Selecting a waypoint will deselect a town. + * @param *wp Waypoint in question + * @param sel Select or deselect given waypoint + */ +void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel) +{ + SetWindowDirtyForViewportCatchment(); + if (sel && _viewport_highlight_waypoint != wp) { + ClearViewportCatchment(); + _viewport_highlight_waypoint = wp; + MarkCatchmentTilesDirty(); + } else if (!sel && _viewport_highlight_waypoint == wp) { + MarkCatchmentTilesDirty(); + _viewport_highlight_waypoint = nullptr; + } + if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index); +} + /** * Select or deselect town for coverage area highlight. * Selecting a town will deselect a station. diff --git a/src/viewport_func.h b/src/viewport_func.h index 20bf5837c1..651fe44573 100644 --- a/src/viewport_func.h +++ b/src/viewport_func.h @@ -95,10 +95,27 @@ static inline void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset = Point GetViewportStationMiddle(const Viewport *vp, const Station *st); struct Station; +struct Waypoint; struct Town; void SetViewportCatchmentStation(const Station *st, bool sel); +void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel); void SetViewportCatchmentTown(const Town *t, bool sel); void MarkCatchmentTilesDirty(); +template +void SetViewportCatchmentSpecializedStation(const T *st, bool sel); + +template<> +inline void SetViewportCatchmentSpecializedStation(const Station *st, bool sel) +{ + SetViewportCatchmentStation(st, sel); +} + +template<> +inline void SetViewportCatchmentSpecializedStation(const Waypoint *st, bool sel) +{ + SetViewportCatchmentWaypoint(st, sel); +} + #endif /* VIEWPORT_FUNC_H */