From 860cf98042153cc16187dac4da430dad142cfe07 Mon Sep 17 00:00:00 2001 From: dP Date: Thu, 10 Jul 2025 15:30:48 +0500 Subject: [PATCH] Use new tool highlight for station coverage button --- src/citymania/cm_highlight.cpp | 2 +- src/citymania/cm_station_gui.cpp | 221 +++++++++++++++++++------------ src/citymania/cm_station_gui.hpp | 13 +- src/station_gui.cpp | 7 +- 4 files changed, 149 insertions(+), 94 deletions(-) diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index 5cae50f24e..53684c87ee 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -2486,7 +2486,7 @@ void UpdateActiveTool() { auto tile = pt.x == -1 ? INVALID_TILE : TileVirtXY(pt.x, pt.y); ToolGUIInfo info; - if (citymania::StationBuildTool::active_highlight.has_value()) { + if (citymania::HasSelectedStationHighlight()) { info = GetSelectedStationGUIInfo(); } else if (_at.tool != nullptr) { _at.tool->Update(pt, tile); diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index d1dfec930a..0dab2b31ff 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -29,6 +29,7 @@ #include "../town.h" #include "../viewport_func.h" #include "../viewport_kdtree.h" +#include "../window_func.h" // SetWindowDirty #include "../window_gui.h" #include "../zoom_type.h" #include "../zoom_func.h" @@ -572,16 +573,50 @@ extern DiagDirection AddAutodetectionRotation(DiagDirection ddir); // cm_highli // if (this->station_to_join == station->index) this->station_to_join = INVALID_STATION; // } +// Non-tool station highlight management (coverage area and picker selection) + +enum class StationHighlightMode { + None, + Picker, + Coverage +}; + +std::optional _active_highlight_object = std::nullopt; +StationID _selected_station = INVALID_STATION; +StationHighlightMode _station_highlight_mode = StationHighlightMode::None; + void SetSelectedStationToJoin(StationID station_id) { - StationBuildTool::current_selected_station = station_id; + _selected_station = station_id; UpdateActiveTool(); } -void ResetJoinStationHighlight() { - StationBuildTool::active_highlight = std::nullopt; - SetSelectedStationToJoin(INVALID_STATION); +void ResetSelectedStationToJoin() { + _station_highlight_mode = StationHighlightMode::None; + UpdateActiveTool(); } +void SetHighlightCoverageStation(Station *station, bool sel) { + if (_station_highlight_mode == StationHighlightMode::Picker) return; + SetWindowDirty(WC_STATION_VIEW, _selected_station); + if (station == nullptr || !sel) { + _station_highlight_mode = StationHighlightMode::None; + } else { + _selected_station = station->index; + _station_highlight_mode = StationHighlightMode::Coverage; + } + SetWindowDirty(WC_STATION_VIEW, _selected_station); + UpdateActiveTool(); +} + +static void ResetHighlightCoverageStation() { + SetHighlightCoverageStation(nullptr, false); +} + +bool IsHighlightCoverageStation(const Station *station) { + if (_station_highlight_mode != StationHighlightMode::Coverage) return false; + if (station == nullptr) return false; + return station->index == _selected_station; +} void OnStationRemoved(const Station *station) { // if (_last_built_station == station) _last_built_station = nullptr; @@ -589,19 +624,105 @@ void OnStationRemoved(const Station *station) { StationBuildTool::station_to_join = INVALID_STATION; UpdateActiveTool(); } - if (StationBuildTool::current_selected_station == station->index) { - StationBuildTool::current_selected_station = INVALID_STATION; + if (_selected_station == station->index) { + _selected_station = INVALID_STATION; + if (_station_highlight_mode == StationHighlightMode::Coverage) { + _station_highlight_mode = StationHighlightMode::None; + SetWindowDirty(WC_STATION_VIEW, _selected_station); + } UpdateActiveTool(); } // TODO? // if (GetActiveTool() != nullptr) GetActiveTool()->OnStationRemoved(station); } +static void SetActiveHighlightObject(std::optional &ohl) { + _active_highlight_object = ohl; + if (_active_highlight_object.has_value()) _active_highlight_object->UpdateTiles(); + if (_station_highlight_mode == StationHighlightMode::Coverage) + SetWindowDirty(WC_STATION_VIEW, _selected_station); + _station_highlight_mode = StationHighlightMode::Picker; +} + void AbortStationPlacement() { // TODO is it necessary? // SetHighlightStationToJoin(station=nullptr, with_area=false); } +bool HasSelectedStationHighlight() { + return _station_highlight_mode != StationHighlightMode::None; +} + +static HighlightMap PrepareHighilightMap(Station *st_join, std::optional ohl, SpriteID pal, bool show_join_area, bool show_coverage, StationCoverageType sct, uint rad) { + bool add_current = true; // FIXME + + auto hlmap = ohl.has_value() ? ohl->GetHighlightMap(pal) : HighlightMap{}; + TileArea join_area; + std::set coverage_area; + + if (show_join_area && st_join != nullptr) { + join_area = GetStationJoinArea(st_join->index); + hlmap.AddTileArea(join_area, CM_PALETTE_TINT_CYAN); + } + + if (show_coverage && st_join != nullptr) { + // Add joining station coverage + for (auto t : st_join->catchment_tiles) { + auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE; + hlmap.Add(t, ObjectTileHighlight::make_tint(pal)); + coverage_area.insert(t); + } + } + + auto area = ohl.has_value() ? ohl->GetArea() : std::nullopt; + if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED; + std::optional rad_area = std::nullopt; + if (area.has_value()) { + auto xarea = area.value(); + xarea.Expand(rad); + xarea.ClampToMap(); + rad_area = xarea; + } + if (show_coverage && add_current && rad_area.has_value()) { + // Add current station coverage + for (auto t : rad_area.value()) { + auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE; + hlmap.Add(t, ObjectTileHighlight::make_tint(pal)); + coverage_area.insert(t); + } + } + + if (show_coverage) { + hlmap.AddTilesBorder(coverage_area, CM_PALETTE_TINT_WHITE); + } + + if (st_join != nullptr) { + // Highlight joining station blue + TileArea ta(TileXY(st_join->rect.left, st_join->rect.top), TileXY(st_join->rect.right, st_join->rect.bottom)); + for (TileIndex t : ta) { + if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != st_join->index) continue; + hlmap.Add(t, ObjectTileHighlight::make_struct_tint(CM_PALETTE_TINT_BLUE)); + } + } + + return hlmap; +} + +ToolGUIInfo GetSelectedStationGUIInfo() { + if (_station_highlight_mode == StationHighlightMode::None) return {}; + auto st = Station::GetIfValid(_selected_station); + + auto hlmap = PrepareHighilightMap( + st, + _station_highlight_mode == StationHighlightMode::Picker ? _active_highlight_object : std::nullopt, + CM_PALETTE_TINT_WHITE, + false, + _station_highlight_mode == StationHighlightMode::Coverage, + SCT_ALL, + 0 + ); + return {hlmap, {}, {}}; +} // --- Action base class --- void Action::OnStationRemoved(const Station *) {} @@ -651,62 +772,6 @@ ToolGUIInfo RemoveAction::GetGUIInfo() { template void RemoveAction::OnStationRemoved(const Station *) {} -static HighlightMap PrepareHighilightMap(Station *st_join, ObjectHighlight &ohl, SpriteID pal, bool show_join_area, StationCoverageType sct, uint rad) { - bool add_current = true; // FIXME - bool show_coverage = (rad > 0); - - auto hlmap = ohl.GetHighlightMap(pal); - TileArea join_area; - std::set coverage_area; - - if (show_join_area && st_join != nullptr) { - join_area = GetStationJoinArea(st_join->index); - hlmap.AddTileArea(join_area, CM_PALETTE_TINT_CYAN); - } - - if (show_coverage && st_join != nullptr) { - // Add joining station coverage - for (auto t : st_join->catchment_tiles) { - auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE; - hlmap.Add(t, ObjectTileHighlight::make_tint(pal)); - coverage_area.insert(t); - } - } - - auto area = ohl.GetArea(); - if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED; - std::optional rad_area = std::nullopt; - if (area.has_value()) { - auto xarea = area.value(); - xarea.Expand(rad); - xarea.ClampToMap(); - rad_area = xarea; - } - if (show_coverage && add_current && rad_area.has_value()) { - // Add current station coverage - for (auto t : rad_area.value()) { - auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE; - hlmap.Add(t, ObjectTileHighlight::make_tint(pal)); - coverage_area.insert(t); - } - } - - if (show_coverage) { - hlmap.AddTilesBorder(coverage_area, CM_PALETTE_TINT_WHITE); - } - - if (st_join != nullptr) { - // Highlight joining station blue - TileArea ta(TileXY(st_join->rect.left, st_join->rect.top), TileXY(st_join->rect.right, st_join->rect.bottom)); - for (TileIndex t : ta) { - if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != st_join->index) continue; - hlmap.Add(t, ObjectTileHighlight::make_struct_tint(CM_PALETTE_TINT_BLUE)); - } - } - - return hlmap; -} - ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, up cmd, StationCoverageType sct, uint rad) { if (!cmd || !ohl.has_value()) return {}; ohl.value().UpdateTiles(); @@ -720,8 +785,9 @@ ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, ohl.value(), cost.Succeeded() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP, true, + show_coverage, sct, - show_coverage ? rad : 0 + rad ); // Prepare build overlay @@ -834,22 +900,6 @@ ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, return {hlmap, data, cost}; } -ToolGUIInfo GetSelectedStationGUIInfo() { - if (!StationBuildTool::active_highlight.has_value()) return {}; - auto &ohl = StationBuildTool::active_highlight.value(); - // TODO maybe update or none at all? - ohl.UpdateTiles(); - auto hlmap = PrepareHighilightMap( - Station::GetIfValid(StationBuildTool::current_selected_station), - ohl, - CM_PALETTE_TINT_WHITE, - false, - SCT_ALL, - 0 - ); - return {hlmap, {}, {}}; -} - // --- SizedPlacementAction --- template void SizedPlacementAction::Update(Point, TileIndex tile) { @@ -972,8 +1022,6 @@ void StationSelectAction::OnStationRemoved(const Station *station) { // --- StationBuildTool --- StationID StationBuildTool::station_to_join = INVALID_STATION; -StationID StationBuildTool::current_selected_station = INVALID_STATION; -std::optional StationBuildTool::active_highlight = std::nullopt; TileArea GetCommandArea(const up &cmd) { if (auto rail_cmd = dynamic_cast(cmd.get())) { @@ -994,11 +1042,15 @@ TileArea GetCommandArea(const up &cmd) { NOT_REACHED(); } + +StationBuildTool::StationBuildTool() { + ResetHighlightCoverageStation(); +} + template bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) { if (UseImprovedStationJoin()) { auto cmd = handler->GetCommand(arg, StationBuildTool::station_to_join); - StationBuildTool::active_highlight = std::nullopt; return cmd ? cmd->post(callback) : false; } @@ -1012,16 +1064,16 @@ bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback if (test) { return cmd->test().Succeeded(); } else { - StationBuildTool::active_highlight = std::nullopt; + ResetSelectedStationToJoin(); return cmd->post(callback); } }; auto ohl = handler->GetObjectHighlight(arg); if (!ohl.has_value()) return false; - StationBuildTool::active_highlight = ohl; auto area = ohl->GetArea(); if (!area.has_value()) return false; + SetActiveHighlightObject(ohl); ShowSelectStationIfNeeded(area.value(), proc); return true; } @@ -1439,5 +1491,4 @@ template class DragNDropPlacementAction; template class SizedPlacementAction; - } // namespace citymania diff --git a/src/citymania/cm_station_gui.hpp b/src/citymania/cm_station_gui.hpp index a2930df0fc..7da44401a5 100644 --- a/src/citymania/cm_station_gui.hpp +++ b/src/citymania/cm_station_gui.hpp @@ -48,7 +48,13 @@ DiagDirection AutodetectRoadObjectDirection(TileIndex tile, Point pt, RoadType r DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area, Point pt, RoadType roadtype); DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt); void SetSelectedStationToJoin(StationID station_id); -void ResetJoinStationHighlight(); +void ResetSelectedStationToJoin(); + +void SetHighlightCoverageStation(Station *station, bool sel); +bool IsHighlightCoverageStation(const Station *station); + +bool HasSelectedStationHighlight(); +ToolGUIInfo GetSelectedStationGUIInfo(); struct OverlayParams { @@ -177,8 +183,6 @@ public: class StationBuildTool : public Tool { public: static StationID station_to_join; - static StationID current_selected_station; - static std::optional active_highlight; class StationSelectHandler : public citymania::StationSelectHandler { public: @@ -188,6 +192,7 @@ public: void SelectStationToJoin(StationID station_id) override { this->tool.SelectStationToJoin(station_id); }; }; + StationBuildTool(); ~StationBuildTool() override = default; void SelectStationToJoin(StationID station_id) { StationBuildTool::station_to_join = station_id; }; ToolGUIInfo GetGUIInfo() override { @@ -355,8 +360,6 @@ private: Mode mode; }; -ToolGUIInfo GetSelectedStationGUIInfo(); - } // namespace citymania #endif diff --git a/src/station_gui.cpp b/src/station_gui.cpp index de2fda931a..b9e96eb818 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1452,7 +1452,7 @@ struct StationViewWindow : public Window { extern const Station *_viewport_highlight_station; this->SetWidgetDisabledState(WID_SV_CATCHMENT, st->facilities == FACIL_NONE); - this->SetWidgetLoweredState(WID_SV_CATCHMENT, _viewport_highlight_station == st); + this->SetWidgetLoweredState(WID_SV_CATCHMENT, citymania::IsHighlightCoverageStation(st)); this->DrawWidgets(); @@ -1946,7 +1946,8 @@ struct StationViewWindow : public Window { break; case WID_SV_CATCHMENT: - SetViewportCatchmentStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT)); + citymania::SetHighlightCoverageStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT)); + // SetViewportCatchmentStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT)); break; case WID_SV_LOCATION: @@ -2340,7 +2341,7 @@ struct SelectStationWindow : WindowPopup { void Close([[maybe_unused]] int data = 0) override { if constexpr (std::is_same_v) SetViewportCatchmentSpecializedStation(nullptr, true); - else citymania::ResetJoinStationHighlight(); + else citymania::ResetSelectedStationToJoin(); _thd.freeze = false; this->Window::Close();