From b870596f153c17d9aa915ca67b8f6414d73cb31f 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/core/kdtree.hpp | 11 +++++++++ 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 | 22 ++++++++++++++++++ src/town_kdtree.h | 2 ++ src/viewport.cpp | 38 ++++++++++++++++++++++++++++++++ src/widgets/town_widget.h | 1 + 10 files changed, 82 insertions(+) diff --git a/src/core/kdtree.hpp b/src/core/kdtree.hpp index c7f66ebff9a9..59f3da8101d0 100644 --- a/src/core/kdtree.hpp +++ b/src/core/kdtree.hpp @@ -372,6 +372,17 @@ class Kdtree { CheckInvariant(); } + /** + * Clear the tree. + */ + void Clear() + { + this->nodes.clear(); + this->free_list.clear(); + this->unbalanced = 0; + return; + } + /** * Reconstruct the tree with the same elements, letting it be fully balanced. */ diff --git a/src/lang/english.txt b/src/lang/english.txt index e6e4bb930594..8d13ee196606 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3122,6 +3122,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 3d09f26f26e2..ffdadecd3b5b 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 3abc091d681c..252cb3e54f4b 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -2495,6 +2495,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 ce938ea06540..b0f4a5c72c9b 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 TownLayout layout; ///< town specific road layout + bool show_zone; ///< NOSAVE: 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 65032c1fb2d0..2049cbddccc9 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1746,6 +1746,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 f9670e84ea36..0436e87e0930 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -33,6 +33,7 @@ #include "genworld.h" #include "stringfilter_type.h" #include "widgets/dropdown_func.h" +#include "town_kdtree.h" #include "widgets/town_widget.h" @@ -40,12 +41,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), @@ -113,6 +117,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(); @@ -258,6 +263,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; @@ -1274,3 +1291,8 @@ void ShowFoundTownWindow() if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return; AllocateWindowDescFront(&_found_town_desc, 0); } + +void InitializeTownGui() +{ + _town_local_authority_kdtree.Clear(); +} diff --git a/src/town_kdtree.h b/src/town_kdtree.h index ae6b9e4eac05..92416558541a 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 534de090b54f..5a5756dfea36 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" @@ -1038,12 +1039,49 @@ static void DrawTileHighlightType(const TileInfo *ti, TileHighlightType tht) } } +/** + * 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) { + if (!Town::GetByTile(ti->tile)->show_zone) 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 e5ac66184d9d..bd6e0b954fda 100644 --- a/src/widgets/town_widget.h +++ b/src/widgets/town_widget.h @@ -25,6 +25,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.