diff --git a/src/lang/english.txt b/src/lang/english.txt index b639d76ab4..1688e4077d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1576,9 +1576,12 @@ STR_CONFIG_SETTING_QUICKGOTO :Quick creation STR_CONFIG_SETTING_QUICKGOTO_HELPTEXT :Pre-select the 'goto cursor' when opening the orders window STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE :Default rail type (after new game/game load): {STRING2} STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT :Rail type to select after starting or loading a game. 'first available' selects the oldest type of tracks, 'last available' selects the newest type of tracks, and 'most used' selects the type which is currently most in use +STR_CONFIG_SETTING_DEFAULT_ROAD_TYPE :Default road/tram types (after new game/game load): {STRING2} +STR_CONFIG_SETTING_DEFAULT_ROAD_TYPE_HELPTEXT :Road/tram types to select after starting or loading a game. 'first available' selects the oldest type of road/tram, 'last available' selects the newest type of road/tram, 'most used' selects the type which is currently most in use, and 'default' selects the default type STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST :First available STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_LAST :Last available STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_MOST_USED :Most used +STR_CONFIG_SETTING_DEFAULT_ROAD_TYPE_DEFAULT :Default STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION :Show path reservations for tracks: {STRING2} STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Give reserved tracks a different colour to assist in problems with trains refusing to enter path-based blocks diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 2b7c25388e..d68c470b76 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -31,6 +31,7 @@ #include "strings_func.h" #include "core/geometry_func.hpp" #include "date_func.h" +#include "station_map.h" #include "widgets/road_widget.h" @@ -1258,11 +1259,87 @@ void InitializeRoadGui() _road_station_picker_orientation = DIAGDIR_NW; } + +/** Set the initial (default) road and tram types to use */ +static void SetDefaultRoadGui() +{ + extern RoadType _last_built_roadtype; + extern RoadType _last_built_tramtype; + + /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */ + _last_built_roadtype = ROADTYPE_ROAD; + _last_built_tramtype = ROADTYPE_TRAM; + + if (_local_company == COMPANY_SPECTATOR || !Company::IsValidID(_local_company)) return; + + auto get_first_road_type = [](RoadTramType rtt, RoadType &out) { + auto it = std::find_if(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), + [&](RoadType r){ return GetRoadTramType(r) == rtt && HasRoadTypeAvail(_local_company, r); }); + if (it != _sorted_roadtypes.end()) out = *it; + }; + auto get_last_road_type = [](RoadTramType rtt, RoadType &out) { + auto it = std::find_if(_sorted_roadtypes.rbegin(), _sorted_roadtypes.rend(), + [&](RoadType r){ return GetRoadTramType(r) == rtt && HasRoadTypeAvail(_local_company, r); }); + if (it != _sorted_roadtypes.rend()) out = *it; + }; + + switch (_settings_client.gui.default_road_type) { + case 3: { + /* Use defaults above */ + break; + } + case 2: { + /* Find the most used types */ + std::array road_count = {}; + std::array tram_count = {}; + for (TileIndex t = 0; t < MapSize(); t++) { + if (MayHaveRoad(t)) { + if (IsTileType(t, MP_STATION) && !IsRoadStop(t)) continue; + RoadType road_type = GetRoadTypeRoad(t); + if (road_type != INVALID_ROADTYPE) road_count[road_type]++; + RoadType tram_type = GetRoadTypeTram(t); + if (tram_type != INVALID_ROADTYPE) tram_count[tram_type]++; + } + } + + auto get_best_road_type = [&](RoadTramType rtt, RoadType &out, const std::array &count) { + uint highest = 0; + for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { + if (count[rt] > highest && HasRoadTypeAvail(_local_company, rt)) { + out = rt; + highest = count[rt]; + } + } + if (highest == 0) get_first_road_type(rtt, out); + }; + get_best_road_type(RTT_ROAD, _last_built_roadtype, road_count); + get_best_road_type(RTT_TRAM, _last_built_tramtype, tram_count); + break; + } + case 0: { + /* Use first available types */ + get_first_road_type(RTT_ROAD, _last_built_roadtype); + get_first_road_type(RTT_TRAM, _last_built_tramtype); + break; + } + case 1: { + /* Use last available type */ + get_last_road_type(RTT_ROAD, _last_built_roadtype); + get_last_road_type(RTT_TRAM, _last_built_tramtype); + break; + } + default: + NOT_REACHED(); + } +} + /** * I really don't know why rail_gui.cpp has this too, shouldn't be included in the other one? */ void InitializeRoadGUI() { + SetDefaultRoadGui(); + BuildRoadToolbarWindow *w = dynamic_cast(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_ROAD)); if (w != nullptr) w->ModifyRoadType(_cur_roadtype); } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 52ccff6e4b..05f1585317 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -49,6 +49,7 @@ #include "../newgrf.h" #include "../engine_func.h" #include "../rail_gui.h" +#include "../road_gui.h" #include "../core/backup_type.hpp" #include "../core/mem_func.hpp" #include "../smallmap_gui.h" @@ -3787,6 +3788,8 @@ bool AfterLoadGame() } } + InitializeRoadGUI(); + /* This needs to be done after conversion. */ RebuildViewportKdtree(); ViewportMapBuildTunnelCache(); diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 5e5ac77f34..6e2b41a546 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1653,6 +1653,7 @@ static SettingsContainer &GetSettingsTree() construction->Add(new SettingEntry("gui.persistent_buildingtools")); construction->Add(new SettingEntry("gui.quick_goto")); construction->Add(new SettingEntry("gui.default_rail_type")); + construction->Add(new SettingEntry("gui.default_road_type")); construction->Add(new SettingEntry("gui.disable_unsuitable_building")); } diff --git a/src/settings_type.h b/src/settings_type.h index fe158aedf4..098957dc5c 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -111,6 +111,7 @@ struct GUISettings : public TimeSettings { uint8 advanced_vehicle_list; ///< use the "advanced" vehicle list uint8 loading_indicators; ///< show loading indicators uint8 default_rail_type; ///< the default rail type for the rail GUI + uint8 default_road_type; ///< the default road/tram types for the road/tram GUI uint8 toolbar_pos; ///< position of toolbars, 0=left, 1=center, 2=right uint8 statusbar_pos; ///< position of statusbar, 0=left, 1=center, 2=right uint8 window_snap_radius; ///< windows snap at each other if closer than this diff --git a/src/table/settings.ini b/src/table/settings.ini index 49cb9ec595..ee5984d9a2 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -4545,6 +4545,19 @@ strhelp = STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_HELPTEXT strval = STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST cat = SC_BASIC +[SDTC_VAR] +var = gui.default_road_type +type = SLE_UINT8 +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +guiflags = SGF_MULTISTRING +def = 0 +min = 0 +max = 3 +str = STR_CONFIG_SETTING_DEFAULT_ROAD_TYPE +strhelp = STR_CONFIG_SETTING_DEFAULT_ROAD_TYPE_HELPTEXT +strval = STR_CONFIG_SETTING_DEFAULT_RAIL_TYPE_FIRST +cat = SC_BASIC + [SDTC_BOOL] var = gui.enable_signal_gui flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index b5ace1ca54..01eb094d87 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2670,10 +2670,6 @@ static WindowDesc _toolb_scen_desc( /** Allocate the toolbar. */ void AllocateToolbar() { - /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */ - _last_built_roadtype = ROADTYPE_ROAD; - _last_built_tramtype = ROADTYPE_TRAM; - if (_game_mode == GM_EDITOR) { new ScenarioEditorToolbarWindow(&_toolb_scen_desc); } else {