From 8063fcb6e03f4a2d20d0b28f6b93ca9a57fd923f Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Sun, 25 Dec 2022 13:20:31 -0500 Subject: [PATCH] Feature: Ctrl-click to bulk edit timetable speeds/waiting times (#10265) --- src/command_type.h | 1 + src/lang/english.txt | 10 +++++----- src/timetable_cmd.cpp | 33 +++++++++++++++++++++++++++++++++ src/timetable_cmd.h | 10 ++++++---- src/timetable_gui.cpp | 23 ++++++++++++++++++++--- 5 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/command_type.h b/src/command_type.h index 0ce1a9a58d..d2b573b333 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -331,6 +331,7 @@ enum Commands : uint16 { CMD_MOVE_ORDER, ///< move an order CMD_CHANGE_TIMETABLE, ///< change the timetable for a vehicle + CMD_BULK_CHANGE_TIMETABLE, ///< change the timetable for all orders of a vehicle CMD_SET_VEHICLE_ON_TIME, ///< set the vehicle on time feature (timetable) CMD_AUTOFILL_TIMETABLE, ///< autofill the timetable CMD_SET_TIMETABLE_START, ///< set the date that a timetable should start diff --git a/src/lang/english.txt b/src/lang/english.txt index 9b14575ac1..dedf5b8519 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4511,22 +4511,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Start da STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable. Ctrl+Click distributes all vehicles sharing this order evenly from the given date based on their relative order, if the order is completely timetabled STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take. Ctrl+Click sets the time for all orders STR_TIMETABLE_CLEAR_TIME :{BLACK}Clear Time -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order. Ctrl+Click clears the time for all orders STR_TIMETABLE_CHANGE_SPEED :{BLACK}Change Speed Limit -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order. Ctrl+Click sets the speed for all orders STR_TIMETABLE_CLEAR_SPEED :{BLACK}Clear Speed Limit -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order. Ctrl+Click clears the speed for all orders STR_TIMETABLE_RESET_LATENESS :{BLACK}Reset Late Counter STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time STR_TIMETABLE_AUTOFILL :{BLACK}Autofill -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey (Ctrl+Click to try to keep waiting times) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey. Ctrl+Click to try to keep waiting times STR_TIMETABLE_EXPECTED :{BLACK}Expected STR_TIMETABLE_SCHEDULED :{BLACK}Scheduled diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 6f7dcca55b..f800b25ae6 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -173,6 +173,39 @@ CommandCost CmdChangeTimetable(DoCommandFlag flags, VehicleID veh, VehicleOrderI return CommandCost(); } +/** + * Change timetable data of all orders of a vehicle. + * @param flags Operation to perform. + * @param veh Vehicle with the orders to change. + * @param mtf Timetable data to change (@see ModifyTimetableFlags) + * @param data The data to modify as specified by \c mtf. + * 0 to clear times, UINT16_MAX to clear speed limit. + * @return the cost of this operation or an error + */ +CommandCost CmdBulkChangeTimetable(DoCommandFlag flags, VehicleID veh, ModifyTimetableFlags mtf, uint16 data) +{ + Vehicle *v = Vehicle::GetIfValid(veh); + if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; + + CommandCost ret = CheckOwnership(v->owner); + if (ret.Failed()) return ret; + + if (mtf >= MTF_END) return CMD_ERROR; + + if (v->GetNumOrders() == 0) return CMD_ERROR; + + if (flags & DC_EXEC) { + for (VehicleOrderID order_number = 0; order_number < v->GetNumOrders(); order_number++) { + Order *order = v->GetOrder(order_number); + if (order == nullptr || order->IsType(OT_IMPLICIT)) continue; + + Command::Do(DC_EXEC, v->index, order_number, mtf, data); + } + } + + return CommandCost(); +} + /** * Clear the lateness counter to make the vehicle on time. * @param flags Operation to perform. diff --git a/src/timetable_cmd.h b/src/timetable_cmd.h index ddf1277372..7be7982320 100644 --- a/src/timetable_cmd.h +++ b/src/timetable_cmd.h @@ -13,13 +13,15 @@ #include "command_type.h" CommandCost CmdChangeTimetable(DoCommandFlag flags, VehicleID veh, VehicleOrderID order_number, ModifyTimetableFlags mtf, uint16 data); +CommandCost CmdBulkChangeTimetable(DoCommandFlag flags, VehicleID veh, ModifyTimetableFlags mtf, uint16 data); CommandCost CmdSetVehicleOnTime(DoCommandFlag flags, VehicleID veh); CommandCost CmdAutofillTimetable(DoCommandFlag flags, VehicleID veh, bool autofill, bool preserve_wait_time); CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, Date start_date); -DEF_CMD_TRAIT(CMD_CHANGE_TIMETABLE, CmdChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_VEHICLE_ON_TIME, CmdSetVehicleOnTime, 0, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_AUTOFILL_TIMETABLE, CmdAutofillTimetable, 0, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_TIMETABLE_START, CmdSetTimetableStart, 0, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CHANGE_TIMETABLE, CmdChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_BULK_CHANGE_TIMETABLE, CmdBulkChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_SET_VEHICLE_ON_TIME, CmdSetVehicleOnTime, 0, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_AUTOFILL_TIMETABLE, CmdAutofillTimetable, 0, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_SET_TIMETABLE_START, CmdSetTimetableStart, 0, CMDT_ROUTE_MANAGEMENT) #endif /* TIMETABLE_CMD_H */ diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 7a48756f57..f6b1e3da93 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -156,6 +156,8 @@ struct TimetableWindow : Window { uint deparr_abbr_width; ///< The width of the departure/arrival abbreviation Scrollbar *vscroll; bool query_is_speed_query; ///< The currently open query window is a speed query and not a time query. + bool set_start_date_all; ///< Set start date using minutes text entry for all timetable entries (ctrl-click) action + bool change_timetable_all; ///< Set wait time or speed for all timetable entries (ctrl-click) action TimetableWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc), @@ -551,6 +553,7 @@ struct TimetableWindow : Window { } this->query_is_speed_query = false; + this->change_timetable_all = _ctrl_pressed && (order != nullptr); ShowQueryString(current, STR_TIMETABLE_CHANGE_TIME, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED); break; } @@ -571,19 +574,28 @@ struct TimetableWindow : Window { } this->query_is_speed_query = true; + this->change_timetable_all = _ctrl_pressed && (order != nullptr); ShowQueryString(current, STR_TIMETABLE_CHANGE_SPEED, 31, this, CS_NUMERAL, QSF_NONE); break; } case WID_VT_CLEAR_TIME: { // Clear waiting time. auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, false); - Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, 0); + if (_ctrl_pressed) { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, 0); + } else { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, 0); + } break; } case WID_VT_CLEAR_SPEED: { // Clear max speed button. auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, true); - Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, UINT16_MAX); + if (_ctrl_pressed) { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, UINT16_MAX); + } else { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, UINT16_MAX); + } break; } @@ -622,7 +634,12 @@ struct TimetableWindow : Window { } auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, this->query_is_speed_query); - Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, std::min(val, UINT16_MAX)); + + if (this->change_timetable_all) { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, mtf, std::min(val, UINT16_MAX)); + } else { + Command::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, v->index, order_id, mtf, std::min(val, UINT16_MAX)); + } } void OnResize() override