diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 526c5c16a2..31194b6362 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -41,6 +41,24 @@ #include "safeguards.h" +struct StationTypeFilter +{ + using StationType = Station; + + static bool IsValidID(StationID id) { return Station::IsValidID(id); } + static bool IsValidBaseStation(const BaseStation *st) { return Station::IsExpected(st); } + static constexpr bool IsWaypoint() { return false; } +}; + +struct WaypointTypeFilter +{ + using StationType = Waypoint; + + static bool IsValidID(StationID id) { return Waypoint::IsValidID(id); } + static bool IsValidBaseStation(const BaseStation *st) { return Waypoint::IsExpected(st); } + static constexpr bool IsWaypoint() { return true; } +}; + /** * Calculates and draws the accepted or supplied cargo around the selected tile(s) * @param left x position where the string is to be drawn @@ -87,7 +105,7 @@ void FindStationsAroundSelection() { /* With distant join we don't know which station will be selected, so don't show any */ if (_ctrl_pressed) { - SetViewportCatchmentSpecializedStation(nullptr, true); + SetViewportCatchmentSpecializedStation(nullptr, true); return; } @@ -96,9 +114,9 @@ void FindStationsAroundSelection() /* If the current tile is already a station, then it must be the nearest station. */ if (IsTileType(location.tile, MP_STATION) && GetTileOwner(location.tile) == _local_company) { - T *st = T::GetByTile(location.tile); - if (st != nullptr) { - SetViewportCatchmentSpecializedStation(st, true); + typename T::StationType *st = T::StationType::GetByTile(location.tile); + if (st != nullptr && T::IsValidBaseStation(st)) { + SetViewportCatchmentSpecializedStation(st, true); return; } } @@ -108,16 +126,16 @@ void FindStationsAroundSelection() uint y = TileY(location.tile); /* 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; + int max_c = T::IsWaypoint() && !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))); - T *adjacent = nullptr; + typename T::StationType *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) { - T *st = T::GetByTile(tile); - if (st == nullptr) continue; + typename T::StationType *st = T::StationType::GetByTile(tile); + if (st == nullptr || !T::IsValidBaseStation(st)) continue; if (adjacent != nullptr && st != adjacent) { /* Multiple nearby, distant join is required. */ adjacent = nullptr; @@ -126,7 +144,7 @@ void FindStationsAroundSelection() adjacent = st; } } - SetViewportCatchmentSpecializedStation(adjacent, true); + SetViewportCatchmentSpecializedStation(adjacent, true); } /** @@ -148,7 +166,7 @@ void CheckRedrawStationCoverage(const Window *w) w->SetDirty(); if (_settings_client.gui.station_show_coverage && _thd.drawstyle == HT_RECT) { - FindStationsAroundSelection(); + FindStationsAroundSelection(); } } } @@ -166,7 +184,7 @@ void CheckRedrawWaypointCoverage(const Window *) _thd.dirty &= ~1; if (_thd.drawstyle == HT_RECT) { - FindStationsAroundSelection(); + FindStationsAroundSelection(); } } } @@ -2172,7 +2190,7 @@ static std::vector _stations_nearby_list; * station spread. * @param tile Tile just being checked * @param user_data Pointer to TileArea context - * @tparam T the type of station to look for + * @tparam T the station filter type */ template static bool AddNearbyStation(TileIndex tile, void *user_data) @@ -2197,7 +2215,7 @@ static bool AddNearbyStation(TileIndex tile, void *user_data) /* This station is (likely) a waypoint */ if (!T::IsValidID(sid)) return false; - T *st = T::Get(sid); + BaseStation *st = BaseStation::Get(sid); if (st->owner != _local_company || std::find(_stations_nearby_list.begin(), _stations_nearby_list.end(), sid) != _stations_nearby_list.end()) return false; if (st->rect.BeforeAddRect(ctx->tile, ctx->w, ctx->h, StationRect::ADD_TEST).Succeeded()) { @@ -2214,10 +2232,10 @@ static bool AddNearbyStation(TileIndex tile, void *user_data) * @param ta Base tile area of the to-be-built station * @param distant_join Search for adjacent stations (false) or stations fully * within station spread - * @tparam T the type of station to look for + * @tparam T the station filter type, for stations to look for */ template -static const T *FindStationsNearby(TileArea ta, bool distant_join) +static const BaseStation *FindStationsNearby(TileArea ta, bool distant_join) { TileArea ctx = ta; @@ -2227,12 +2245,12 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join) /* Check the inside, to return, if we sit on another station */ for (TileIndex t : ta) { - if (t < Map::Size() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return T::GetByTile(t); + if (t < Map::Size() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return BaseStation::GetByTile(t); } /* Look for deleted stations */ for (const BaseStation *st : BaseStation::Iterate()) { - if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) { + if (T::IsValidBaseStation(st) && !st->IsInUse() && st->owner == _local_company) { /* Include only within station spread (yes, it is strictly less than) */ if (std::max(DistanceMax(ta.tile, st->xy), DistanceMax(TileAddXY(ta.tile, ta.w - 1, ta.h - 1), st->xy)) < _settings_game.station.station_spread) { _deleted_stations_nearby.push_back({st->xy, st->index}); @@ -2275,7 +2293,7 @@ static constexpr NWidgetPart _nested_select_station_widgets[] = { /** * Window for selecting stations/waypoints to (distant) join to. - * @tparam T The type of station to join with + * @tparam T The station filter type, for stations to join with */ template struct SelectStationWindow : Window { @@ -2290,7 +2308,7 @@ struct SelectStationWindow : Window { { this->CreateNestedTree(); this->vscroll = this->GetScrollbar(WID_JS_SCROLLBAR); - this->GetWidget(WID_JS_CAPTION)->widget_data = T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CAPTION : STR_JOIN_STATION_CAPTION; + this->GetWidget(WID_JS_CAPTION)->widget_data = T::IsWaypoint() ? STR_JOIN_WAYPOINT_CAPTION : STR_JOIN_STATION_CAPTION; this->FinishInitNested(0); this->OnInvalidateData(0); @@ -2299,7 +2317,7 @@ struct SelectStationWindow : Window { void Close([[maybe_unused]] int data = 0) override { - SetViewportCatchmentSpecializedStation(nullptr, true); + SetViewportCatchmentSpecializedStation(nullptr, true); _thd.freeze = false; this->Window::Close(); @@ -2310,13 +2328,13 @@ struct SelectStationWindow : Window { if (widget != WID_JS_PANEL) return; /* Determine the widest string */ - Dimension d = GetStringBoundingBox(T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION); + Dimension d = GetStringBoundingBox(T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION); for (const auto &station : _stations_nearby_list) { if (station == NEW_STATION) continue; - const T *st = T::Get(station); + const BaseStation *st = BaseStation::Get(station); SetDParam(0, st->index); SetDParam(1, st->facilities); - d = maxdim(d, GetStringBoundingBox(T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION)); + d = maxdim(d, GetStringBoundingBox(T::IsWaypoint() ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION)); } resize.height = d.height; @@ -2334,12 +2352,12 @@ struct SelectStationWindow : Window { auto [first, last] = this->vscroll->GetVisibleRangeIterators(_stations_nearby_list); for (auto it = first; it != last; ++it, tr.top += this->resize.step_height) { if (*it == NEW_STATION) { - DrawString(tr, T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION); + DrawString(tr, T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION); } else { - const T *st = T::Get(*it); + const BaseStation *st = BaseStation::Get(*it); SetDParam(0, st->index); SetDParam(1, st->facilities); - DrawString(tr, T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION); + DrawString(tr, T::IsWaypoint() ? STR_STATION_LIST_WAYPOINT : STR_STATION_LIST_STATION); } } @@ -2388,14 +2406,14 @@ struct SelectStationWindow : Window { void OnMouseOver([[maybe_unused]] Point pt, WidgetID widget) override { if (widget != WID_JS_PANEL) { - SetViewportCatchmentSpecializedStation(nullptr, true); + 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 T *st = it == _stations_nearby_list.end() || *it == NEW_STATION ? nullptr : T::Get(*it); - SetViewportCatchmentSpecializedStation(st, true); + const typename T::StationType *st = it == _stations_nearby_list.end() || *it == NEW_STATION ? nullptr : T::StationType::Get(*it); + SetViewportCatchmentSpecializedStation(st, true); } }; @@ -2411,7 +2429,7 @@ static WindowDesc _select_station_desc( * Check whether we need to show the station selection window. * @param cmd Command to build the station. * @param ta Tile area of the to-be-built station - * @tparam T the type of station + * @tparam T the station filter type * @return whether we need to show the station selection window. */ template @@ -2438,7 +2456,7 @@ static bool StationJoinerNeeded(TileArea ta, const StationPickerCmdProc &proc) /* Test for adjacent station or station below selection. * If adjacent-stations is disabled and we are building next to a station, do not show the selection window. * but join the other station immediately. */ - const T *st = FindStationsNearby(ta, false); + const BaseStation *st = FindStationsNearby(ta, false); return st == nullptr && (_settings_game.station.adjacent_stations || std::any_of(std::begin(_stations_nearby_list), std::end(_stations_nearby_list), [](StationID s) { return s != NEW_STATION; })); } @@ -2466,7 +2484,7 @@ void ShowSelectBaseStationIfNeeded(TileArea ta, StationPickerCmdProc&& proc) */ void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc) { - ShowSelectBaseStationIfNeeded(ta, std::move(proc)); + ShowSelectBaseStationIfNeeded(ta, std::move(proc)); } /** @@ -2476,5 +2494,5 @@ void ShowSelectStationIfNeeded(TileArea ta, StationPickerCmdProc proc) */ void ShowSelectWaypointIfNeeded(TileArea ta, StationPickerCmdProc proc) { - ShowSelectBaseStationIfNeeded(ta, std::move(proc)); + ShowSelectBaseStationIfNeeded(ta, std::move(proc)); }