From 6d1207244593c98d98255561b3d989673cf99848 Mon Sep 17 00:00:00 2001 From: Gabda Date: Sat, 5 Jan 2019 14:22:07 +0100 Subject: [PATCH] Add #6887: Option to show zone inside local authority boundary of towns Can be found at town information > local authority window Layout for button is same as Graph Keys Turn on/off for every town individually --- src/lang/english.txt | 2 ++ src/misc.cpp | 2 ++ src/script/api/script_window.hpp | 1 + src/town.h | 2 ++ src/town_cmd.cpp | 1 + src/town_gui.cpp | 23 ++++++++++++++++++ src/town_kdtree.h | 2 ++ src/viewport.cpp | 40 ++++++++++++++++++++++++++++++++ src/widgets/town_widget.h | 1 + 9 files changed, 74 insertions(+) diff --git a/src/lang/english.txt b/src/lang/english.txt index 61fa2a91ba82b..d614b897b829d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3099,6 +3099,8 @@ STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Rename Town # Town local authority window STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} local authority +STR_LOCAL_AUTHORITY_ZONE :{BLACK}Zone +STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Show zone within local authority boundaries STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Transport company ratings: STR_LOCAL_AUTHORITY_COMPANY_RATING :{YELLOW}{COMPANY} {COMPANY_NUM}: {ORANGE}{STRING} STR_LOCAL_AUTHORITY_ACTIONS_TITLE :{BLACK}Actions available: diff --git a/src/misc.cpp b/src/misc.cpp index 3d09f26f26e2e..ffdadecd3b5b8 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -47,6 +47,7 @@ void InitializeAirportGui(); void InitializeDockGui(); void InitializeGraphGui(); void InitializeObjectGui(); +void InitializeTownGui(); void InitializeIndustries(); void InitializeObjects(); void InitializeTrees(); @@ -97,6 +98,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin InitializeDockGui(); InitializeGraphGui(); InitializeObjectGui(); + InitializeTownGui(); InitializeAIGui(); InitializeTrees(); InitializeIndustries(); diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index fa584693af934..2d11ef0fe0b57 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -2482,6 +2482,7 @@ class ScriptWindow : public ScriptObject { /** Widgets of the #TownAuthorityWindow class. */ enum TownAuthorityWidgets { WID_TA_CAPTION = ::WID_TA_CAPTION, ///< Caption of window. + WID_TA_ZONE_BUTTON = ::WID_TA_ZONE_BUTTON, ///< Turn on/off showing local authority zone. WID_TA_RATING_INFO = ::WID_TA_RATING_INFO, ///< Overview with ratings for each company. WID_TA_COMMAND_LIST = ::WID_TA_COMMAND_LIST, ///< List of commands for the player. WID_TA_SCROLLBAR = ::WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands. diff --git a/src/town.h b/src/town.h index 76c3b770d4da3..c4bd2116b8126 100644 --- a/src/town.h +++ b/src/town.h @@ -101,6 +101,8 @@ struct Town : TownPool::PoolItem<&_town_pool> { bool larger_town; ///< if this is a larger town and should grow more quickly TownLayoutByte layout; ///< town specific road layout + bool show_zone; ///< mark town to show the local authority zone in the viewports + std::list psa_list; /** diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index d918fbcedaf45..8d78462e6a936 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1677,6 +1677,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize * similar towns they're unlikely to grow all in one tick */ t->grow_counter = t->index % TOWN_GROWTH_TICKS; t->growth_rate = TownTicksToGameTicks(250); + t->show_zone = false; _town_kdtree.Insert(t->index); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index cf5d4302602e4..730c503ddbf7d 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -32,6 +32,7 @@ #include "core/geometry_func.hpp" #include "genworld.h" #include "widgets/dropdown_func.h" +#include "town_kdtree.h" #include "widgets/town_widget.h" @@ -39,12 +40,15 @@ #include "safeguards.h" +TownKdtree _town_local_authority_kdtree(&Kdtree_TownXYFunc); + typedef GUIList GUITownList; static const NWidgetPart _nested_town_authority_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TA_CAPTION), SetDataTip(STR_LOCAL_AUTHORITY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TA_ZONE_BUTTON), SetMinimalSize(50, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP), NWidget(WWT_SHADEBOX, COLOUR_BROWN), NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN), NWidget(WWT_STICKYBOX, COLOUR_BROWN), @@ -112,6 +116,7 @@ struct TownAuthorityWindow : Window { this->sel_index = -1; } + this->SetWidgetLoweredState(WID_TA_ZONE_BUTTON, this->town->show_zone); this->SetWidgetDisabledState(WID_TA_EXECUTE, this->sel_index == -1); this->DrawWidgets(); @@ -257,6 +262,18 @@ struct TownAuthorityWindow : Window { void OnClick(Point pt, int widget, int click_count) override { switch (widget) { + case WID_TA_ZONE_BUTTON: { + bool new_show_state = !this->town->show_zone; + TownID index = this->town->index; + + new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index); + + this->town->show_zone = new_show_state; + this->SetWidgetLoweredState(widget, new_show_state); + MarkWholeScreenDirty(); + break; + } + case WID_TA_COMMAND_LIST: { int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, FONT_HEIGHT_NORMAL); if (!IsInsideMM(y, 0, 5)) return; @@ -1209,3 +1226,9 @@ void ShowFoundTownWindow() if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return; AllocateWindowDescFront(&_found_town_desc, 0); } + +void InitializeTownGui() +{ + std::vector townids; + _town_local_authority_kdtree.Build(townids.begin(), townids.end()); +} diff --git a/src/town_kdtree.h b/src/town_kdtree.h index ae6b9e4eac05c..92416558541ad 100644 --- a/src/town_kdtree.h +++ b/src/town_kdtree.h @@ -15,6 +15,8 @@ inline uint16 Kdtree_TownXYFunc(TownID tid, int dim) { return (dim == 0) ? TileX(Town::Get(tid)->xy) : TileY(Town::Get(tid)->xy); } typedef Kdtree TownKdtree; + extern TownKdtree _town_kdtree; +extern TownKdtree _town_local_authority_kdtree; #endif diff --git a/src/viewport.cpp b/src/viewport.cpp index 9bbe6a46235aa..2fea3eaa1edb6 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -83,6 +83,7 @@ #include "window_gui.h" #include "linkgraph/linkgraph_gui.h" #include "viewport_kdtree.h" +#include "town_kdtree.h" #include "viewport_sprite_sorter.h" #include "bridge_map.h" #include "company_base.h" @@ -979,12 +980,51 @@ static void DrawAutorailSelection(const TileInfo *ti, uint autorail_type) DrawSelectionSprite(image, _thd.make_square_red ? PALETTE_SEL_TILE_RED : pal, ti, 7, foundation_part); } +/** + * Highlights tiles insede local authority of selected towns. + * @param *ti TileInfo Tile that is being drawn + */ +static void HighlightTownLocalAuthorityTiles(const TileInfo *ti) +{ + /* Going through cases in order of computational time. */ + + if (_town_local_authority_kdtree.Count() == 0) return; + + /* Tile belongs to town regardless of distance from town. */ + if (GetTileType(ti->tile) == MP_HOUSE) { + TownID tid = GetTownIndex(ti->tile); + + if (!_town_local_authority_kdtree.IsInTree(tid)) return; + + DrawTileSelectionRect(ti, PALETTE_CRASH); + return; + } + + /* If the closest town in the highlighted list is far, we can stop searching. */ + TownID tid = _town_local_authority_kdtree.FindNearest(TileX(ti->tile), TileY(ti->tile)); + Town *closest_highlighted_town = Town::Get(tid); + + if (DistanceManhattan(ti->tile, closest_highlighted_town->xy) >= _settings_game.economy.dist_local_authority) return; + + /* Tile is inside of the local autrhority distance of a highlighted town, + but it is possible that a non-highlighted town is even closer. */ + Town *closest_town = ClosestTownFromTile(ti->tile, _settings_game.economy.dist_local_authority); + + if (closest_town->show_zone) { + DrawTileSelectionRect(ti, PALETTE_CRASH); + } + +} + /** * Checks if the specified tile is selected and if so draws selection using correct selectionstyle. * @param *ti TileInfo Tile that is being drawn */ static void DrawTileSelection(const TileInfo *ti) { + /* Highlight tiles insede local authority of selected towns. */ + HighlightTownLocalAuthorityTiles(ti); + /* Draw a red error square? */ bool is_redsq = _thd.redsq == ti->tile; if (is_redsq) DrawTileSelectionRect(ti, PALETTE_TILE_RED_PULSATING); diff --git a/src/widgets/town_widget.h b/src/widgets/town_widget.h index 4f5443c36ef9e..8906e4022da38 100644 --- a/src/widgets/town_widget.h +++ b/src/widgets/town_widget.h @@ -24,6 +24,7 @@ enum TownDirectoryWidgets { /** Widgets of the #TownAuthorityWindow class. */ enum TownAuthorityWidgets { WID_TA_CAPTION, ///< Caption of window. + WID_TA_ZONE_BUTTON, ///< Turn on/off showing local authority zone. WID_TA_RATING_INFO, ///< Overview with ratings for each company. WID_TA_COMMAND_LIST, ///< List of commands for the player. WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands.