Index: src/autoreplace_cmd.cpp =================================================================== --- src/autoreplace_cmd.cpp (revision 27931) +++ src/autoreplace_cmd.cpp (working copy) @@ -78,11 +78,6 @@ if (HasBit(e_from->info.misc_flags, EF_ROAD_TRAM) != HasBit(e_to->info.misc_flags, EF_ROAD_TRAM)) return false; break; - case VEH_AIRCRAFT: - /* make sure that we do not replace a plane with a helicopter or vice versa */ - if ((e_from->u.air.subtype & AIR_CTOL) != (e_to->u.air.subtype & AIR_CTOL)) return false; - break; - default: break; } Index: src/autoreplace_gui.cpp =================================================================== --- src/autoreplace_gui.cpp (revision 27931) +++ src/autoreplace_gui.cpp (working copy) @@ -31,6 +31,7 @@ #include "safeguards.h" void DrawEngineList(VehicleType type, int x, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group); +int _autoreplace_last_selected_aircraft_type = 1; // Last aircraft type option selected by default (Same aircraft type) static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b) { @@ -74,6 +75,15 @@ INVALID_STRING_ID }; +static const StringID _autoreplace_aircraft_type_dropdown[] = { + STR_REPLACE_ALL_AIRCRAFT_TYPES, // sel_air_type = 0 + STR_REPLACE_SAME_AIRCRAFT_TYPE, // sel_air_type = 1 + STR_REPLACE_HELICOPTER, // sel_air_type = 2 + STR_REPLACE_SMALL_AEROPLANE, // sel_air_type = 3 + STR_REPLACE_LARGE_AEROPLANE, // sel_air_type = 4 + INVALID_STRING_ID +}; + /** * Window for the autoreplacing of vehicles. */ @@ -87,6 +97,7 @@ byte sort_criteria; ///< Criteria of sorting vehicles. bool descending_sort_order; ///< Order of sorting vehicles. bool show_hidden_engines; ///< Whether to show the hidden engines. + int sel_air_type; ///< Type of aircraft selected to list. RailType sel_railtype; ///< Type of rail tracks selected. #INVALID_RAILTYPE to show all. Scrollbar *vscroll[2]; @@ -111,7 +122,41 @@ return true; } + /** + * Figure out if an aircraft should be added to the right list, regarding its type. + * @param from The EngineID of the selected aircraft on the left list. + * @param to The EngineID of the aircraft to be added to the right list. + * @return \c true if the engine should be added to the right list, else \c false. + */ + bool GenerateReplaceAircraftList(EngineID from, EngineID to) + { + const Engine *e_from = Engine::Get(from); + const Engine *e_to = Engine::Get(to); + switch (this->sel_air_type) { + case 0: // All aircraft types + return true; + + case 1: // Match aircraft type + if ((e_from->u.air.subtype == AIR_CTOL) != (e_to->u.air.subtype == AIR_CTOL)) return false; + if ((e_from->u.air.subtype == AIR_HELI) != (e_to->u.air.subtype == AIR_HELI)) return false; + if ((e_from->u.air.subtype == (AIR_CTOL | AIR_FAST)) != (e_to->u.air.subtype == (AIR_CTOL | AIR_FAST))) return false; + return true; + + case 2: // Helicopter + return e_to->u.air.subtype == AIR_HELI; + + case 3: // Small aeroplane + return e_to->u.air.subtype == AIR_CTOL; + + case 4: // Large aeroplane + return e_to->u.air.subtype == (AIR_CTOL | AIR_FAST); + + default: + return false; + } + } + /** * Generate an engines list * @param draw_left true if generating the left list, otherwise false @@ -138,6 +183,7 @@ if (num_engines == 0 && EngineReplacementForCompany(Company::Get(_local_company), eid, this->sel_group) == INVALID_ENGINE) continue; } else { if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue; + if (type == VEH_AIRCRAFT && !this->GenerateReplaceAircraftList(this->sel_engine[0], eid)) continue; } *list->Append() = eid; @@ -220,6 +266,7 @@ this->sel_engine[0] = INVALID_ENGINE; this->sel_engine[1] = INVALID_ENGINE; this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype]; + this->sel_air_type = _autoreplace_last_selected_aircraft_type; this->CreateNestedTree(); this->vscroll[0] = this->GetScrollbar(WID_RV_LEFT_SCROLLBAR); @@ -303,6 +350,17 @@ break; } + case WID_RV_AIRCRAFT_TYPE_DROPDOWN: { + Dimension d = GetStringBoundingBox(STR_REPLACE_ALL_AIRCRAFT_TYPES); + for (int i = 0; _autoreplace_aircraft_type_dropdown[i] != INVALID_STRING_ID; i++) { + d = maxdim(d, GetStringBoundingBox(_autoreplace_aircraft_type_dropdown[i])); + } + d.width += padding.width; + d.height += padding.height; + *size = maxdim(*size, d); + break; + } + case WID_RV_START_REPLACE: { Dimension d = GetStringBoundingBox(STR_REPLACE_VEHICLES_START); for (int i = 0; _start_replace_dropdown[i] != INVALID_STRING_ID; i++) { @@ -416,6 +474,11 @@ this->GetWidget(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(sel_railtype)->strings.replace_text; } + if (this->window_number == VEH_AIRCRAFT) { + /* Show the last selected aircraft type in the pulldown menu*/ + this->GetWidget(WID_RV_AIRCRAFT_TYPE_DROPDOWN)->widget_data = _autoreplace_aircraft_type_dropdown[sel_air_type]; + } + this->DrawWidgets(); if (!this->IsShaded()) { @@ -475,6 +538,11 @@ DoCommandP(0, GetCompanySettingIndex("company.renew_keep_length"), Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1, CMD_CHANGE_COMPANY_SETTING); break; + case WID_RV_AIRCRAFT_TYPE_DROPDOWN: { // Aircraft type dropdown menu + ShowDropDownMenu(this, _autoreplace_aircraft_type_dropdown, sel_air_type, WID_RV_AIRCRAFT_TYPE_DROPDOWN, 0, 0); + break; + } + case WID_RV_START_REPLACE: { // Start replacing if (this->GetWidget(widget)->ButtonHit(pt)) { this->HandleButtonClick(WID_RV_START_REPLACE); @@ -551,6 +619,17 @@ break; } + case WID_RV_AIRCRAFT_TYPE_DROPDOWN: { + int temp = index; + if (temp == sel_air_type) return; // we didn't select a new one. No need to change anything + sel_air_type = temp; + _autoreplace_last_selected_aircraft_type = this->sel_air_type; + this->vscroll[1]->SetPosition(0); + this->engines[1].ForceRebuild(); + this->SetDirty(); + break; + } + case WID_RV_START_REPLACE: this->ReplaceClick_StartReplace(index != 0); break; @@ -697,6 +776,60 @@ _nested_replace_vehicle_widgets, lengthof(_nested_replace_vehicle_widgets) ); +static const NWidgetPart _nested_replace_aircraft_vehicle_widgets[] = { + NWidget(NWID_HORIZONTAL), + NWidget(WWT_CLOSEBOX, COLOUR_GREY), + NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_SHADEBOX, COLOUR_GREY), + NWidget(WWT_DEFSIZEBOX, COLOUR_GREY), + NWidget(WWT_STICKYBOX, COLOUR_GREY), + EndContainer(), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), + NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0), + EndContainer(), + EndContainer(), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA), + EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_AIRCRAFT_TYPE_DROPDOWN), SetDataTip(STR_BLACK_STRING, STR_REPLACE_HELP_AIRCRAFT_TYPE_DROPDOWN), SetFill(1, 0), SetResize(1, 0), + EndContainer(), + EndContainer(), + EndContainer(), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR), + EndContainer(), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(228, 92), SetResize(1, 0), EndContainer(), + EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON), + NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0), EndContainer(), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON), + NWidget(WWT_RESIZEBOX, COLOUR_GREY), + EndContainer(), +}; + +static WindowDesc _replace_aircraft_vehicle_desc( + WDP_AUTO, "replace_vehicle_aircraft", 456, 118, + WC_REPLACE_VEHICLE, WC_NONE, + WDF_CONSTRUCTION, + _nested_replace_aircraft_vehicle_widgets, lengthof(_nested_replace_aircraft_vehicle_widgets) +); + /** * Show the autoreplace configuration window for a particular group. * @param id_g The group to replace the vehicles for. @@ -705,5 +838,11 @@ void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype) { DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype); - new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g); + if (vehicletype == VEH_TRAIN) { + new ReplaceVehicleWindow(&_replace_rail_vehicle_desc, vehicletype, id_g); + } else if (vehicletype == VEH_AIRCRAFT) { + new ReplaceVehicleWindow(&_replace_aircraft_vehicle_desc, vehicletype, id_g); + } else { + new ReplaceVehicleWindow(&_replace_vehicle_desc, vehicletype, id_g); + } } Index: src/engine_gui.h =================================================================== --- src/engine_gui.h (revision 27931) +++ src/engine_gui.h (working copy) @@ -42,4 +42,6 @@ uint GetEngineListHeight(VehicleType type); void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button); +extern int _autoreplace_last_selected_aircraft_type; + #endif /* ENGINE_GUI_H */ Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 27931) +++ src/lang/english.txt (working copy) @@ -3582,6 +3582,13 @@ STR_REPLACE_MONORAIL_VEHICLES :Monorail Vehicles STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles +STR_REPLACE_HELP_AIRCRAFT_TYPE_DROPDOWN :{BLACK}List the type of aircraft you want the left selected aircraft to be replaced with +STR_REPLACE_ALL_AIRCRAFT_TYPES :All aircraft types +STR_REPLACE_SAME_AIRCRAFT_TYPE :Same aircraft type +STR_REPLACE_HELICOPTER :Helicopter +STR_REPLACE_SMALL_AEROPLANE :Small aeroplane +STR_REPLACE_LARGE_AEROPLANE :Large aeroplane + STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal: {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing wagons (starting at the front), if replacing the engine would make the train longer Index: src/script/api/game/game_window.hpp.sq =================================================================== --- src/script/api/game/game_window.hpp.sq (revision 27931) +++ src/script/api/game/game_window.hpp.sq (working copy) @@ -228,6 +228,7 @@ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_ENGINEWAGON_DROPDOWN, "WID_RV_TRAIN_ENGINEWAGON_DROPDOWN"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_RAILTYPE_DROPDOWN, "WID_RV_TRAIN_RAILTYPE_DROPDOWN"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_WAGONREMOVE_TOGGLE, "WID_RV_TRAIN_WAGONREMOVE_TOGGLE"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_AIRCRAFT_TYPE_DROPDOWN, "WID_RV_AIRCRAFT_TYPE_DROPDOWN"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BB_BACKGROUND, "WID_BB_BACKGROUND"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BAFD_QUESTION, "WID_BAFD_QUESTION"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BAFD_YES, "WID_BAFD_YES"); Index: src/script/api/script_window.hpp =================================================================== --- src/script/api/script_window.hpp (revision 27931) +++ src/script/api/script_window.hpp (working copy) @@ -945,6 +945,9 @@ WID_RV_TRAIN_ENGINEWAGON_DROPDOWN = ::WID_RV_TRAIN_ENGINEWAGON_DROPDOWN, ///< Dropdown to select engines and/or wagons. WID_RV_TRAIN_RAILTYPE_DROPDOWN = ::WID_RV_TRAIN_RAILTYPE_DROPDOWN, ///< Dropdown menu about the railtype. WID_RV_TRAIN_WAGONREMOVE_TOGGLE = ::WID_RV_TRAIN_WAGONREMOVE_TOGGLE, ///< Button to toggle removing wagons. + + /* Aircraft only widget. */ + WID_RV_AIRCRAFT_TYPE_DROPDOWN = ::WID_RV_AIRCRAFT_TYPE_DROPDOWN, ///< Dropdown menu to select aircraft type. }; /* automatically generated from ../../widgets/bootstrap_widget.h */ Index: src/widgets/autoreplace_widget.h =================================================================== --- src/widgets/autoreplace_widget.h (revision 27931) +++ src/widgets/autoreplace_widget.h (working copy) @@ -38,6 +38,9 @@ WID_RV_TRAIN_ENGINEWAGON_DROPDOWN, ///< Dropdown to select engines and/or wagons. WID_RV_TRAIN_RAILTYPE_DROPDOWN, ///< Dropdown menu about the railtype. WID_RV_TRAIN_WAGONREMOVE_TOGGLE, ///< Button to toggle removing wagons. + + /* Aircraft only widget. */ + WID_RV_AIRCRAFT_TYPE_DROPDOWN, ///< Dropdown menu to select aircraft type. }; #endif /* WIDGETS_AUTOREPLACE_WIDGET_H */