From 63afc96d2ab070a805ec0f4c93400083799719c4 Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Wed, 10 May 2023 21:52:47 +0200 Subject: [PATCH] Feature: Show depot signs of removed depots. (based on patch by adf88, #6328, #5071) --- src/depot.cpp | 13 +++++++++ src/depot_base.h | 3 +++ src/depot_cmd.cpp | 26 ++++++++++++++++++ src/depot_func.h | 1 + src/lang/english.txt | 3 +++ src/saveload/afterload.cpp | 2 ++ src/station.cpp | 4 +++ src/town_cmd.cpp | 3 +++ src/viewport.cpp | 55 ++++++++++++++++++++++++++++++++++++++ src/viewport_kdtree.h | 7 +++++ 10 files changed, 117 insertions(+) diff --git a/src/depot.cpp b/src/depot.cpp index b0e750e87b..894fa1138e 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -17,6 +17,7 @@ #include "vehiclelist.h" #include "command_func.h" #include "vehicle_base.h" +#include "viewport_kdtree.h" #include "safeguards.h" @@ -63,6 +64,10 @@ Depot::~Depot() this->veh_type, this->owner, this->index).Pack()); InvalidateWindowData(WC_SELECT_DEPOT, this->veh_type); + + /* The sign will now disappear. */ + _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeDepot(this->index)); + this->sign.MarkDirty(); } /** @@ -77,6 +82,10 @@ void Depot::Reuse(TileIndex xy) this->xy = xy; this->ta.tile = xy; this->ta.h = this->ta.w = 1; + + /* Ensure the sign is not drawn */ + _viewport_sign_kdtree.Remove(ViewportSignKdtreeItem::MakeDepot(this->index)); + this->sign.MarkDirty(); } /** @@ -93,6 +102,10 @@ void Depot::Disuse() { /* Mark that the depot is demolished and start the countdown. */ this->delete_ctr = 8; + + /* Update the sign, it will be visible from now. */ + this->UpdateVirtCoord(); + _viewport_sign_kdtree.Insert(ViewportSignKdtreeItem::MakeDepot(this->index)); } /** diff --git a/src/depot_base.h b/src/depot_base.h index f6fcd04027..f25d817999 100644 --- a/src/depot_base.h +++ b/src/depot_base.h @@ -11,6 +11,7 @@ #define DEPOT_BASE_H #include "depot_map.h" +#include "viewport_type.h" #include "core/pool_type.hpp" #include "timer/timer_game_calendar.h" #include "rail_type.h" @@ -33,6 +34,7 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> { VehicleType veh_type; ///< Vehicle type of the depot. Owner owner; ///< Owner of the depot. uint8_t delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the depot is then deleted. + ViewportSign sign; ///< NOSAVE: Dimensions of sign Station *station; ///< For aircraft, station associated with this hangar. union { @@ -87,6 +89,7 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> { void Reuse(TileIndex xy); void Disuse(); + void UpdateVirtCoord(); /* Check we can add some tiles to this depot. */ CommandCost BeforeAddTiles(TileArea ta); diff --git a/src/depot_cmd.cpp b/src/depot_cmd.cpp index 88959bf98e..1364800dd8 100644 --- a/src/depot_cmd.cpp +++ b/src/depot_cmd.cpp @@ -17,6 +17,9 @@ #include "vehiclelist.h" #include "window_func.h" #include "depot_cmd.h" +#include "strings_func.h" +#include "landscape.h" +#include "viewport_kdtree.h" #include "timer/timer_game_tick.h" #include "table/strings.h" @@ -60,6 +63,8 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str } if (flags & DC_EXEC) { + /* _viewport_sign_kdtree does not need to be updated, only in-use depots can be renamed */ + if (reset) { d->name.clear(); MakeDefaultName(d); @@ -77,6 +82,27 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str return CommandCost(); } +/** Update the virtual coords needed to draw the depot sign. */ +void Depot::UpdateVirtCoord() +{ + Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE); + + pt.y -= 32 * ZOOM_BASE; + + SetDParam(0, this->veh_type); + SetDParam(1, this->index); + this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_DEPOT, STR_VIEWPORT_DEPOT_TINY); + + SetWindowDirty(WC_VEHICLE_DEPOT, this->index); +} + +/** Update the virtual coords needed to draw the depot sign for all depots. */ +void UpdateAllDepotVirtCoords() +{ + /* Only demolished depots have signs. */ + for (Depot *d : Depot::Iterate()) if (!d->IsInUse()) d->UpdateVirtCoord(); +} + /** * Find a demolished depot close to a tile. * @param ta Tile area to search for. diff --git a/src/depot_func.h b/src/depot_func.h index f214e6d848..d1890c8728 100644 --- a/src/depot_func.h +++ b/src/depot_func.h @@ -19,6 +19,7 @@ void ShowDepotWindow(DepotID depot_id); void InitDepotWindowBlockSizes(); void DeleteDepotHighlightOfVehicle(const Vehicle *v); +void UpdateAllDepotVirtCoords(); /** * Find out if the slope of the tile is suitable to build a depot of given direction diff --git a/src/lang/english.txt b/src/lang/english.txt index e2e0e477ad..d1526effea 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5848,6 +5848,9 @@ STR_VIEWPORT_STATION_TINY :{TINY_FONT}{STA STR_VIEWPORT_WAYPOINT :{WAYPOINT} STR_VIEWPORT_WAYPOINT_TINY :{TINY_FONT}{WAYPOINT} +STR_VIEWPORT_DEPOT :{DEPOT} +STR_VIEWPORT_DEPOT_TINY :{TINY_FONT}{DEPOT} + # Simple strings to get specific types of data STR_COMPANY_NAME :{COMPANY} STR_COMPANY_NAME_COMPANY_NUM :{COMPANY} {COMPANY_NUM} diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 6aff783288..1cdc0959a7 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -11,6 +11,7 @@ #include "../void_map.h" #include "../signs_base.h" #include "../depot_base.h" +#include "../depot_func.h" #include "../fios.h" #include "../gamelog_internal.h" #include "../network/network.h" @@ -222,6 +223,7 @@ static inline RailType UpdateRailType(RailType rt, RailType min) void UpdateAllVirtCoords() { UpdateAllStationVirtCoords(); + UpdateAllDepotVirtCoords(); UpdateAllSignVirtCoords(); UpdateAllTownVirtCoords(); UpdateAllTextEffectVirtCoords(); diff --git a/src/station.cpp b/src/station.cpp index 0d4198ac6c..cf07e27f92 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -755,6 +755,9 @@ void Airport::AddHangar() */ void Airport::RemoveHangar() { + if (this->hangar == nullptr) return; + + /* TODO Check this. */ RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->hangar->index); for (Aircraft *a : Aircraft::Iterate()) { @@ -764,6 +767,7 @@ void Airport::RemoveHangar() a->current_order.MakeDummy(); } + this->hangar->Disuse(); delete this->hangar; this->hangar = nullptr; } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index cc8364b0a1..983065c108 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -44,6 +44,7 @@ #include "core/random_func.hpp" #include "core/backup_type.hpp" #include "depot_base.h" +#include "depot_func.h" #include "object_map.h" #include "object_base.h" #include "ai/ai.hpp" @@ -2998,6 +2999,8 @@ CommandCost CmdRenameTown(DoCommandFlag flags, TownID town_id, const std::string ClearAllStationCachedNames(); ClearAllIndustryCachedNames(); UpdateAllStationVirtCoords(); + UpdateAllDepotVirtCoords(); + RebuildViewportKdtree(); } return CommandCost(); } diff --git a/src/viewport.cpp b/src/viewport.cpp index 1892962398..2bee590429 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -66,6 +66,8 @@ #include "viewport_func.h" #include "station_base.h" #include "waypoint_base.h" +#include "depot_base.h" +#include "depot_func.h" #include "town.h" #include "signs_base.h" #include "signs_func.h" @@ -1366,12 +1368,14 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) bool show_waypoints = HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES) && _game_mode != GM_MENU; bool show_towns = HasBit(_display_opt, DO_SHOW_TOWN_NAMES) && _game_mode != GM_MENU; bool show_signs = HasBit(_display_opt, DO_SHOW_SIGNS) && !IsInvisibilitySet(TO_SIGNS); + bool show_depotsigns = _game_mode != GM_MENU; bool show_competitors = HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS); /* Collect all the items first and draw afterwards, to ensure layering */ std::vector stations; std::vector towns; std::vector signs; + std::vector depots; _viewport_sign_kdtree.FindContained(search_rect.left, search_rect.top, search_rect.right, search_rect.bottom, [&](const ViewportSignKdtreeItem & item) { switch (item.type) { @@ -1415,6 +1419,19 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) break; } + case ViewportSignKdtreeItem::VKI_DEPOT: { + if (!show_depotsigns) break; + const Depot *depot = Depot::Get(item.id.depot); + + /* Only show depot name after the depot is removed. */ + if (depot->IsInUse()) break; + /* Don't draw if depot is owned by another company and competitor signs are hidden. */ + if (!show_competitors && _local_company != depot->owner) break; + + depots.push_back(depot); + break; + } + default: NOT_REACHED(); } @@ -1441,6 +1458,12 @@ static void ViewportAddKdtreeSigns(DrawPixelInfo *dpi) (si->owner == OWNER_NONE) ? COLOUR_GREY : (si->owner == OWNER_DEITY ? INVALID_COLOUR : _company_colours[si->owner])); } + for (const auto *d : depots) { + SetDParam(0, d->veh_type); + SetDParam(1, d->index); + ViewportAddString(dpi, ZOOM_LVL_OUT_4X, &d->sign, STR_VIEWPORT_DEPOT, STR_VIEWPORT_DEPOT_TINY, STR_NULL, COLOUR_GREY); + } + for (const auto *st : stations) { SetDParam(0, st->index); SetDParam(1, st->facilities); @@ -2237,6 +2260,7 @@ static bool CheckClickOnViewportSign(const Viewport *vp, int x, int y) BaseStation *st = nullptr, *last_st = nullptr; Town *t = nullptr, *last_t = nullptr; Sign *si = nullptr, *last_si = nullptr; + Depot *dep = nullptr, *last_dep = nullptr; /* See ViewportAddKdtreeSigns() for details on the search logic */ _viewport_sign_kdtree.FindContained(search_rect.left, search_rect.top, search_rect.right, search_rect.bottom, [&](const ViewportSignKdtreeItem & item) { @@ -2268,6 +2292,12 @@ static bool CheckClickOnViewportSign(const Viewport *vp, int x, int y) if (CheckClickOnViewportSign(vp, x, y, &si->sign)) last_si = si; break; + case ViewportSignKdtreeItem::VKI_DEPOT: + dep = Depot::Get(item.id.depot); + if (!show_competitors && _local_company != st->owner && st->owner != OWNER_NONE) break; + if (CheckClickOnViewportSign(vp, x, y, &dep->sign)) last_dep = dep; + break; + default: NOT_REACHED(); } @@ -2287,6 +2317,9 @@ static bool CheckClickOnViewportSign(const Viewport *vp, int x, int y) } else if (last_si != nullptr) { HandleClickOnSign(last_si); return true; + } else if (last_dep != nullptr) { + ShowDepotWindow(last_dep->index); + return true; } else { return false; } @@ -2310,6 +2343,23 @@ ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeStation(StationID id) return item; } +ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeDepot(DepotID id) +{ + ViewportSignKdtreeItem item; + item.type = VKI_DEPOT; + item.id.depot = id; + + const Depot *depot = Depot::Get(id); + + item.center = depot->sign.center; + item.top = depot->sign.top; + + /* Assume the sign can be a candidate for drawing, so measure its width */ + _viewport_sign_maxwidth = std::max(_viewport_sign_maxwidth, depot->sign.width_normal); + + return item; +} + ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeWaypoint(StationID id) { ViewportSignKdtreeItem item; @@ -2385,6 +2435,11 @@ void RebuildViewportKdtree() if (sign->sign.kdtree_valid) items.push_back(ViewportSignKdtreeItem::MakeSign(sign->index)); } + for (const Depot *dep : Depot::Iterate()) { + if (dep->IsInUse()) continue; + items.push_back(ViewportSignKdtreeItem::MakeDepot(dep->index)); + } + _viewport_sign_kdtree.Build(items.begin(), items.end()); } diff --git a/src/viewport_kdtree.h b/src/viewport_kdtree.h index 3c2f49c2e4..333c3685fc 100644 --- a/src/viewport_kdtree.h +++ b/src/viewport_kdtree.h @@ -22,12 +22,14 @@ struct ViewportSignKdtreeItem { VKI_WAYPOINT, VKI_TOWN, VKI_SIGN, + VKI_DEPOT, }; ItemType type; union { StationID station; TownID town; SignID sign; + DepotID depot; } id; int32_t center; int32_t top; @@ -43,6 +45,8 @@ struct ViewportSignKdtreeItem { return this->id.town == other.id.town; case VKI_SIGN: return this->id.sign == other.id.sign; + case VKI_DEPOT: + return this->id.depot == other.id.depot; default: NOT_REACHED(); } @@ -59,6 +63,8 @@ struct ViewportSignKdtreeItem { return this->id.town < other.id.town; case VKI_SIGN: return this->id.sign < other.id.sign; + case VKI_DEPOT: + return this->id.depot < other.id.depot; default: NOT_REACHED(); } @@ -68,6 +74,7 @@ struct ViewportSignKdtreeItem { static ViewportSignKdtreeItem MakeWaypoint(StationID id); static ViewportSignKdtreeItem MakeTown(TownID id); static ViewportSignKdtreeItem MakeSign(SignID id); + static ViewportSignKdtreeItem MakeDepot(DepotID id); }; inline int32_t Kdtree_ViewportSignXYFunc(const ViewportSignKdtreeItem &item, int dim)