diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 1a985eb64a..d0e1ba31c9 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -38,6 +38,7 @@ #include "querystring_gui.h" #include "stringfilter_type.h" #include "hotkeys.h" +#include "depot_base.h" #include "widgets/build_vehicle_widget.h" @@ -1163,6 +1164,25 @@ enum BuildVehicleHotkeys { BVHK_FOCUS_FILTER_BOX, ///< Focus the edit box for editing the filter string }; +/** + * Return a unique window number for the BuildVehicleWindow. + * The BuildVehicleWindow can be opened for a valid depot or + * for a specific vehicle type ("Available Trains", "Available Ships"...). + * The corresponding unique window number is chosen as: + * - For existing depots, the depot id. + * - For vehicle types, it is MAX_DEPOTS + vehicle_type + * @param depot_id the depot id + * @param type the vehicle type + * @return the depot id for valid depots or MAX_DEPOTS + vehicle_type otherwise. + */ +DepotID GetBuildVehicleWindowNumber(DepotID depot_id, VehicleType type) +{ + assert(depot_id == INVALID_DEPOT || Depot::IsValidID(depot_id)); + assert(IsCompanyBuildableVehicleType(type)); + if (depot_id != INVALID_DEPOT) return depot_id; + return MAX_DEPOTS + type; +} + /** GUI for building vehicles. */ struct BuildVehicleWindow : Window { VehicleType vehicle_type; ///< Type of vehicles shown in the window. @@ -1201,11 +1221,11 @@ struct BuildVehicleWindow : Window { } } - BuildVehicleWindow(WindowDesc &desc, TileIndex tile, VehicleType type) : Window(desc), vehicle_editbox(MAX_LENGTH_VEHICLE_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_VEHICLE_NAME_CHARS) + BuildVehicleWindow(WindowDesc &desc, DepotID depot_id, VehicleType type) : Window(desc), vehicle_editbox(MAX_LENGTH_VEHICLE_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_VEHICLE_NAME_CHARS) { this->vehicle_type = type; - this->listview_mode = tile == INVALID_TILE; - this->window_number = this->listview_mode ? (int)type : tile.base(); + this->listview_mode = depot_id == INVALID_DEPOT; + this->window_number = GetBuildVehicleWindowNumber(depot_id, type); this->sel_engine = INVALID_ENGINE; @@ -1240,16 +1260,13 @@ struct BuildVehicleWindow : Window { this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9); - if (tile == INVALID_TILE) { - this->FinishInitNested(type); - } else { - this->FinishInitNested(tile); - } + this->FinishInitNested(this->window_number); this->querystrings[WID_BV_FILTER] = &this->vehicle_editbox; this->vehicle_editbox.cancel_button = QueryString::ACTION_CLEAR; - this->owner = (tile != INVALID_TILE) ? GetTileOwner(tile) : _local_company; + Depot *depot = Depot::GetIfValid(depot_id); + this->owner = (depot != nullptr) ? GetTileOwner(depot->xy) : _local_company; this->eng_list.ForceRebuild(); this->GenerateBuildList(); // generate the list, since we need it in the next line @@ -1264,13 +1281,16 @@ struct BuildVehicleWindow : Window { /** Set the filter type according to the depot type */ void UpdateFilterByTile() { + TileIndex tile = INVALID_TILE; + if (!this->listview_mode) tile = Depot::Get(this->window_number)->xy; + switch (this->vehicle_type) { default: NOT_REACHED(); case VEH_TRAIN: if (this->listview_mode) { this->filter.railtype = INVALID_RAILTYPE; } else { - this->filter.railtype = GetRailType(this->window_number); + this->filter.railtype = GetRailType(tile); } break; @@ -1278,9 +1298,9 @@ struct BuildVehicleWindow : Window { if (this->listview_mode) { this->filter.roadtype = INVALID_ROADTYPE; } else { - this->filter.roadtype = GetRoadTypeRoad(this->window_number); + this->filter.roadtype = GetRoadTypeRoad(tile); if (this->filter.roadtype == INVALID_ROADTYPE) { - this->filter.roadtype = GetRoadTypeTram(this->window_number); + this->filter.roadtype = GetRoadTypeTram(tile); } } break; @@ -1326,7 +1346,7 @@ struct BuildVehicleWindow : Window { if (!this->listview_mode) { /* Query for cost and refitted capacity */ - auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command::Do(DC_QUERY_COST, this->window_number, this->sel_engine, true, cargo, INVALID_CLIENT_ID); + auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command::Do(DC_QUERY_COST, Depot::Get(this->window_number)->xy, this->sel_engine, true, cargo, INVALID_CLIENT_ID); if (ret.Succeeded()) { this->te.cost = ret.GetCost() - e->GetCost(); this->te.capacity = refit_capacity; @@ -1613,10 +1633,15 @@ struct BuildVehicleWindow : Window { CargoID cargo = this->cargo_filter_criteria; if (cargo == CargoFilterCriteria::CF_ANY || cargo == CargoFilterCriteria::CF_ENGINES || cargo == CargoFilterCriteria::CF_NONE) cargo = INVALID_CARGO; + + assert(Depot::IsValidID(this->window_number)); + Depot *depot = Depot::Get(this->window_number); + assert(depot->xy != INVALID_TILE); + if (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) { - Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildWagon, this->window_number, sel_eng, true, cargo, INVALID_CLIENT_ID); + Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildWagon, depot->xy, sel_eng, true, cargo, INVALID_CLIENT_ID); } else { - Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildPrimaryVehicle, this->window_number, sel_eng, true, cargo, INVALID_CLIENT_ID); + Command::Post(GetCmdBuildVehMsg(this->vehicle_type), CcBuildPrimaryVehicle, depot->xy, sel_eng, true, cargo, INVALID_CLIENT_ID); } /* Update last used variant in hierarchy and refresh if necessary. */ @@ -1930,17 +1955,11 @@ static WindowDesc _build_vehicle_desc( &BuildVehicleWindow::hotkeys ); -void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) +void ShowBuildVehicleWindow(DepotID depot_id, VehicleType type) { - /* We want to be able to open both Available Train as Available Ships, - * so if tile == INVALID_TILE (Available XXX Window), use 'type' as unique number. - * As it always is a low value, it won't collide with any real tile - * number. */ - uint num = (tile == INVALID_TILE) ? (int)type : tile.base(); - assert(IsCompanyBuildableVehicleType(type)); - CloseWindowById(WC_BUILD_VEHICLE, num); + CloseWindowById(WC_BUILD_VEHICLE, GetBuildVehicleWindowNumber(depot_id, type)); - new BuildVehicleWindow(_build_vehicle_desc, tile, type); + new BuildVehicleWindow(_build_vehicle_desc, depot_id, type); } diff --git a/src/depot_base.h b/src/depot_base.h index 1d8330fc74..a5be19f3a4 100644 --- a/src/depot_base.h +++ b/src/depot_base.h @@ -14,7 +14,15 @@ #include "core/pool_type.hpp" #include "timer/timer_game_calendar.h" -typedef Pool DepotPool; +static const DepotID MAX_DEPOTS = 64000; +/** + * For build_vehicle_window, each vehicle type needs its own unique value. + * So we need some special indexes: MAX_DEPOTS + VEH_TYPE_XXX. + * @see GetBuildVehicleWindowNumber + */ +static_assert(MAX_DEPOTS + VEH_COMPANY_END - 1 <= INVALID_DEPOT); + +typedef Pool DepotPool; extern DepotPool _depot_pool; struct Depot : DepotPool::PoolItem<&_depot_pool> { diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 750beb96eb..4f400de33b 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -769,7 +769,7 @@ struct DepotWindow : Window { case WID_D_BUILD: // Build vehicle ResetObjectToPlace(); - ShowBuildVehicleWindow(tile, this->type); + ShowBuildVehicleWindow(this->window_number, this->type); break; case WID_D_CLONE: // Clone button @@ -824,7 +824,7 @@ struct DepotWindow : Window { break; case WID_D_VEHICLE_LIST: - ShowVehicleListWindow(this->owner, this->type, tile); + ShowVehicleListWindowDepot(this->owner, this->type, this->window_number); break; case WID_D_AUTOREPLACE: diff --git a/src/group_gui.cpp b/src/group_gui.cpp index bb2a8d840d..ff3244c3a8 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -842,7 +842,7 @@ public: break; case WID_GL_AVAILABLE_VEHICLES: - ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype); + ShowBuildVehicleWindow(INVALID_DEPOT, this->vli.vtype); break; case WID_GL_MANAGE_VEHICLES_DROPDOWN: { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index aaaf10f993..bb277bab34 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -2123,7 +2123,7 @@ public: } case WID_VL_AVAILABLE_VEHICLES: - ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype); + ShowBuildVehicleWindow(INVALID_DEPOT, this->vli.vtype); break; case WID_VL_MANAGE_VEHICLES_DROPDOWN: { @@ -2268,16 +2268,9 @@ void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationI ShowVehicleListWindowLocal(company, VL_STATION_LIST, vehicle_type, station); } -void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile) +void ShowVehicleListWindowDepot(CompanyID company, VehicleType vehicle_type, DepotID depot_id) { - uint16_t depot_airport_index; - - if (vehicle_type == VEH_AIRCRAFT) { - depot_airport_index = GetStationIndex(depot_tile); - } else { - depot_airport_index = GetDepotIndex(depot_tile); - } - ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_airport_index); + ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_id); } diff --git a/src/vehicle_gui.h b/src/vehicle_gui.h index ebd0d3fde8..cf5d8a381d 100644 --- a/src/vehicle_gui.h +++ b/src/vehicle_gui.h @@ -18,6 +18,7 @@ #include "station_type.h" #include "engine_type.h" #include "company_type.h" +#include "depot_type.h" void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit = false); @@ -56,7 +57,7 @@ void DrawRoadVehImage(const Vehicle *v, const Rect &r, VehicleID selection, Engi void DrawShipImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type); void DrawAircraftImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type); -void ShowBuildVehicleWindow(TileIndex tile, VehicleType type); +void ShowBuildVehicleWindow(DepotID depot_id, VehicleType type); uint ShowRefitOptionsList(int left, int right, int y, EngineID engine); StringID GetCargoSubtypeText(const Vehicle *v); @@ -64,7 +65,7 @@ StringID GetCargoSubtypeText(const Vehicle *v); void ShowVehicleListWindow(const Vehicle *v); void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type); void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station); -void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile); +void ShowVehicleListWindowDepot(CompanyID company, VehicleType vehicle_type, DepotID depot_id); /** * Get the height of a single vehicle in the GUIs. diff --git a/src/window_type.h b/src/window_type.h index 6161aeee78..4437d26b3f 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -383,8 +383,8 @@ enum WindowClass { /** * Build vehicle; %Window numbers: - * - #VehicleType = #BuildVehicleWidgets - * - #TileIndex = #BuildVehicleWidgets + * - #DepotID = #BuildVehicleWidgets, for existing depots + * - #MAX_DEPOTS + VehicleType = #BuildVehicleWidgets, for "Available Trains"... */ WC_BUILD_VEHICLE,