OpenTTD Source 20260421-master-gc2fbc6fdeb
order_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "command_func.h"
12#include "viewport_func.h"
13#include "depot_map.h"
14#include "roadveh.h"
15#include "timetable.h"
16#include "strings_func.h"
17#include "company_func.h"
18#include "dropdown_type.h"
19#include "dropdown_func.h"
20#include "textbuf_gui.h"
21#include "string_func.h"
22#include "tilehighlight_func.h"
23#include "network/network.h"
24#include "station_base.h"
25#include "industry.h"
26#include "waypoint_base.h"
28#include "hotkeys.h"
29#include "aircraft.h"
30#include "engine_func.h"
31#include "vehicle_func.h"
32#include "vehiclelist.h"
33#include "vehicle_func.h"
34#include "error.h"
35#include "order_cmd.h"
36#include "company_cmd.h"
38
40
41#include "table/strings.h"
42
43#include "safeguards.h"
44
45
47static const StringID _station_load_types[][5][5] = {
48 {
49 /* No refitting. */
50 {
53 STR_ORDER_FULL_LOAD,
54 STR_ORDER_FULL_LOAD_ANY,
55 STR_ORDER_NO_LOAD,
56 }, {
57 STR_ORDER_UNLOAD,
59 STR_ORDER_UNLOAD_FULL_LOAD,
60 STR_ORDER_UNLOAD_FULL_LOAD_ANY,
61 STR_ORDER_UNLOAD_NO_LOAD,
62 }, {
63 STR_ORDER_TRANSFER,
65 STR_ORDER_TRANSFER_FULL_LOAD,
66 STR_ORDER_TRANSFER_FULL_LOAD_ANY,
67 STR_ORDER_TRANSFER_NO_LOAD,
68 }, {
69 /* Unload and transfer do not work together. */
75 }, {
76 STR_ORDER_NO_UNLOAD,
78 STR_ORDER_NO_UNLOAD_FULL_LOAD,
79 STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY,
80 STR_ORDER_NO_UNLOAD_NO_LOAD,
81 }
82 }, {
83 /* With auto-refitting. No loading and auto-refitting do not work together. */
84 {
85 STR_ORDER_AUTO_REFIT,
87 STR_ORDER_FULL_LOAD_REFIT,
88 STR_ORDER_FULL_LOAD_ANY_REFIT,
90 }, {
91 STR_ORDER_UNLOAD_REFIT,
93 STR_ORDER_UNLOAD_FULL_LOAD_REFIT,
94 STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT,
96 }, {
97 STR_ORDER_TRANSFER_REFIT,
99 STR_ORDER_TRANSFER_FULL_LOAD_REFIT,
100 STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT,
102 }, {
103 /* Unload and transfer do not work together. */
109 }, {
110 STR_ORDER_NO_UNLOAD_REFIT,
112 STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT,
113 STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT,
115 }
116 }
117};
118
119static const StringID _order_non_stop_dropdown[] = {
120 STR_ORDER_GO_TO,
121 STR_ORDER_GO_NON_STOP_TO,
122 STR_ORDER_GO_VIA,
123 STR_ORDER_GO_NON_STOP_VIA,
124};
125
126static const StringID _order_full_load_dropdown[] = {
127 STR_ORDER_DROP_LOAD_IF_POSSIBLE,
128 STR_EMPTY,
129 STR_ORDER_DROP_FULL_LOAD_ALL,
130 STR_ORDER_DROP_FULL_LOAD_ANY,
131 STR_ORDER_DROP_NO_LOADING,
132};
133
134static const StringID _order_unload_dropdown[] = {
135 STR_ORDER_DROP_UNLOAD_IF_ACCEPTED,
136 STR_ORDER_DROP_UNLOAD,
137 STR_ORDER_DROP_TRANSFER,
138 STR_EMPTY,
139 STR_ORDER_DROP_NO_UNLOADING,
140};
141
142static const StringID _order_goto_dropdown[] = {
143 STR_ORDER_GO_TO,
144 STR_ORDER_GO_TO_NEAREST_DEPOT,
145 STR_ORDER_CONDITIONAL,
146 STR_ORDER_SHARE,
147};
148
149static const StringID _order_goto_dropdown_aircraft[] = {
150 STR_ORDER_GO_TO,
151 STR_ORDER_GO_TO_NEAREST_HANGAR,
152 STR_ORDER_CONDITIONAL,
153 STR_ORDER_SHARE,
154};
155
168
169static const StringID _order_conditional_condition[] = {
170 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,
171 STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,
172 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,
173 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS,
174 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,
175 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS,
176 STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,
177 STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,
178};
179
180extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type);
181extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type);
182
183static const StringID _order_depot_action_dropdown[] = {
184 STR_ORDER_DROP_GO_ALWAYS_DEPOT,
185 STR_ORDER_DROP_SERVICE_DEPOT,
186 STR_ORDER_DROP_HALT_DEPOT,
187 STR_ORDER_DROP_UNBUNCH,
188};
189
190static OrderDepotAction DepotActionStringIndex(const Order *order)
191{
196}
197
198static const StringID _order_refit_action_dropdown[] = {
199 STR_ORDER_DROP_REFIT_AUTO,
200 STR_ORDER_DROP_REFIT_AUTO_ANY,
201};
202
203static StringID GetOrderGoToString(const Order &order)
204{
206 return order.GetNonStopType().Test(OrderNonStopFlag::NonStop) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT;
207 } else {
208 return order.GetNonStopType().Test(OrderNonStopFlag::NonStop) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO;
209 }
210}
211
224void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_index, int y, bool selected, bool timetable, int left, int middle, int right)
225{
226 bool rtl = _current_text_dir == TD_RTL;
227
228 SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
229 Dimension sprite_size = GetSpriteSize(sprite);
230 if (v->cur_real_order_index == order_index) {
231 /* Draw two arrows before the next real order. */
232 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FontSize::Normal) - (int)sprite_size.height) / 2);
233 DrawSprite(sprite, PAL_NONE, rtl ? right - 2 * sprite_size.width : left + sprite_size.width, y + ((int)GetCharacterHeight(FontSize::Normal) - (int)sprite_size.height) / 2);
234 } else if (v->cur_implicit_order_index == order_index) {
235 /* Draw one arrow before the next implicit order; the next real order will still get two arrows. */
236 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FontSize::Normal) - (int)sprite_size.height) / 2);
237 }
238
239 TextColour colour = TC_BLACK;
240 if (order->IsType(OT_IMPLICIT)) {
241 colour = (selected ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
242 } else if (selected) {
243 colour = TC_WHITE;
244 }
245
246 DrawString(left, rtl ? right - 2 * sprite_size.width - 3 : middle, y, GetString(STR_ORDER_INDEX, order_index + 1), colour, SA_RIGHT | SA_FORCE);
247
248 std::string line;
249
250 switch (order->GetType()) {
251 case OT_DUMMY:
252 line = GetString(STR_INVALID_ORDER);
253 break;
254
255 case OT_IMPLICIT:
256 line = GetString(STR_ORDER_GO_TO_STATION, STR_ORDER_GO_TO, order->GetDestination());
257 if (!timetable) line += GetString(STR_ORDER_IMPLICIT);
258 break;
259
260 case OT_GOTO_STATION: {
261 OrderLoadType load = order->GetLoadType();
262 OrderUnloadType unload = order->GetUnloadType();
263 bool valid_station = CanVehicleUseStation(v, Station::Get(order->GetDestination().ToStationID()));
264
265 line = GetString(valid_station ? STR_ORDER_GO_TO_STATION : STR_ORDER_GO_TO_STATION_CAN_T_USE_STATION, STR_ORDER_GO_TO + (v->IsGroundVehicle() ? order->GetNonStopType() : OrderNonStopFlags{}).base(), order->GetDestination());
266 if (timetable) {
267 /* Show only wait time in the timetable window. */
268 if (order->GetWaitTime() > 0) {
269 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
270 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED, str, value);
271 }
272 } else {
273 /* Show non-stop, refit and stop location only in the order window. */
275 StringID str = _station_load_types[order->IsRefit()][to_underlying(unload)][to_underlying(load)];
276 if (str != INVALID_STRING_ID) {
277 if (order->IsRefit()) {
278 line += GetString(str, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name);
279 } else {
280 line += GetString(str);
281 }
282 }
283 }
284
285 if (v->type == VEH_TRAIN && !order->GetNonStopType().Test(OrderNonStopFlag::GoVia)) {
286 /* Only show the stopping location if other than the default chosen by the player. */
287 if (order->GetStopLocation() != _settings_client.gui.stop_location) {
288 line += GetString(STR_ORDER_STOP_LOCATION_NEAR_END + to_underlying(order->GetStopLocation()));
289 }
290 }
291 }
292 break;
293 }
294
295 case OT_GOTO_DEPOT:
297 /* Going to a specific depot. */
298 line = GetString(STR_ORDER_GO_TO_DEPOT_FORMAT, GetOrderGoToString(*order), v->type, order->GetDestination());
299 } else if (v->type == VEH_AIRCRAFT) {
300 /* Going to the nearest hangar. */
301 line = GetString(STR_ORDER_GO_TO_NEAREST_HANGAR_FORMAT, GetOrderGoToString(*order));
302 } else {
303 /* Going to the nearest depot. */
304 line = GetString(STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT, GetOrderGoToString(*order), STR_ORDER_TRAIN_DEPOT + v->type);
305 }
306
307 /* Do not show stopping in the depot in the timetable window. */
308 if (!timetable && order->GetDepotActionType().Test(OrderDepotActionFlag::Halt)) {
309 line += GetString(STR_ORDER_STOP_ORDER);
310 }
311
312 /* Do not show refitting in the depot in the timetable window. */
313 if (!timetable && order->IsRefit()) {
314 line += GetString(order->GetDepotActionType().Test(OrderDepotActionFlag::Halt) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER, CargoSpec::Get(order->GetRefitCargo())->name);
315 }
316
317 /* Show unbunching depot in both order and timetable windows. */
319 line += GetString(STR_ORDER_WAIT_TO_UNBUNCH);
320 }
321 break;
322
323 case OT_GOTO_WAYPOINT:
324 line = GetString(order->GetNonStopType().Test(OrderNonStopFlag::NonStop) ? STR_ORDER_GO_NON_STOP_TO_WAYPOINT : STR_ORDER_GO_TO_WAYPOINT, order->GetDestination());
325 break;
326
327 case OT_CONDITIONAL:
329 line = GetString(STR_ORDER_CONDITIONAL_UNCONDITIONAL, order->GetConditionSkipToOrder() + 1);
330 } else {
332
333 uint value = order->GetConditionValue();
335
336 line = GetString((occ == OrderConditionComparator::IsTrue || occ == OrderConditionComparator::IsFalse) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM,
337 order->GetConditionSkipToOrder() + 1,
338 STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + to_underlying(order->GetConditionVariable()),
339 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + to_underlying(occ),
340 value);
341 }
342
343 if (timetable && order->GetWaitTime() > 0) {
344 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
345 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_AND_TRAVEL_FOR : STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED, str, value);
346 }
347 break;
348
349 default: NOT_REACHED();
350 }
351
352 /* Check range for aircraft. */
353 if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->GetRange() > 0 && order->IsGotoOrder()) {
354 if (GetOrderDistance(order_index, v->orders->GetNext(order_index), v) > Aircraft::From(v)->acache.cached_max_range_sqr) {
355 line += GetString(STR_ORDER_OUT_OF_RANGE);
356 }
357 }
358
359 DrawString(rtl ? left : middle, rtl ? middle : right, y, line, colour);
360}
361
369{
370 Order order{};
371
372 /* check depot first */
373 if (IsDepotTypeTile(tile, (TransportType)(uint)v->type) && IsTileOwner(tile, _local_company)) {
376 (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? OrderNonStopFlag::NonStop : OrderNonStopFlags{});
377
378 if (_ctrl_pressed) {
379 /* Now we are allowed to set the action type. */
381 }
382
383 return order;
384 }
385
386 /* check rail waypoint */
387 if (IsRailWaypointTile(tile) &&
388 v->type == VEH_TRAIN &&
392 return order;
393 }
394
395 /* check road waypoint */
396 if (IsRoadWaypointTile(tile) &&
397 v->type == VEH_ROAD &&
401 return order;
402 }
403
404 /* check buoy (no ownership) */
405 if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
407 return order;
408 }
409
410 /* check for station or industry with neutral station */
412 const Station *st = nullptr;
413
414 if (IsTileType(tile, TileType::Station)) {
415 st = Station::GetByTile(tile);
416 } else {
417 const Industry *in = Industry::GetByTile(tile);
418 st = in->neutral_station;
419 }
420 if (st != nullptr && (st->owner == _local_company || st->owner == OWNER_NONE)) {
421 StationFacilities facil;
422 switch (v->type) {
423 case VEH_SHIP: facil = StationFacility::Dock; break;
424 case VEH_TRAIN: facil = StationFacility::Train; break;
425 case VEH_AIRCRAFT: facil = StationFacility::Airport; break;
427 default: NOT_REACHED();
428 }
429 if (st->facilities.Any(facil)) {
430 order.MakeGoToStation(st->index);
434 return order;
435 }
436 }
437 }
438
439 /* not found */
440 order.Free();
441 return order;
442}
443
445enum OrderHotKeys : int32_t {
446 OHK_SKIP,
447 OHK_DELETE,
448 OHK_GOTO,
449 OHK_NONSTOP,
450 OHK_FULLLOAD,
451 OHK_UNLOAD,
452 OHK_NEAREST_DEPOT,
453 OHK_ALWAYS_SERVICE,
454 OHK_TRANSFER,
455 OHK_NO_UNLOAD,
456 OHK_NO_LOAD,
457};
458
499struct OrdersWindow : public Window {
500private:
502 enum OrderPlaceObjectState : uint8_t {
503 OPOS_NONE,
504 OPOS_GOTO,
505 OPOS_CONDITIONAL,
506 OPOS_SHARE,
507 OPOS_END,
508 };
509
511 enum DisplayPane : uint8_t {
512 /* WID_O_SEL_TOP_ROW_GROUNDVEHICLE */
515
516 /* WID_O_SEL_TOP_LEFT */
519
520 /* WID_O_SEL_TOP_MIDDLE */
523
524 /* WID_O_SEL_TOP_RIGHT */
527
528 /* WID_O_SEL_TOP_ROW */
532
533 /* WID_O_SEL_BOTTOM_MIDDLE */
536 };
537
538 int selected_order = -1;
540 OrderPlaceObjectState goto_type = OPOS_NONE;
541 const Vehicle *vehicle = nullptr;
542 Scrollbar *vscroll = nullptr;
543 bool can_do_refit = false;
544 bool can_do_autorefit = false;
545
552 {
553 int num = this->selected_order;
554 return (num >= 0 && num < vehicle->GetNumOrders()) ? num : vehicle->GetNumOrders();
555 }
556
566 {
567 int32_t sel = this->vscroll->GetScrolledRowFromWidget(y, this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.top);
568 if (sel == INT32_MAX) return INVALID_VEH_ORDER_ID;
569 /* One past the orders is the 'End of Orders' line. */
570 assert(IsInsideBS(sel, 0, vehicle->GetNumOrders() + 1));
571 return sel;
572 }
573
579 {
580 assert(type > OPOS_NONE && type < OPOS_END);
581
582 static const HighLightStyle goto_place_style[OPOS_END - 1] = {
583 HT_RECT | HT_VEHICLE, // OPOS_GOTO
584 HT_NONE, // OPOS_CONDITIONAL
585 HT_VEHICLE, // OPOS_SHARE
586 };
587 SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, goto_place_style[type - 1], this);
588 this->goto_type = type;
590 }
591
597 void OrderClick_FullLoad(OrderLoadType load_type, bool toggle = false)
598 {
599 VehicleOrderID sel_ord = this->OrderGetSel();
600 const Order *order = this->vehicle->GetOrder(sel_ord);
601
602 if (order == nullptr) return;
603
604 if (toggle && order->GetLoadType() == load_type) {
605 load_type = OrderLoadType::LoadIfPossible; // reset to 'default'
606 }
607 if (order->GetLoadType() == load_type) return; // If we still match, do nothing
608
609 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, to_underlying(load_type));
610 }
611
616 void OrderClick_Service(std::optional<OrderDepotAction> i)
617 {
618 VehicleOrderID sel_ord = this->OrderGetSel();
619
620 if (!i.has_value()) {
621 const Order *order = this->vehicle->GetOrder(sel_ord);
622 if (order == nullptr) return;
624 }
625 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_DEPOT_ACTION, to_underlying(i.value()));
626 }
627
632 {
633 Order order{};
634 order.MakeGoToDepot(DepotID::Invalid(), OrderDepotTypeFlag::PartOfOrders,
635 _settings_client.gui.new_nonstop && this->vehicle->IsGroundVehicle() ? OrderNonStopFlag::NonStop : OrderNonStopFlags{});
637
638 Command<Commands::InsertOrder>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
639 }
640
646 void OrderClick_Unload(OrderUnloadType unload_type, bool toggle = false)
647 {
648 VehicleOrderID sel_ord = this->OrderGetSel();
649 const Order *order = this->vehicle->GetOrder(sel_ord);
650
651 if (order == nullptr) return;
652
653 if (toggle && order->GetUnloadType() == unload_type) {
655 }
656 if (order->GetUnloadType() == unload_type) return; // If we still match, do nothing
657
658 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_UNLOAD, to_underlying(unload_type));
659
660 /* Transfer and unload orders with leave empty as default */
661 if (unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload) {
662 Command<Commands::ModifyOrder>::Post(this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, to_underlying(OrderLoadType::NoLoad));
664 }
665 }
666
671 void OrderClick_Nonstop(std::optional<OrderNonStopFlags> non_stop)
672 {
673 if (!this->vehicle->IsGroundVehicle()) return;
674
675 VehicleOrderID sel_ord = this->OrderGetSel();
676 const Order *order = this->vehicle->GetOrder(sel_ord);
677
678 if (order == nullptr || order->GetNonStopType() == non_stop) return;
679
680 /* Keypress if no value, so 'toggle' to the next */
681 if (!non_stop.has_value()) {
682 non_stop = order->GetNonStopType().Flip(OrderNonStopFlag::NonStop);
683 }
684
686 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_NON_STOP, non_stop.value().base());
687 }
688
694 {
695 /* Don't skip when there's nothing to skip */
696 if (_ctrl_pressed && this->vehicle->cur_implicit_order_index == this->OrderGetSel()) return;
697 if (this->vehicle->GetNumOrders() <= 1) return;
698
699 Command<Commands::SkipToOrder>::Post(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER,
700 this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_implicit_order_index + 1) % this->vehicle->GetNumOrders()));
701 }
702
707 {
708 /* When networking, move one order lower */
709 int selected = this->selected_order + (int)_networking;
710
711 if (Command<Commands::DeleteOrder>::Post(STR_ERROR_CAN_T_DELETE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel())) {
712 this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected;
713 this->UpdateButtonState();
714 }
715 }
716
724 {
725 /* Don't try to stop sharing orders if 'End of Shared Orders' isn't selected. */
726 if (!this->vehicle->IsOrderListShared() || this->selected_order != this->vehicle->GetNumOrders()) return;
727 /* If Ctrl is pressed, delete the order list as if we clicked the 'Delete' button. */
728 if (_ctrl_pressed) {
729 this->OrderClick_Delete();
730 return;
731 }
732
733 /* Get another vehicle that share orders with this vehicle. */
734 Vehicle *other_shared = (this->vehicle->FirstShared() == this->vehicle) ? this->vehicle->NextShared() : this->vehicle->PreviousShared();
735 /* Copy the order list of the other vehicle. */
736 if (Command<Commands::CloneOrder>::Post(STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST, this->vehicle->tile, CO_COPY, this->vehicle->index, other_shared->index)) {
737 this->UpdateButtonState();
738 }
739 }
740
747 void OrderClick_Refit(int i, bool auto_refit)
748 {
749 if (_ctrl_pressed) {
750 /* Cancel refitting */
751 Command<Commands::OrderRefit>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_NO_REFIT);
752 } else {
753 if (i == 1) { // Auto-refit to available cargo type.
754 Command<Commands::OrderRefit>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_AUTO_REFIT);
755 } else {
756 ShowVehicleRefitWindow(this->vehicle, this->OrderGetSel(), this, auto_refit);
757 }
758 }
759 }
760
763 {
764 this->can_do_refit = false;
765 this->can_do_autorefit = false;
766 for (const Vehicle *w = this->vehicle; w != nullptr; w = w->IsGroundVehicle() ? w->Next() : nullptr) {
767 if (IsEngineRefittable(w->engine_type)) this->can_do_refit = true;
768 if (Engine::Get(w->engine_type)->info.misc_flags.Test(EngineMiscFlag::AutoRefit)) this->can_do_autorefit = true;
769 }
770 }
771
772public:
773 OrdersWindow(WindowDesc &desc, const Vehicle *v) : Window(desc)
774 {
775 this->vehicle = v;
776
777 this->CreateNestedTree();
778 this->vscroll = this->GetScrollbar(WID_O_SCROLLBAR);
779 if (NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_O_DEPOT_ACTION); nwid != nullptr) {
780 nwid->SetToolTip(STR_ORDER_TRAIN_DEPOT_ACTION_TOOLTIP + v->type);
781 }
782 this->FinishInitNested(v->index);
783
784 this->owner = v->owner;
785
786 this->UpdateAutoRefitState();
787
789 /* If there are less than 2 station, make Go To active. */
790 int station_orders = std::ranges::count_if(v->Orders(), [](const Order &order) { return order.IsType(OT_GOTO_STATION); });
791
792 if (station_orders < 2) this->OrderClick_Goto(OPOS_GOTO);
793 }
795 }
796
797 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
798 {
799 switch (widget) {
800 case WID_O_ORDER_LIST:
801 fill.height = resize.height = GetCharacterHeight(FontSize::Normal);
802 size.height = 6 * resize.height + padding.height;
803 break;
804
805 case WID_O_COND_VARIABLE: {
806 Dimension d = {0, 0};
807 for (const auto &ocv : _order_conditional_variable) {
808 d = maxdim(d, GetStringBoundingBox(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + to_underlying(ocv)));
809 }
810 d.width += padding.width;
811 d.height += padding.height;
812 size = maxdim(size, d);
813 break;
814 }
815
817 Dimension d = GetStringListBoundingBox(_order_conditional_condition);
818 d.width += padding.width;
819 d.height += padding.height;
820 size = maxdim(size, d);
821 break;
822 }
823
824 case WID_O_DELETE: {
825 Dimension d = maxdim(GetStringBoundingBox(STR_ORDERS_DELETE_BUTTON), GetStringBoundingBox(STR_ORDERS_DELETE_ALL_BUTTON));
826 d.width += padding.width;
827 d.height += padding.height;
828 size = maxdim(size, d);
829 break;
830 }
831 }
832 }
833
839 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
840 {
843
844 switch (data) {
845 case VIWD_AUTOREPLACE:
846 /* Autoreplace replaced the vehicle */
847 this->vehicle = Vehicle::Get(this->window_number);
848 [[fallthrough]];
849
851 /* Vehicle composition was changed. */
852 this->UpdateAutoRefitState();
853 break;
854
856 /* Removed / replaced all orders (after deleting / sharing) */
857 if (this->selected_order == -1) break;
858
859 this->CloseChildWindows();
860 this->selected_order = -1;
861 break;
862
864 /* Some other order changes */
865 break;
866
867 default:
868 if (data < 0) break;
869
870 if (gui_scope) break; // only do this once; from command scope
871 from = GB(data, 0, 8);
872 to = GB(data, 8, 8);
873 /* Moving an order. If one of these is INVALID_VEH_ORDER_ID, then
874 * the order is being created / removed */
875 if (this->selected_order == -1) break;
876
877 if (from == to) break; // no need to change anything
878
879 if (from != this->selected_order) {
880 /* Moving from preceding order? */
881 this->selected_order -= (int)(from <= this->selected_order);
882 /* Moving to preceding order? */
883 this->selected_order += (int)(to <= this->selected_order);
884 break;
885 }
886
887 /* Now we are modifying the selected order */
888 if (to == INVALID_VEH_ORDER_ID) {
889 /* Deleting selected order */
890 this->CloseChildWindows();
891 this->selected_order = -1;
892 break;
893 }
894
895 /* Moving selected order */
896 this->selected_order = to;
897 break;
898 }
899
900 this->vscroll->SetCount(this->vehicle->GetNumOrders() + 1);
901 if (gui_scope) this->UpdateButtonState();
902
903 /* Scroll to the new order. */
904 if (from == INVALID_VEH_ORDER_ID && to != INVALID_VEH_ORDER_ID && !this->vscroll->IsVisible(to)) {
905 this->vscroll->ScrollTowards(to);
906 }
907 }
908
909 void UpdateButtonState()
910 {
911 if (this->vehicle->owner != _local_company) return; // No buttons are displayed with competitor order windows.
912
913 bool shared_orders = this->vehicle->IsOrderListShared();
914 VehicleOrderID sel = this->OrderGetSel();
915 const Order *order = this->vehicle->GetOrder(sel);
916
917 /* Second row. */
918 /* skip */
919 this->SetWidgetDisabledState(WID_O_SKIP, this->vehicle->GetNumOrders() <= 1);
920
921 /* delete / stop sharing */
923 if (shared_orders && this->selected_order == this->vehicle->GetNumOrders()) {
924 /* The 'End of Shared Orders' order is selected, show the 'stop sharing' button. */
926 } else {
927 /* The 'End of Shared Orders' order isn't selected, show the 'delete' button. */
930 (uint)this->vehicle->GetNumOrders() + ((shared_orders || this->vehicle->GetNumOrders() != 0) ? 1 : 0) <= (uint)this->selected_order);
931
932 /* Set the tooltip of the 'delete' button depending on whether the
933 * 'End of Orders' order or a regular order is selected. */
934 NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_O_DELETE);
935 if (this->selected_order == this->vehicle->GetNumOrders()) {
936 nwi->SetStringTip(STR_ORDERS_DELETE_ALL_BUTTON, STR_ORDERS_DELETE_ALL_TOOLTIP);
937 } else {
938 nwi->SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP);
939 }
940 }
941
942 /* First row. */
945
946 /* Selection widgets. */
947 /* Train or road vehicle. */
948 NWidgetStacked *train_row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW_GROUNDVEHICLE);
949 NWidgetStacked *left_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_LEFT);
950 NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_MIDDLE);
951 NWidgetStacked *right_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_RIGHT);
952 /* Ship or airplane. */
953 NWidgetStacked *row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW);
954 assert(row_sel != nullptr || (train_row_sel != nullptr && left_sel != nullptr && middle_sel != nullptr && right_sel != nullptr));
955
956
957 if (order == nullptr) {
958 if (row_sel != nullptr) {
960 } else {
967 }
971 } else {
974
975 switch (order->GetType()) {
976 case OT_GOTO_STATION:
977 if (row_sel != nullptr) {
979 } else {
986 }
989
990 /* Can only do refitting when stopping at the destination and loading cargo.
991 * Also enable the button if a refit is already set to allow clearing it. */
994 ((!this->can_do_refit || !this->can_do_autorefit) && !order->IsRefit()));
995
996 break;
997
998 case OT_GOTO_WAYPOINT:
999 if (row_sel != nullptr) {
1001 } else {
1008 }
1012 break;
1013
1014 case OT_GOTO_DEPOT:
1015 if (row_sel != nullptr) {
1017 } else {
1024 }
1025 /* Disable refit button if the order is no 'always go' order.
1026 * However, keep the service button enabled for refit-orders to allow clearing refits (without knowing about ctrl). */
1029 (!this->can_do_refit && !order->IsRefit()));
1030 break;
1031
1032 case OT_CONDITIONAL: {
1033 if (row_sel != nullptr) {
1035 } else {
1037 }
1039 /* Set the strings for the dropdown boxes. */
1040 this->GetWidget<NWidgetCore>(WID_O_COND_VARIABLE)->SetString(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + to_underlying(ocv));
1041 this->GetWidget<NWidgetCore>(WID_O_COND_COMPARATOR)->SetString(_order_conditional_condition[to_underlying(order->GetConditionComparator())]);
1044 break;
1045 }
1046
1047 default: // every other order
1048 if (row_sel != nullptr) {
1050 } else {
1056 }
1060 break;
1061 }
1062 }
1063
1064 /* Disable list of vehicles with the same shared orders if there is no list */
1065 this->SetWidgetDisabledState(WID_O_SHARED_ORDER_LIST, !shared_orders);
1066
1067 this->SetDirty();
1068 }
1069
1070 void OnPaint() override
1071 {
1072 if (this->vehicle->owner != _local_company) {
1073 this->selected_order = -1; // Disable selection any selected row at a competitor order window.
1074 } else {
1075 this->SetWidgetLoweredState(WID_O_GOTO, this->goto_type != OPOS_NONE);
1076 }
1077 this->DrawWidgets();
1078 }
1079
1080 void DrawWidget(const Rect &r, WidgetID widget) const override
1081 {
1082 if (widget != WID_O_ORDER_LIST) return;
1083
1084 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
1085 bool rtl = _current_text_dir == TD_RTL;
1086 uint64_t max_value = GetParamMaxValue(this->vehicle->GetNumOrders(), 2);
1087 int index_column_width = GetStringBoundingBox(GetString(STR_ORDER_INDEX, max_value)).width + 2 * GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + WidgetDimensions::scaled.hsep_normal;
1088 int middle = rtl ? ir.right - index_column_width : ir.left + index_column_width;
1089
1090 int y = ir.top;
1091 int line_height = this->GetWidget<NWidgetBase>(WID_O_ORDER_LIST)->resize_y;
1092
1093 VehicleOrderID i = this->vscroll->GetPosition();
1094 VehicleOrderID num_orders = this->vehicle->GetNumOrders();
1095
1096 /* First draw the highlighting underground if it exists. */
1097 if (this->order_over != INVALID_VEH_ORDER_ID) {
1098 while (i < num_orders) {
1099 /* Don't draw anything if it extends past the end of the window. */
1100 if (!this->vscroll->IsVisible(i)) break;
1101
1102 if (i != this->selected_order && i == this->order_over) {
1103 /* Highlight dragged order destination. */
1104 int top = (this->order_over < this->selected_order ? y : y + line_height) - WidgetDimensions::scaled.framerect.top;
1105 int bottom = std::min(top + 2, ir.bottom);
1106 top = std::max(top - 3, ir.top);
1107 GfxFillRect(ir.left, top, ir.right, bottom, GetColourGradient(Colours::Grey, SHADE_LIGHTEST));
1108 break;
1109 }
1110 y += line_height;
1111
1112 i++;
1113 }
1114
1115 /* Reset counters for drawing the orders. */
1116 y = ir.top;
1117 i = this->vscroll->GetPosition();
1118 }
1119
1120 /* Draw the orders. */
1121 while (i < num_orders) {
1122 /* Don't draw anything if it extends past the end of the window. */
1123 if (!this->vscroll->IsVisible(i)) break;
1124
1125 DrawOrderString(this->vehicle, this->vehicle->GetOrder(i), i, y, i == this->selected_order, false, ir.left, middle, ir.right);
1126 y += line_height;
1127
1128 i++;
1129 }
1130
1131 if (this->vscroll->IsVisible(i)) {
1132 StringID str = this->vehicle->IsOrderListShared() ? STR_ORDERS_END_OF_SHARED_ORDERS : STR_ORDERS_END_OF_ORDERS;
1133 DrawString(rtl ? ir.left : middle, rtl ? middle : ir.right, y, str, (i == this->selected_order) ? TC_WHITE : TC_BLACK);
1134 }
1135 }
1136
1137 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1138 {
1139 switch (widget) {
1140 case WID_O_COND_VALUE: {
1141 VehicleOrderID sel = this->OrderGetSel();
1142 const Order *order = this->vehicle->GetOrder(sel);
1143
1144 if (order != nullptr && order->IsType(OT_CONDITIONAL)) {
1145 uint value = order->GetConditionValue();
1146 if (order->GetConditionVariable() == OrderConditionVariable::MaxSpeed) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1147 return GetString(STR_JUST_COMMA, value);
1148 }
1149 return {};
1150 }
1151
1152 case WID_O_CAPTION:
1153 return GetString(STR_ORDERS_CAPTION, this->vehicle->index);
1154
1155 case WID_O_DEPOT_ACTION: {
1156 VehicleOrderID sel = this->OrderGetSel();
1157 const Order *order = this->vehicle->GetOrder(sel);
1158 if (order == nullptr || !order->IsType(OT_GOTO_DEPOT)) return {};
1159
1160 /* Select the current action selected in the dropdown. The flags don't match the dropdown so we can't just use an index. */
1161 if (order->GetDepotOrderType().Test(OrderDepotTypeFlag::Service)) return GetString(STR_ORDER_DROP_SERVICE_DEPOT);
1162 if (order->GetDepotActionType().Test(OrderDepotActionFlag::Halt)) return GetString(STR_ORDER_DROP_HALT_DEPOT);
1163 if (order->GetDepotActionType().Test(OrderDepotActionFlag::Unbunch)) return GetString(STR_ORDER_DROP_UNBUNCH);
1164
1165 return GetString(STR_ORDER_DROP_GO_ALWAYS_DEPOT);
1166 }
1167
1168 default:
1169 return this->Window::GetWidgetString(widget, stringid);
1170 }
1171 }
1172
1173 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1174 {
1175 switch (widget) {
1176 case WID_O_ORDER_LIST: {
1177 if (this->goto_type == OPOS_CONDITIONAL) {
1178 VehicleOrderID order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
1179 if (order_id != INVALID_VEH_ORDER_ID) {
1180 Order order{};
1181 order.MakeConditional(order_id);
1182
1183 Command<Commands::InsertOrder>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
1184 }
1186 break;
1187 }
1188
1189 VehicleOrderID sel = this->GetOrderFromPt(pt.y);
1190
1191 if (_ctrl_pressed && sel < this->vehicle->GetNumOrders()) {
1192 TileIndex xy = this->vehicle->GetOrder(sel)->GetLocation(this->vehicle);
1193 if (xy != INVALID_TILE) ScrollMainWindowToTile(xy);
1194 return;
1195 }
1196
1197 /* This order won't be selected any more, close all child windows and dropdowns */
1198 this->CloseChildWindows();
1199
1200 if (sel == INVALID_VEH_ORDER_ID || this->vehicle->owner != _local_company) {
1201 /* Deselect clicked order */
1202 this->selected_order = -1;
1203 } else if (sel == this->selected_order && click_count > 1) {
1204 if (this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
1205 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER,
1206 this->vehicle->tile, this->vehicle->index, sel,
1208 }
1209 } else {
1210 /* Select clicked order */
1211 this->selected_order = sel;
1212
1213 if (this->vehicle->owner == _local_company) {
1214 /* Activate drag and drop */
1216 }
1217 }
1218
1219 this->UpdateButtonState();
1220 break;
1221 }
1222
1223 case WID_O_SKIP:
1224 this->OrderClick_Skip();
1225 break;
1226
1227 case WID_O_DELETE:
1228 this->OrderClick_Delete();
1229 break;
1230
1231 case WID_O_STOP_SHARING:
1232 this->OrderClick_StopSharing();
1233 break;
1234
1235 case WID_O_NON_STOP:
1236 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1237 this->OrderClick_Nonstop(std::nullopt);
1238 } else {
1239 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1240 assert(o != nullptr);
1241 ShowDropDownMenu(this, _order_non_stop_dropdown, o->GetNonStopType().base(), WID_O_NON_STOP, 0,
1242 o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
1243 }
1244 break;
1245
1246 case WID_O_GOTO:
1247 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1248 if (this->goto_type != OPOS_NONE) {
1250 } else {
1251 this->OrderClick_Goto(OPOS_GOTO);
1252 }
1253 } else {
1254 int sel;
1255 switch (this->goto_type) {
1256 case OPOS_NONE: sel = -1; break;
1257 case OPOS_GOTO: sel = 0; break;
1258 case OPOS_CONDITIONAL: sel = 2; break;
1259 case OPOS_SHARE: sel = 3; break;
1260 default: NOT_REACHED();
1261 }
1262 ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, sel, WID_O_GOTO, 0, 0);
1263 }
1264 break;
1265
1266 case WID_O_FULL_LOAD:
1267 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1269 } else {
1270 ShowDropDownMenu(this, _order_full_load_dropdown, to_underlying(this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType()), WID_O_FULL_LOAD, 0, 2);
1271 }
1272 break;
1273
1274 case WID_O_UNLOAD:
1275 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1277 } else {
1278 ShowDropDownMenu(this, _order_unload_dropdown, to_underlying(this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType()), WID_O_UNLOAD, 0, 8);
1279 }
1280 break;
1281
1282 case WID_O_REFIT:
1283 this->OrderClick_Refit(0, false);
1284 break;
1285
1286 case WID_O_DEPOT_ACTION:
1287 ShowDropDownMenu(this, _order_depot_action_dropdown, to_underlying(DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel()))), WID_O_DEPOT_ACTION, 0, 0);
1288 break;
1289
1291 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1292 this->OrderClick_Refit(0, true);
1293 } else {
1294 ShowDropDownMenu(this, _order_refit_action_dropdown, 0, WID_O_REFIT_DROPDOWN, 0, 0);
1295 }
1296 break;
1297
1299 ShowTimetableWindow(this->vehicle);
1300 break;
1301
1302 case WID_O_COND_VARIABLE: {
1303 DropDownList list;
1304 for (const auto &ocv : _order_conditional_variable) {
1305 if (ocv == OrderConditionVariable::DrivingBackwards && this->vehicle->type != VEH_TRAIN) continue;
1306 list.push_back(MakeDropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + to_underlying(ocv), to_underlying(ocv)));
1307 }
1308 ShowDropDownList(this, std::move(list), to_underlying(this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable()), WID_O_COND_VARIABLE);
1309 break;
1310 }
1311
1312 case WID_O_COND_COMPARATOR: {
1313 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1314 assert(o != nullptr);
1316 break;
1317 }
1318
1319 case WID_O_COND_VALUE: {
1320 const Order *order = this->vehicle->GetOrder(this->OrderGetSel());
1321 assert(order != nullptr);
1322 uint value = order->GetConditionValue();
1323 if (order->GetConditionVariable() == OrderConditionVariable::MaxSpeed) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1324 ShowQueryString(GetString(STR_JUST_INT, value), STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, this, CS_NUMERAL, {});
1325 break;
1326 }
1327
1329 ShowVehicleListWindow(this->vehicle);
1330 break;
1331 }
1332 }
1333
1334 void OnQueryTextFinished(std::optional<std::string> str) override
1335 {
1336 if (!str.has_value() || str->empty()) return;
1337
1338 VehicleOrderID sel = this->OrderGetSel();
1339 auto value = ParseInteger(*str, 10, true);
1340 if (!value.has_value()) return;
1341
1342 switch (this->vehicle->GetOrder(sel)->GetConditionVariable()) {
1344 value = ConvertDisplaySpeedToSpeed(*value, this->vehicle->type);
1345 break;
1346
1350 value = Clamp(*value, 0, 100);
1351 break;
1352
1353 default:
1354 break;
1355 }
1356 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel, MOF_COND_VALUE, Clamp(*value, 0, 2047));
1357 }
1358
1359 void OnDropdownSelect(WidgetID widget, int index, int) override
1360 {
1361 switch (widget) {
1362 case WID_O_NON_STOP:
1363 this->OrderClick_Nonstop(static_cast<OrderNonStopFlags>(index));
1364 break;
1365
1366 case WID_O_FULL_LOAD:
1367 this->OrderClick_FullLoad(static_cast<OrderLoadType>(index));
1368 break;
1369
1370 case WID_O_UNLOAD:
1371 this->OrderClick_Unload(static_cast<OrderUnloadType>(index));
1372 break;
1373
1374 case WID_O_GOTO:
1375 switch (index) {
1376 case 0: this->OrderClick_Goto(OPOS_GOTO); break;
1377 case 1: this->OrderClick_NearestDepot(); break;
1378 case 2: this->OrderClick_Goto(OPOS_CONDITIONAL); break;
1379 case 3: this->OrderClick_Goto(OPOS_SHARE); break;
1380 default: NOT_REACHED();
1381 }
1382 break;
1383
1384 case WID_O_DEPOT_ACTION:
1385 this->OrderClick_Service(static_cast<OrderDepotAction>(index));
1386 break;
1387
1389 this->OrderClick_Refit(index, true);
1390 break;
1391
1393 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_VARIABLE, index);
1394 break;
1395
1397 Command<Commands::ModifyOrder>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_COMPARATOR, index);
1398 break;
1399 }
1400 }
1401
1402 void OnDragDrop(Point pt, WidgetID widget) override
1403 {
1404 switch (widget) {
1405 case WID_O_ORDER_LIST: {
1406 VehicleOrderID from_order = this->OrderGetSel();
1407 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1408
1409 if (!(from_order == to_order || from_order == INVALID_VEH_ORDER_ID || from_order > this->vehicle->GetNumOrders() || to_order == INVALID_VEH_ORDER_ID || to_order > this->vehicle->GetNumOrders()) &&
1410 Command<Commands::MoveOrder>::Post(STR_ERROR_CAN_T_MOVE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, from_order, to_order)) {
1411 this->selected_order = -1;
1412 this->UpdateButtonState();
1413 }
1414 break;
1415 }
1416
1417 case WID_O_DELETE:
1418 this->OrderClick_Delete();
1419 break;
1420
1421 case WID_O_STOP_SHARING:
1422 this->OrderClick_StopSharing();
1423 break;
1424 }
1425
1427
1428 if (this->order_over != INVALID_VEH_ORDER_ID) {
1429 /* End of drag-and-drop, hide dragged order destination highlight. */
1430 this->order_over = INVALID_VEH_ORDER_ID;
1432 }
1433 }
1434
1435 EventState OnHotkey(int hotkey) override
1436 {
1437 if (this->vehicle->owner != _local_company) return ES_NOT_HANDLED;
1438
1439 switch (hotkey) {
1440 case OHK_SKIP: this->OrderClick_Skip(); break;
1441 case OHK_DELETE: this->OrderClick_Delete(); break;
1442 case OHK_GOTO: this->OrderClick_Goto(OPOS_GOTO); break;
1443 case OHK_NONSTOP: this->OrderClick_Nonstop(std::nullopt); break;
1444 case OHK_FULLLOAD: this->OrderClick_FullLoad(OrderLoadType::FullLoadAny, true); break;
1445 case OHK_UNLOAD: this->OrderClick_Unload(OrderUnloadType::Unload, true); break;
1446 case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break;
1447 case OHK_ALWAYS_SERVICE: this->OrderClick_Service(std::nullopt); break;
1448 case OHK_TRANSFER: this->OrderClick_Unload(OrderUnloadType::Transfer, true); break;
1449 case OHK_NO_UNLOAD: this->OrderClick_Unload(OrderUnloadType::NoUnload, true); break;
1450 case OHK_NO_LOAD: this->OrderClick_FullLoad(OrderLoadType::NoLoad, true); break;
1451 default: return ES_NOT_HANDLED;
1452 }
1453 return ES_HANDLED;
1454 }
1455
1456 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1457 {
1458 if (this->goto_type == OPOS_GOTO) {
1459 const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
1460 if (cmd.IsType(OT_NOTHING)) return;
1461
1462 if (Command<Commands::InsertOrder>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), cmd)) {
1463 /* With quick goto the Go To button stays active */
1464 if (!_settings_client.gui.quick_goto) ResetObjectToPlace();
1465 }
1466 }
1467 }
1468
1469 bool OnVehicleSelect(const Vehicle *v) override
1470 {
1471 /* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet.
1472 * We disallow copying orders of other vehicles if we already have at least one order entry
1473 * ourself as it easily copies orders of vehicles within a station when we mean the station.
1474 * Obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
1475 * TODO: give a warning message */
1476 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1477 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1478
1479 if (Command<Commands::CloneOrder>::Post(share_order ? STR_ERROR_CAN_T_SHARE_ORDER_LIST : STR_ERROR_CAN_T_COPY_ORDER_LIST,
1480 this->vehicle->tile, share_order ? CO_SHARE : CO_COPY, this->vehicle->index, v->index)) {
1481 this->selected_order = -1;
1483 }
1484 return true;
1485 }
1486
1495 bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
1496 {
1497 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1498 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1499
1500 if (!share_order) {
1501 /* If CTRL is not pressed: If all the vehicles in this list have the same orders, then copy orders */
1502 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1503 return VehiclesHaveSameOrderList(v1, v2);
1504 })) {
1505 OnVehicleSelect(*begin);
1506 } else {
1507 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST), WL_INFO);
1508 }
1509 } else {
1510 /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */
1511 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1512 return v1->FirstShared() == v2->FirstShared();
1513 })) {
1514 OnVehicleSelect(*begin);
1515 } else {
1516 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST), WL_INFO);
1517 }
1518 }
1519
1520 return true;
1521 }
1522
1523 void OnPlaceObjectAbort() override
1524 {
1525 this->goto_type = OPOS_NONE;
1527
1528 /* Remove drag highlighting if it exists. */
1529 if (this->order_over != INVALID_VEH_ORDER_ID) {
1530 this->order_over = INVALID_VEH_ORDER_ID;
1532 }
1533 }
1534
1535 void OnMouseDrag(Point pt, WidgetID widget) override
1536 {
1537 if (this->selected_order != -1 && widget == WID_O_ORDER_LIST) {
1538 /* An order is dragged.. */
1539 VehicleOrderID from_order = this->OrderGetSel();
1540 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1541 uint num_orders = this->vehicle->GetNumOrders();
1542
1543 if (from_order != INVALID_VEH_ORDER_ID && from_order <= num_orders) {
1544 if (to_order != INVALID_VEH_ORDER_ID && to_order <= num_orders) { // ..over an existing order.
1545 this->order_over = to_order;
1546 this->SetWidgetDirty(widget);
1547 } else if (from_order != to_order && this->order_over != INVALID_VEH_ORDER_ID) { // ..outside of the order list.
1548 this->order_over = INVALID_VEH_ORDER_ID;
1549 this->SetWidgetDirty(widget);
1550 }
1551 }
1552 }
1553 }
1554
1555 void OnResize() override
1556 {
1557 /* Update the scroll bar */
1558 this->vscroll->SetCapacityFromWidget(this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.Vertical());
1559 }
1560
1561 static inline HotkeyList hotkeys{"order", {
1562 Hotkey('D', "skip", OHK_SKIP),
1563 Hotkey('F', "delete", OHK_DELETE),
1564 Hotkey('G', "goto", OHK_GOTO),
1565 Hotkey('H', "nonstop", OHK_NONSTOP),
1566 Hotkey('J', "fullload", OHK_FULLLOAD),
1567 Hotkey('K', "unload", OHK_UNLOAD),
1568 Hotkey(0, "nearest_depot", OHK_NEAREST_DEPOT),
1569 Hotkey(0, "always_service", OHK_ALWAYS_SERVICE),
1570 Hotkey(0, "transfer", OHK_TRANSFER),
1571 Hotkey(0, "no_unload", OHK_NO_UNLOAD),
1572 Hotkey(0, "no_load", OHK_NO_LOAD),
1573 }};
1574};
1575
1577static constexpr std::initializer_list<NWidgetPart> _nested_orders_train_widgets = {
1581 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1585 EndContainer(),
1589 EndContainer(),
1590
1591 /* First button row. */
1596 SetStringTip(STR_ORDER_NON_STOP, STR_ORDER_TOOLTIP_NON_STOP), SetResize(1, 0),
1599 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1601 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1602 EndContainer(),
1605 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1607 SetStringTip(STR_JUST_STRING), SetResize(1, 0),
1608 EndContainer(),
1612 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1613 EndContainer(),
1614 EndContainer(),
1617 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1619 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1621 SetToolTip(STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1622 EndContainer(),
1623 EndContainer(),
1624 NWidget(WWT_PUSHIMGBTN, Colours::Grey, WID_O_SHARED_ORDER_LIST), SetAspect(1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
1625 EndContainer(),
1626
1627 /* Second button row. */
1631 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1634 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1636 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1637 EndContainer(),
1639 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1640 EndContainer(),
1642 EndContainer(),
1643};
1644
1645static WindowDesc _orders_train_desc(
1646 WDP_AUTO, "view_vehicle_orders_train", 384, 100,
1650 &OrdersWindow::hotkeys
1651);
1652
1654static constexpr std::initializer_list<NWidgetPart> _nested_orders_widgets = {
1657 NWidget(WWT_CAPTION, Colours::Grey, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1658 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1662 EndContainer(),
1666 EndContainer(),
1667
1668 /* First button row. */
1671 /* Load + unload + refit buttons. */
1674 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1676 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1678 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1679 EndContainer(),
1680 /* Refit + service buttons. */
1683 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1685 SetResize(1, 0),
1686 EndContainer(),
1687
1688 /* Buttons for setting a condition. */
1691 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1693 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1695 SetStringTip(STR_JUST_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1696 EndContainer(),
1697 EndContainer(),
1698
1699 NWidget(WWT_PUSHIMGBTN, Colours::Grey, WID_O_SHARED_ORDER_LIST), SetAspect(1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
1700 EndContainer(),
1701
1702 /* Second button row. */
1705 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1708 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1710 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1711 EndContainer(),
1713 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1715 EndContainer(),
1716};
1717
1718static WindowDesc _orders_desc(
1719 WDP_AUTO, "view_vehicle_orders", 384, 100,
1723 &OrdersWindow::hotkeys
1724);
1725
1727static constexpr std::initializer_list<NWidgetPart> _nested_other_orders_widgets = {
1730 NWidget(WWT_CAPTION, Colours::Grey, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1731 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1735 EndContainer(),
1741 EndContainer(),
1742 EndContainer(),
1743};
1744
1745static WindowDesc _other_orders_desc(
1746 WDP_AUTO, "view_vehicle_orders_competitor", 384, 86,
1750 &OrdersWindow::hotkeys
1751);
1752
1753void ShowOrdersWindow(const Vehicle *v)
1754{
1755 CloseWindowById(WC_VEHICLE_DETAILS, v->index, false);
1756 CloseWindowById(WC_VEHICLE_TIMETABLE, v->index, false);
1757 if (BringWindowToFrontById(WC_VEHICLE_ORDERS, v->index) != nullptr) return;
1758
1759 /* Using a different WindowDescs for _local_company causes problems.
1760 * Due to this we have to close order windows in ChangeWindowOwner/CloseCompanyWindows,
1761 * because we cannot change switch the WindowDescs and keeping the old WindowDesc results
1762 * in crashed due to missing widget.
1763 * TODO Rewrite the order GUI to not use different WindowDescs.
1764 */
1765 if (v->owner != _local_company) {
1766 new OrdersWindow(_other_orders_desc, v);
1767 } else {
1768 new OrdersWindow(v->IsGroundVehicle() ? _orders_train_desc : _orders_desc, v);
1769 }
1770}
Base for aircraft.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static const CargoType CARGO_AUTO_REFIT
Automatically choose cargo type when doing auto refitting.
Definition cargo_type.h:76
static const CargoType CARGO_NO_REFIT
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-renew).
Definition cargo_type.h:77
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
constexpr Timpl & Flip(Tvalue_type value)
Flip the value-th bit.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Base class for a 'real' widget.
void SetStringTip(StringID string, StringID tool_tip)
Set string and tool tip of the nested widget.
Definition widget.cpp:1195
Stacked widgets, widgets all occupying the same space in the window.
bool SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition widget.cpp:1453
Scrollbar data structure.
bool IsVisible(size_type item) const
Checks whether given current item is visible in the list.
void SetCount(size_t num)
Sets the number of elements in the list.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2458
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2532
void ScrollTowards(size_type position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
size_type GetPosition() const
Gets the position of the first visible element in the list.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
Functions related to commands.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Command definitions related to companies.
Functions related to companies.
static constexpr Owner OWNER_NONE
The tile has no ownership.
Map related accessors for depots.
bool IsDepotTypeTile(Tile tile, TransportType type)
Check if a tile is a depot and it is a depot of the given type.
Definition depot_map.h:22
DestinationID GetDepotDestinationIndex(Tile t)
Get the destination index of a 'depot'.
Definition depot_map.h:69
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:629
std::unique_ptr< DropDownListItem > MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
Creates new DropDownListStringItem.
Definition dropdown.cpp:49
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:587
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
bool IsEngineRefittable(EngineID engine)
Check if an engine is refittable.
Definition engine.cpp:1293
Functions related to engines.
@ AutoRefit
Automatic refitting is allowed.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:88
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:972
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:900
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:939
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:669
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1038
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:116
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:390
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:400
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ Grey
Grey.
Definition gfx_type.h:299
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:331
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:980
Hotkey related functions.
Base of all industries.
#define Point
Macro that prevents name conflicts between included headers.
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
bool _networking
are we in networking mode?
Definition network.cpp:67
Basic functions/variables used all over the place.
@ Order
Something wrong with the order, e.g. invalid or duplicate entries, too few entries.
Definition news_type.h:54
uint GetOrderDistance(VehicleOrderID prev, VehicleOrderID cur, const Vehicle *v, int conditional_depth)
Get the distance between two orders of a vehicle.
Command definitions related to orders.
static constexpr std::initializer_list< NWidgetPart > _nested_orders_widgets
Nested widget definition for "your" orders (non-train).
static constexpr std::initializer_list< NWidgetPart > _nested_other_orders_widgets
Nested widget definition for competitor orders.
uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type)
Convert the given (internal) speed to the display speed.
Definition strings.cpp:969
static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
Get the order command a vehicle can do in a given tile.
static const OrderConditionVariable _order_conditional_variable[]
Variables for conditional orders; this defines the order of appearance in the dropdown box.
OrderHotKeys
Hotkeys for order window.
static const StringID _station_load_types[][5][5]
Order load types that could be given to station orders.
Definition order_gui.cpp:47
static constexpr std::initializer_list< NWidgetPart > _nested_orders_train_widgets
Nested widget definition for "your" train orders.
uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
Convert the given display speed to the (internal) speed.
Definition strings.cpp:983
void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_index, int y, bool selected, bool timetable, int left, int middle, int right)
Draws an order in order or timetable GUI.
OrderUnloadType
Unloading order types.
Definition order_type.h:67
@ Transfer
Transfer all cargo onto the platform.
Definition order_type.h:70
@ UnloadIfPossible
Unload all cargo that the station accepts.
Definition order_type.h:68
@ NoUnload
Totally no unloading will be done.
Definition order_type.h:71
@ Unload
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:69
OrderConditionVariable
Variables (of a vehicle) to 'cause' skipping on.
Definition order_type.h:128
@ Unconditionally
Always skip.
Definition order_type.h:134
@ MaxSpeed
Skip based on the maximum speed.
Definition order_type.h:131
@ Reliability
Skip based on the reliability.
Definition order_type.h:130
@ MaxReliability
Skip based on the maximum reliability.
Definition order_type.h:136
@ RequiresService
Skip when the vehicle requires service.
Definition order_type.h:133
@ LoadPercentage
Skip based on the amount of load.
Definition order_type.h:129
@ Age
Skip based on the age.
Definition order_type.h:132
@ DrivingBackwards
Skip when the train is driving backwards.
Definition order_type.h:137
@ RemainingLifetime
Skip based on the remaining lifetime.
Definition order_type.h:135
OrderStopLocation
Where to stop the trains.
Definition order_type.h:97
@ End
End marker.
Definition order_type.h:101
@ FarEnd
Stop at the far end of the platform.
Definition order_type.h:100
@ MOF_COND_VARIABLE
A conditional variable changes.
Definition order_type.h:166
@ MOF_LOAD
Passes an OrderLoadType.
Definition order_type.h:164
@ MOF_UNLOAD
Passes an OrderUnloadType.
Definition order_type.h:163
@ MOF_STOP_LOCATION
Passes an OrderStopLocation.
Definition order_type.h:162
@ MOF_COND_COMPARATOR
A comparator changes.
Definition order_type.h:167
@ MOF_COND_VALUE
The value to set the condition to.
Definition order_type.h:168
@ MOF_DEPOT_ACTION
Selects the OrderDepotAction.
Definition order_type.h:165
@ MOF_NON_STOP
Passes an OrderNonStopFlags.
Definition order_type.h:161
OrderDepotAction
Depot action to switch to when doing a MOF_DEPOT_ACTION.
Definition order_type.h:176
@ Stop
Go to the depot and stop there.
Definition order_type.h:179
@ AlwaysGo
Always go to the depot.
Definition order_type.h:177
@ Service
Service only if needed.
Definition order_type.h:178
@ Unbunch
Go to the depot and unbunch.
Definition order_type.h:180
@ NonStop
The vehicle will not stop at any stations it passes except the destination, aka non-stop.
Definition order_type.h:88
@ GoVia
The vehicle will stop at any station it passes except the destination, aka via.
Definition order_type.h:89
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related).
Definition order_type.h:18
OrderLoadType
Loading order types.
Definition order_type.h:77
@ NoLoad
Do not load anything.
Definition order_type.h:81
@ FullLoadAny
Full load a single cargo of the consist.
Definition order_type.h:80
@ LoadIfPossible
Load as long as there is cargo that fits in the train.
Definition order_type.h:78
@ Halt
Service the vehicle and then halt it.
Definition order_type.h:118
@ NearestDepot
Send the vehicle to the nearest depot.
Definition order_type.h:119
@ Unbunch
Service the vehicle and then unbunch it.
Definition order_type.h:120
@ PartOfOrders
This depot order is because of a regular order.
Definition order_type.h:109
@ Service
This depot order is because of the servicing limit.
Definition order_type.h:108
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel).
Definition order_type.h:39
OrderConditionComparator
Comparator for the skip reasoning.
Definition order_type.h:144
@ IsTrue
Skip if the variable is true.
Definition order_type.h:151
@ IsFalse
Skip if the variable is false.
Definition order_type.h:152
Types related to the order widgets.
@ WID_O_TIMETABLE_VIEW
Toggle timetable view.
@ WID_O_SHARED_ORDER_LIST
Open list of shared vehicles.
@ WID_O_SKIP
Skip current order.
@ WID_O_SCROLLBAR
Order list scrollbar.
@ WID_O_SEL_TOP_MIDDLE
NWID_SELECTION widget for middle part of the top row of the 'your train' order window.
@ WID_O_SEL_BOTTOM_MIDDLE
NWID_SELECTION widget for the middle part of the bottom row of the 'your train' order window.
@ WID_O_REFIT
Select refit.
@ WID_O_ORDER_LIST
Order list panel.
@ WID_O_COND_VARIABLE
Choose condition variable.
@ WID_O_SEL_TOP_ROW
NWID_SELECTION widget for the top row of the 'your non-trains' order window.
@ WID_O_DELETE
Delete selected order.
@ WID_O_STOP_SHARING
Stop sharing orders.
@ WID_O_COND_COMPARATOR
Choose condition type.
@ WID_O_CAPTION
Caption of the window.
@ WID_O_UNLOAD
Select unload.
@ WID_O_SEL_TOP_LEFT
NWID_SELECTION widget for left part of the top row of the 'your train' order window.
@ WID_O_DEPOT_ACTION
Dropdown to select the depot action (stop, service if needed, unbunch).
@ WID_O_REFIT_DROPDOWN
Open refit options.
@ WID_O_SEL_TOP_RIGHT
NWID_SELECTION widget for right part of the top row of the 'your train' order window.
@ WID_O_NON_STOP
Goto non-stop to destination.
@ WID_O_COND_VALUE
Choose condition value.
@ WID_O_FULL_LOAD
Select full load.
@ WID_O_SEL_TOP_ROW_GROUNDVEHICLE
NWID_SELECTION widget for the top row of the 'your train' order window.
@ WID_O_GOTO
Goto destination.
PixelColour GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:393
Road vehicle states.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
static const CursorID ANIMCURSOR_PICKSTATION
716 - 718 - goto-order icon
Definition sprites.h:1525
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition sprites.h:1404
Base classes/functions for stations.
bool IsRailWaypointTile(Tile t)
Is this tile a station tile and a rail waypoint?
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
bool IsRoadWaypointTile(Tile t)
Is this tile a station tile and a road waypoint?
bool IsBuoyTile(Tile t)
Is tile t a buoy tile?
@ Dock
Station with a dock.
@ TruckStop
Station with truck stops.
@ Train
Station with train station.
@ Airport
Station with an airport.
@ BusStop
Station with bus stops.
Definition of base types and functions in a cross-platform compatible way.
Parse strings.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
Functions related to low-level strings.
@ CS_NUMERAL
Only numeric ones.
Definition string_type.h:26
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:236
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
@ TD_RTL
Text is written right-to-left by default.
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
StationFacilities facilities
The facilities that this station has.
Owner owner
The owner of this station.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
VehicleType type
Type of vehicle.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
Definition cargotype.h:139
GUISettings gui
settings related to the GUI
T y
Y coordinate.
Dimensions (a width and height) of a rectangle in 2D.
bool quick_goto
Allow quick access to 'goto button' in vehicle orders window.
List of hotkeys for a window.
Definition hotkeys.h:46
All data for a single hotkey.
Definition hotkeys.h:22
Defines the internal data of a functional industry.
Definition industry.h:62
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:251
Station * neutral_station
Associated neutral station.
Definition industry.h:108
VehicleOrderID GetNext(VehicleOrderID cur) const
Get the order after the given one or the first one, if the given one is the last one.
Definition order_base.h:476
If you change this, keep in mind that it is also saved in 2 other places:
Definition order_base.h:34
TileIndex GetLocation(const Vehicle *v, bool airport=false) const
Returns a tile somewhat representing the order destination (not suitable for pathfinding).
bool IsGotoOrder() const
Is this a 'goto' order with a real destination?
Definition order_base.h:90
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition order_base.h:170
OrderConditionVariable GetConditionVariable() const
What variable do we have to compare?
Definition order_base.h:182
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:100
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition order_base.h:218
VehicleOrderID GetConditionSkipToOrder() const
Get the order to skip to.
Definition order_base.h:194
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition order_base.h:164
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:294
CargoType GetRefitCargo() const
Get the cargo to to refit to.
Definition order_base.h:128
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:73
void MakeGoToStation(StationID destination)
Makes this order a Go To Station order.
Definition order_cmd.cpp:58
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition order_base.h:224
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
Definition order_cmd.cpp:87
OrderUnloadType GetUnloadType() const
How must the consist be unloaded?
Definition order_base.h:152
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:271
void MakeConditional(VehicleOrderID order)
Makes this order an conditional order.
void SetDepotActionType(OrderDepotActionFlags depot_service_type)
Set what we are going to do in the depot.
Definition order_base.h:236
OrderLoadType GetLoadType() const
How must the consist be loaded?
Definition order_base.h:146
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition order_base.h:176
void Free()
'Free' the order
Definition order_cmd.cpp:47
void SetLoadType(OrderLoadType load_type)
Set how the consist must be loaded.
Definition order_base.h:206
bool IsAutoRefit() const
Is this order a auto-refit order.
Definition order_base.h:121
void MakeGoToDepot(DestinationID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=OrderNonStopFlag::NonStop, OrderDepotActionFlags action={}, CargoType cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition order_cmd.cpp:73
OrderConditionComparator GetConditionComparator() const
What is the comparator to use?
Definition order_base.h:188
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:158
bool IsRefit() const
Is this order a refit order.
Definition order_base.h:114
uint16_t GetConditionValue() const
Get the value to base the skip on.
Definition order_base.h:200
Order window code for all vehicles.
void OrderClick_Refit(int i, bool auto_refit)
Handle the click on the refit button.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
void OrderClick_Delete()
Handle the click on the delete button.
void OnResize() override
Called after the window got resized.
void OrderClick_Skip()
Handle the click on the skip button.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
Clones an order list from a vehicle list.
void OrderClick_FullLoad(OrderLoadType load_type, bool toggle=false)
Handle the click on the full load button.
const Vehicle * vehicle
Vehicle owning the orders being displayed and manipulated.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
bool can_do_refit
Vehicle chain can be refitted in depot.
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
DisplayPane
Displayed planes of the NWID_SELECTION widgets.
@ DP_BOTTOM_MIDDLE_DELETE
Display 'delete' in the middle button of the bottom row of the vehicle order window.
@ DP_ROW_CONDITIONAL
Display the conditional order buttons in the top row of the ship/airplane order window.
@ DP_ROW_DEPOT
Display 'refit' / 'service' buttons in the top row of the ship/airplane order window.
@ DP_BOTTOM_MIDDLE_STOP_SHARING
Display 'stop sharing' in the middle button of the bottom row of the vehicle order window.
@ DP_MIDDLE_UNLOAD
Display 'unload' in the middle button of the top row of the train/rv order window.
@ DP_LEFT_LOAD
Display 'load' in the left button of the top row of the train/rv order window.
@ DP_RIGHT_EMPTY
Display an empty panel in the right button of the top row of the train/rv order window.
@ DP_RIGHT_REFIT
Display 'refit' in the right button of the top row of the train/rv order window.
@ DP_ROW_LOAD
Display 'load' / 'unload' / 'refit' buttons in the top row of the ship/airplane order window.
@ DP_MIDDLE_SERVICE
Display 'service' in the middle button of the top row of the train/rv order window.
@ DP_GROUNDVEHICLE_ROW_CONDITIONAL
Display the row for conditional orders in the top row of the train/rv order window.
@ DP_LEFT_REFIT
Display 'refit' in the left button of the top row of the train/rv order window.
@ DP_GROUNDVEHICLE_ROW_NORMAL
Display the row for normal/depot orders in the top row of the train/rv order window.
void OrderClick_NearestDepot()
Handle the click on the service in nearest depot button.
void OrderClick_StopSharing()
Handle the click on the 'stop sharing' button.
VehicleOrderID OrderGetSel() const
Return the memorised selected order.
void UpdateAutoRefitState()
Cache auto-refittability of the vehicle chain.
void OnPaint() override
The window must be repainted.
void OnDragDrop(Point pt, WidgetID widget) override
A dragged 'object' has been released.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnMouseDrag(Point pt, WidgetID widget) override
An 'object' is being dragged at the provided position, highlight the target if possible.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
OrderPlaceObjectState
Under what reason are we using the PlaceObject functionality?
void OrderClick_Unload(OrderUnloadType unload_type, bool toggle=false)
Handle the click on the unload button.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
VehicleOrderID GetOrderFromPt(int y)
Calculate the selected order.
void OrderClick_Service(std::optional< OrderDepotAction > i)
Handle the click on the service.
bool can_do_autorefit
Vehicle chain can be auto-refitted.
void OrderClick_Nonstop(std::optional< OrderNonStopFlags > non_stop)
Handle the click on the nonstop button.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OrderClick_Goto(OrderPlaceObjectState type)
Handle the click on the goto button.
VehicleOrderID order_over
Order over which another order is dragged, INVALID_VEH_ORDER_ID if none.
static Engine * Get(auto index)
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
static Station * Get(auto index)
Station data structure.
Vehicle data structure.
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
OrderList * orders
Pointer to the order list for this vehicle.
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Vehicle * PreviousShared() const
Get the previous vehicle of the shared vehicle chain.
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
TileIndex tile
Current tile index.
Owner owner
Which company owns the vehicle?
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:274
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1822
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:786
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:470
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:570
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:518
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1089
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:392
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1812
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:401
int top
y position of top edge of the window
Definition window_gui.h:311
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1846
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:327
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Stuff related to the text buffer GUI.
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Industry
Part of an industry.
Definition tile_type.h:57
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
HighLightStyle
Highlighting draw styles.
@ HT_DRAG
dragging items in the depot windows
@ HT_NONE
default
@ HT_RECT
rectangle (stations, depots, ...)
@ HT_VEHICLE
vehicle is accepted as target as well (bitmask)
Functions related to time tabling.
void ShowTimetableWindow(const Vehicle *v)
Show the timetable for a given vehicle.
std::pair< StringParameter, StringParameter > GetTimetableParameters(TimerGameTick::Ticks ticks)
Get parameters to format timetable time.
TransportType
Available types of transport.
bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicles have the same list of orders.
Definition vehicle.cpp:3329
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3098
Functions related to vehicles.
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
Show the refit window for a vehicle.
@ VIWD_CONSIST_CHANGED
Vehicle composition was changed.
Definition vehicle_gui.h:37
@ VIWD_AUTOREPLACE
Autoreplace replaced the vehicle.
Definition vehicle_gui.h:38
@ VIWD_MODIFY_ORDERS
Other order modifications.
Definition vehicle_gui.h:36
@ VIWD_REMOVE_ALL_ORDERS
Removed / replaced all orders (after deleting / sharing).
Definition vehicle_gui.h:35
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
Functions and type for generating vehicle lists.
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Functions related to (drawing on) viewports.
Base of waypoints.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ NWID_BUTTON_DROPDOWN
Button with a drop-down.
Definition widget_type.h:74
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX).
Definition widget_type.h:57
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX).
Definition widget_type.h:55
@ WWT_CAPTION
Window caption (window title between closebox and stickybox).
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window).
Definition widget_type.h:60
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window).
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX).
Definition widget_type.h:56
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ EqualSize
Containers should keep all their (resizing) children equally large.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1209
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1293
@ Construction
This window is used for construction; close it whenever changing company.
Definition window_gui.h:153
bool AllEqual(It begin, It end, Pred pred)
Generic helper function that checks if all elements of the range are equal with respect to the given ...
Definition window_gui.h:953
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:21
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers: