From 81f0f9740690d0f3307d946d848375e269c8d2ee Mon Sep 17 00:00:00 2001 From: peter1138 Date: Sat, 30 Mar 2019 16:58:40 +0000 Subject: [PATCH] Feature: Add existing station coverage area display when placing new station parts. --- src/airport_gui.cpp | 3 ++ src/dock_gui.cpp | 3 ++ src/rail_gui.cpp | 3 ++ src/road_gui.cpp | 3 ++ src/station_gui.cpp | 72 ++++++++++++++++++++++++++++++++++++++++ src/tilehighlight_type.h | 2 ++ src/viewport.cpp | 2 ++ 7 files changed, 88 insertions(+) diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 8e436f1cb5..0fff03a3cf 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -79,6 +79,7 @@ struct BuildAirToolbarWindow : Window { ~BuildAirToolbarWindow() { + if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -143,6 +144,8 @@ struct BuildAirToolbarWindow : Window { void OnPlaceObjectAbort() override { + if (this->IsWidgetLowered(WID_AT_AIRPORT)) SetViewportCatchmentStation(nullptr, true); + this->RaiseButtons(); DeleteWindowById(WC_BUILD_STATION, TRANSPORT_AIR); diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 95989dc035..d74c6d2caf 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -105,6 +105,7 @@ struct BuildDocksToolbarWindow : Window { ~BuildDocksToolbarWindow() { + if (this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -248,6 +249,8 @@ struct BuildDocksToolbarWindow : Window { void OnPlaceObjectAbort() override { + if (this->IsWidgetLowered(WID_DT_STATION)) SetViewportCatchmentStation(nullptr, true); + this->RaiseButtons(); DeleteWindowById(WC_BUILD_STATION, TRANSPORT_WATER); diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 54aaf61f62..6d70686fde 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -432,6 +432,7 @@ struct BuildRailToolbarWindow : Window { ~BuildRailToolbarWindow() { + if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -743,6 +744,8 @@ struct BuildRailToolbarWindow : Window { void OnPlaceObjectAbort() override { + if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) SetViewportCatchmentStation(nullptr, true); + this->RaiseButtons(); this->DisableWidget(WID_RAT_REMOVE); this->SetWidgetDirty(WID_RAT_REMOVE); diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 27c8fe8e7f..78f5377dae 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -327,6 +327,7 @@ struct BuildRoadToolbarWindow : Window { ~BuildRoadToolbarWindow() { + if (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION)) SetViewportCatchmentStation(nullptr, true); if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false); } @@ -545,6 +546,8 @@ struct BuildRoadToolbarWindow : Window { void OnPlaceObjectAbort() override { + if (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION)) SetViewportCatchmentStation(nullptr, true); + this->RaiseButtons(); this->SetWidgetsDisabledState(true, WID_ROT_REMOVE, diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 1cc6a126ff..31da16238e 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -80,6 +80,46 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageTyp return DrawStringMultiLine(left, right, top, INT32_MAX, supplies ? STR_STATION_BUILD_SUPPLIES_CARGO : STR_STATION_BUILD_ACCEPTS_CARGO); } +/** + * Find stations adjacent to the current tile highlight area, so that existing coverage + * area can be drawn. + */ +static 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); + return; + } + + /* Tile area for TileHighlightData */ + TileArea location(TileVirtXY(_thd.pos.x, _thd.pos.y), _thd.size.x / TILE_SIZE - 1, _thd.size.y / TILE_SIZE - 1); + + /* Extended area by one tile */ + uint x = TileX(location.tile); + uint y = TileY(location.tile); + + int max_c = 1; + TileArea ta(TileXY(max(0, x - max_c), max(0, y - max_c)), TileXY(min(MapMaxX(), x + location.w + max_c), min(MapMaxY(), y + location.h + max_c))); + + Station *adjacent = nullptr; + + /* Direct loop instead of FindStationsAroundTiles as we are not interested in catchment area */ + TILE_AREA_LOOP(tile, ta) { + if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) { + Station *st = Station::GetByTile(tile); + if (st == nullptr) continue; + if (adjacent != nullptr && st != adjacent) { + /* Multiple nearby, distant join is required. */ + adjacent = nullptr; + break; + } + adjacent = st; + } + } + SetViewportCatchmentStation(adjacent, true); +} + /** * Check whether we need to redraw the station coverage text. * If it is needed actually make the window for redrawing. @@ -87,9 +127,20 @@ int DrawStationCoverageAreaText(int left, int right, int top, StationCoverageTyp */ void CheckRedrawStationCoverage(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; w->SetDirty(); + + if (_settings_client.gui.station_show_coverage && _thd.drawstyle == HT_RECT) { + FindStationsAroundSelection(); + } } } @@ -2256,11 +2307,15 @@ struct SelectStationWindow : Window { this->GetWidget(WID_JS_CAPTION)->widget_data = T::EXPECTED_FACIL == FACIL_WAYPOINT ? STR_JOIN_WAYPOINT_CAPTION : STR_JOIN_STATION_CAPTION; this->FinishInitNested(0); this->OnInvalidateData(0); + + _thd.freeze = true; } ~SelectStationWindow() { if (_settings_client.gui.station_show_coverage) SetViewportCatchmentStation(nullptr, true); + + _thd.freeze = false; } void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override @@ -2350,6 +2405,23 @@ struct SelectStationWindow : Window { this->vscroll->SetCount((uint)_stations_nearby_list.size() + 1); this->SetDirty(); } + + void OnMouseOver(Point pt, int widget) override + { + if (widget != WID_JS_PANEL) { + SetViewportCatchmentStation(nullptr, true); + return; + } + + /* Show coverage area of station under cursor */ + uint st_index = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_JS_PANEL, WD_FRAMERECT_TOP); + if (st_index == 0 || st_index > _stations_nearby_list.size()) { + SetViewportCatchmentStation(nullptr, true); + } else { + st_index--; + SetViewportCatchmentStation(Station::Get(_stations_nearby_list[st_index]), true); + } + } }; static WindowDesc _select_station_desc( diff --git a/src/tilehighlight_type.h b/src/tilehighlight_type.h index 3d64248dff..f1109bf2e5 100644 --- a/src/tilehighlight_type.h +++ b/src/tilehighlight_type.h @@ -52,6 +52,8 @@ struct TileHighlightData { Point outersize; ///< Size, in tile "units", of the blue coverage area excluding the side of the selected area. bool diagonal; ///< Whether the dragged area is a 45 degrees rotated rectangle. + bool freeze; ///< Freeze highlight in place. + Point new_pos; ///< New value for \a pos; used to determine whether to redraw the selection. Point new_size; ///< New value for \a size; used to determine whether to redraw the selection. Point new_outersize; ///< New value for \a outersize; used to determine whether to redraw the selection. diff --git a/src/viewport.cpp b/src/viewport.cpp index c8ae46abdb..27e8f2eca9 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2445,6 +2445,8 @@ void UpdateTileSelection() int x1; int y1; + if (_thd.freeze) return; + HighLightStyle new_drawstyle = HT_NONE; bool new_diagonal = false;