OpenTTD Source 20250528-master-g3aca5d62a8
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 <http://www.gnu.org/licenses/>.
6 */
7
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_drowdown[] = {
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_drowdown[] = {
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_drowdown[] = {
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
167
168static const StringID _order_conditional_condition[] = {
169 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,
170 STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,
171 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,
172 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS,
173 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,
174 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS,
175 STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,
176 STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,
177};
178
179extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type);
180extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type);
181
182static const StringID _order_depot_action_dropdown[] = {
183 STR_ORDER_DROP_GO_ALWAYS_DEPOT,
184 STR_ORDER_DROP_SERVICE_DEPOT,
185 STR_ORDER_DROP_HALT_DEPOT,
186 STR_ORDER_DROP_UNBUNCH,
187};
188
189static int DepotActionStringIndex(const Order *order)
190{
191 if (order->GetDepotActionType() & ODATFB_HALT) {
192 return DA_STOP;
193 } else if (order->GetDepotOrderType() & ODTFB_SERVICE) {
194 return DA_SERVICE;
195 } else if (order->GetDepotActionType() & ODATFB_UNBUNCH) {
196 return DA_UNBUNCH;
197 } else {
198 return DA_ALWAYS_GO;
199 }
200}
201
202static const StringID _order_refit_action_dropdown[] = {
203 STR_ORDER_DROP_REFIT_AUTO,
204 STR_ORDER_DROP_REFIT_AUTO_ANY,
205};
206
207static StringID GetOrderGoToString(const Order &order)
208{
209 if (order.GetDepotOrderType() & ODTFB_SERVICE) {
210 return (order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT;
211 } else {
212 return (order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO;
213 }
214}
215
228void DrawOrderString(const Vehicle *v, const Order *order, VehicleOrderID order_index, int y, bool selected, bool timetable, int left, int middle, int right)
229{
230 bool rtl = _current_text_dir == TD_RTL;
231
232 SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
233 Dimension sprite_size = GetSpriteSize(sprite);
234 if (v->cur_real_order_index == order_index) {
235 /* Draw two arrows before the next real order. */
236 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
237 DrawSprite(sprite, PAL_NONE, rtl ? right - 2 * sprite_size.width : left + sprite_size.width, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
238 } else if (v->cur_implicit_order_index == order_index) {
239 /* Draw one arrow before the next implicit order; the next real order will still get two arrows. */
240 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
241 }
242
243 TextColour colour = TC_BLACK;
244 if (order->IsType(OT_IMPLICIT)) {
245 colour = (selected ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
246 } else if (selected) {
247 colour = TC_WHITE;
248 }
249
250 DrawString(left, rtl ? right - 2 * sprite_size.width - 3 : middle, y, GetString(STR_ORDER_INDEX, order_index + 1), colour, SA_RIGHT | SA_FORCE);
251
252 std::string line;
253
254 switch (order->GetType()) {
255 case OT_DUMMY:
256 line = GetString(STR_INVALID_ORDER);
257 break;
258
259 case OT_IMPLICIT:
260 line = GetString(STR_ORDER_GO_TO_STATION, STR_ORDER_GO_TO, order->GetDestination());
261 if (!timetable) line += GetString(STR_ORDER_IMPLICIT);
262 break;
263
264 case OT_GOTO_STATION: {
265 OrderLoadFlags load = order->GetLoadType();
266 OrderUnloadFlags unload = order->GetUnloadType();
267 bool valid_station = CanVehicleUseStation(v, Station::Get(order->GetDestination().ToStationID()));
268
269 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() : 0), order->GetDestination());
270 if (timetable) {
271 /* Show only wait time in the timetable window. */
272 if (order->GetWaitTime() > 0) {
273 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
274 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED, str, value);
275 }
276 } else {
277 /* Show non-stop, refit and stop location only in the order window. */
279 StringID str = _station_load_types[order->IsRefit()][unload][load];
280 if (str != INVALID_STRING_ID) {
281 if (order->IsRefit()) {
282 line += GetString(str, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name);
283 } else {
284 line += GetString(str);
285 }
286 }
287 }
288
289 if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) {
290 /* Only show the stopping location if other than the default chosen by the player. */
292 line += GetString(STR_ORDER_STOP_LOCATION_NEAR_END + order->GetStopLocation());
293 }
294 }
295 }
296 break;
297 }
298
299 case OT_GOTO_DEPOT:
300 if (!(order->GetDepotActionType() & ODATFB_NEAREST_DEPOT)) {
301 /* Going to a specific depot. */
302 line = GetString(STR_ORDER_GO_TO_DEPOT_FORMAT, GetOrderGoToString(*order), v->type, order->GetDestination());
303 } else if (v->type == VEH_AIRCRAFT) {
304 /* Going to the nearest hangar. */
305 line = GetString(STR_ORDER_GO_TO_NEAREST_HANGAR_FORMAT, GetOrderGoToString(*order));
306 } else {
307 /* Going to the nearest depot. */
308 line = GetString(STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT, GetOrderGoToString(*order), STR_ORDER_TRAIN_DEPOT + v->type);
309 }
310
311 /* Do not show stopping in the depot in the timetable window. */
312 if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) {
313 line += GetString(STR_ORDER_STOP_ORDER);
314 }
315
316 /* Do not show refitting in the depot in the timetable window. */
317 if (!timetable && order->IsRefit()) {
318 line += GetString((order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER, CargoSpec::Get(order->GetRefitCargo())->name);
319 }
320
321 /* Show unbunching depot in both order and timetable windows. */
322 if (order->GetDepotActionType() & ODATFB_UNBUNCH) {
323 line += GetString(STR_ORDER_WAIT_TO_UNBUNCH);
324 }
325 break;
326
327 case OT_GOTO_WAYPOINT:
328 line = GetString((order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO_WAYPOINT : STR_ORDER_GO_TO_WAYPOINT, order->GetDestination());
329 break;
330
331 case OT_CONDITIONAL:
333 line = GetString(STR_ORDER_CONDITIONAL_UNCONDITIONAL, order->GetConditionSkipToOrder() + 1);
334 } else {
336
337 uint value = order->GetConditionValue();
338 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, v->type);
339
340 line = GetString((occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM,
341 order->GetConditionSkipToOrder() + 1,
342 STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable(),
343 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ,
344 value);
345 }
346
347 if (timetable && order->GetWaitTime() > 0) {
348 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
349 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_AND_TRAVEL_FOR : STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED, str, value);
350 }
351 break;
352
353 default: NOT_REACHED();
354 }
355
356 /* Check range for aircraft. */
357 if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->GetRange() > 0 && order->IsGotoOrder()) {
358 if (GetOrderDistance(order_index, v->orders->GetNext(order_index), v) > Aircraft::From(v)->acache.cached_max_range_sqr) {
359 line += GetString(STR_ORDER_OUT_OF_RANGE);
360 }
361 }
362
363 DrawString(rtl ? left : middle, rtl ? middle : right, y, line, colour);
364}
365
373{
374 Order order{};
375
376 /* check depot first */
377 if (IsDepotTypeTile(tile, (TransportType)(uint)v->type) && IsTileOwner(tile, _local_company)) {
381
382 if (_ctrl_pressed) {
383 /* Check to see if we are allowed to make this an unbunching order. */
384 bool failed = false;
385 if (v->HasFullLoadOrder()) {
386 /* We don't allow unbunching if the vehicle has a full load order. */
387 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD), WL_INFO);
388 failed = true;
389 } else if (v->HasUnbunchingOrder()) {
390 /* Don't allow a new unbunching order if we already have one. */
391 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED), WL_INFO);
392 failed = true;
393 } else if (v->HasConditionalOrder()) {
394 /* We don't allow unbunching if the vehicle has a conditional order. */
395 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL), WL_INFO);
396 failed = true;
397 }
398
399 /* Return an empty order to bail out. */
400 if (failed) {
401 order.Free();
402 return order;
403 }
404
405 /* Now we are allowed to set the action type. */
407 }
408
409 return order;
410 }
411
412 /* check rail waypoint */
413 if (IsRailWaypointTile(tile) &&
414 v->type == VEH_TRAIN &&
418 return order;
419 }
420
421 /* check road waypoint */
422 if (IsRoadWaypointTile(tile) &&
423 v->type == VEH_ROAD &&
427 return order;
428 }
429
430 /* check buoy (no ownership) */
431 if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
433 return order;
434 }
435
436 /* check for station or industry with neutral station */
437 if (IsTileType(tile, MP_STATION) || IsTileType(tile, MP_INDUSTRY)) {
438 const Station *st = nullptr;
439
440 if (IsTileType(tile, MP_STATION)) {
441 st = Station::GetByTile(tile);
442 } else {
443 const Industry *in = Industry::GetByTile(tile);
444 st = in->neutral_station;
445 }
446 if (st != nullptr && (st->owner == _local_company || st->owner == OWNER_NONE)) {
447 StationFacilities facil;
448 switch (v->type) {
449 case VEH_SHIP: facil = StationFacility::Dock; break;
450 case VEH_TRAIN: facil = StationFacility::Train; break;
451 case VEH_AIRCRAFT: facil = StationFacility::Airport; break;
453 default: NOT_REACHED();
454 }
455 if (st->facilities.Any(facil)) {
456 order.MakeGoToStation(st->index);
460 return order;
461 }
462 }
463 }
464
465 /* not found */
466 order.Free();
467 return order;
468}
469
471enum OrderHotKeys : int32_t {
472 OHK_SKIP,
473 OHK_DELETE,
474 OHK_GOTO,
475 OHK_NONSTOP,
476 OHK_FULLLOAD,
477 OHK_UNLOAD,
478 OHK_NEAREST_DEPOT,
479 OHK_ALWAYS_SERVICE,
480 OHK_TRANSFER,
481 OHK_NO_UNLOAD,
482 OHK_NO_LOAD,
483};
484
525struct OrdersWindow : public Window {
526private:
528 enum OrderPlaceObjectState : uint8_t {
529 OPOS_NONE,
530 OPOS_GOTO,
531 OPOS_CONDITIONAL,
532 OPOS_SHARE,
533 OPOS_END,
534 };
535
537 enum DisplayPane : uint8_t {
538 /* WID_O_SEL_TOP_ROW_GROUNDVEHICLE */
541
542 /* WID_O_SEL_TOP_LEFT */
545
546 /* WID_O_SEL_TOP_MIDDLE */
549
550 /* WID_O_SEL_TOP_RIGHT */
553
554 /* WID_O_SEL_TOP_ROW */
558
559 /* WID_O_SEL_BOTTOM_MIDDLE */
562 };
563
564 int selected_order = -1;
566 OrderPlaceObjectState goto_type = OPOS_NONE;
567 const Vehicle *vehicle = nullptr;
568 Scrollbar *vscroll = nullptr;
569 bool can_do_refit = false;
570 bool can_do_autorefit = false;
571
578 {
579 int num = this->selected_order;
580 return (num >= 0 && num < vehicle->GetNumOrders()) ? num : vehicle->GetNumOrders();
581 }
582
592 {
593 int32_t sel = this->vscroll->GetScrolledRowFromWidget(y, this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.top);
594 if (sel == INT32_MAX) return INVALID_VEH_ORDER_ID;
595 /* One past the orders is the 'End of Orders' line. */
596 assert(IsInsideBS(sel, 0, vehicle->GetNumOrders() + 1));
597 return sel;
598 }
599
604 {
605 assert(type > OPOS_NONE && type < OPOS_END);
606
607 static const HighLightStyle goto_place_style[OPOS_END - 1] = {
608 HT_RECT | HT_VEHICLE, // OPOS_GOTO
609 HT_NONE, // OPOS_CONDITIONAL
610 HT_VEHICLE, // OPOS_SHARE
611 };
612 SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, goto_place_style[type - 1], this);
613 this->goto_type = type;
615 }
616
622 void OrderClick_FullLoad(OrderLoadFlags load_type, bool toggle = false)
623 {
624 VehicleOrderID sel_ord = this->OrderGetSel();
625 const Order *order = this->vehicle->GetOrder(sel_ord);
626
627 if (order == nullptr) return;
628
629 if (toggle && order->GetLoadType() == load_type) {
630 load_type = OLF_LOAD_IF_POSSIBLE; // reset to 'default'
631 }
632 if (order->GetLoadType() == load_type) return; // If we still match, do nothing
633
634 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, load_type);
635 }
636
641 {
642 VehicleOrderID sel_ord = this->OrderGetSel();
643
644 if (i < 0) {
645 const Order *order = this->vehicle->GetOrder(sel_ord);
646 if (order == nullptr) return;
648 }
649 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_DEPOT_ACTION, i);
650 }
651
656 {
657 Order order{};
658 order.MakeGoToDepot(DepotID::Invalid(), ODTFB_PART_OF_ORDERS,
661
662 Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
663 }
664
670 void OrderClick_Unload(OrderUnloadFlags unload_type, bool toggle = false)
671 {
672 VehicleOrderID sel_ord = this->OrderGetSel();
673 const Order *order = this->vehicle->GetOrder(sel_ord);
674
675 if (order == nullptr) return;
676
677 if (toggle && order->GetUnloadType() == unload_type) {
678 unload_type = OUF_UNLOAD_IF_POSSIBLE;
679 }
680 if (order->GetUnloadType() == unload_type) return; // If we still match, do nothing
681
682 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_UNLOAD, unload_type);
683
684 /* Transfer and unload orders with leave empty as default */
685 if (unload_type == OUFB_TRANSFER || unload_type == OUFB_UNLOAD) {
686 Command<CMD_MODIFY_ORDER>::Post(this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, OLFB_NO_LOAD);
688 }
689 }
690
695 void OrderClick_Nonstop(int non_stop)
696 {
697 if (!this->vehicle->IsGroundVehicle()) return;
698
699 VehicleOrderID sel_ord = this->OrderGetSel();
700 const Order *order = this->vehicle->GetOrder(sel_ord);
701
702 if (order == nullptr || order->GetNonStopType() == non_stop) return;
703
704 /* Keypress if negative, so 'toggle' to the next */
705 if (non_stop < 0) {
707 }
708
710 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_NON_STOP, non_stop);
711 }
712
718 {
719 /* Don't skip when there's nothing to skip */
720 if (_ctrl_pressed && this->vehicle->cur_implicit_order_index == this->OrderGetSel()) return;
721 if (this->vehicle->GetNumOrders() <= 1) return;
722
723 Command<CMD_SKIP_TO_ORDER>::Post(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER,
724 this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_implicit_order_index + 1) % this->vehicle->GetNumOrders()));
725 }
726
731 {
732 /* When networking, move one order lower */
733 int selected = this->selected_order + (int)_networking;
734
735 if (Command<CMD_DELETE_ORDER>::Post(STR_ERROR_CAN_T_DELETE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel())) {
736 this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected;
737 this->UpdateButtonState();
738 }
739 }
740
748 {
749 /* Don't try to stop sharing orders if 'End of Shared Orders' isn't selected. */
750 if (!this->vehicle->IsOrderListShared() || this->selected_order != this->vehicle->GetNumOrders()) return;
751 /* If Ctrl is pressed, delete the order list as if we clicked the 'Delete' button. */
752 if (_ctrl_pressed) {
753 this->OrderClick_Delete();
754 return;
755 }
756
757 /* Get another vehicle that share orders with this vehicle. */
758 Vehicle *other_shared = (this->vehicle->FirstShared() == this->vehicle) ? this->vehicle->NextShared() : this->vehicle->PreviousShared();
759 /* Copy the order list of the other vehicle. */
760 if (Command<CMD_CLONE_ORDER>::Post(STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST, this->vehicle->tile, CO_COPY, this->vehicle->index, other_shared->index)) {
761 this->UpdateButtonState();
762 }
763 }
764
771 void OrderClick_Refit(int i, bool auto_refit)
772 {
773 if (_ctrl_pressed) {
774 /* Cancel refitting */
775 Command<CMD_ORDER_REFIT>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_NO_REFIT);
776 } else {
777 if (i == 1) { // Auto-refit to available cargo type.
778 Command<CMD_ORDER_REFIT>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_AUTO_REFIT);
779 } else {
780 ShowVehicleRefitWindow(this->vehicle, this->OrderGetSel(), this, auto_refit);
781 }
782 }
783 }
784
787 {
788 this->can_do_refit = false;
789 this->can_do_autorefit = false;
790 for (const Vehicle *w = this->vehicle; w != nullptr; w = w->IsGroundVehicle() ? w->Next() : nullptr) {
791 if (IsEngineRefittable(w->engine_type)) this->can_do_refit = true;
792 if (Engine::Get(w->engine_type)->info.misc_flags.Test(EngineMiscFlag::AutoRefit)) this->can_do_autorefit = true;
793 }
794 }
795
796public:
797 OrdersWindow(WindowDesc &desc, const Vehicle *v) : Window(desc)
798 {
799 this->vehicle = v;
800
801 this->CreateNestedTree();
802 this->vscroll = this->GetScrollbar(WID_O_SCROLLBAR);
803 if (NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_O_DEPOT_ACTION); nwid != nullptr) {
804 nwid->SetToolTip(STR_ORDER_TRAIN_DEPOT_ACTION_TOOLTIP + v->type);
805 }
806 this->FinishInitNested(v->index);
807
808 this->owner = v->owner;
809
810 this->UpdateAutoRefitState();
811
813 /* If there are less than 2 station, make Go To active. */
814 int station_orders = std::ranges::count_if(v->Orders(), [](const Order &order) { return order.IsType(OT_GOTO_STATION); });
815
816 if (station_orders < 2) this->OrderClick_Goto(OPOS_GOTO);
817 }
819 }
820
821 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
822 {
823 switch (widget) {
824 case WID_O_ORDER_LIST:
826 size.height = 6 * resize.height + padding.height;
827 break;
828
829 case WID_O_COND_VARIABLE: {
830 Dimension d = {0, 0};
831 for (const auto &ocv : _order_conditional_variable) {
832 d = maxdim(d, GetStringBoundingBox(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv));
833 }
834 d.width += padding.width;
835 d.height += padding.height;
836 size = maxdim(size, d);
837 break;
838 }
839
841 Dimension d = GetStringListBoundingBox(_order_conditional_condition);
842 d.width += padding.width;
843 d.height += padding.height;
844 size = maxdim(size, d);
845 break;
846 }
847 }
848 }
849
855 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
856 {
859
860 switch (data) {
861 case VIWD_AUTOREPLACE:
862 /* Autoreplace replaced the vehicle */
863 this->vehicle = Vehicle::Get(this->window_number);
864 [[fallthrough]];
865
867 /* Vehicle composition was changed. */
868 this->UpdateAutoRefitState();
869 break;
870
872 /* Removed / replaced all orders (after deleting / sharing) */
873 if (this->selected_order == -1) break;
874
875 this->CloseChildWindows();
876 this->selected_order = -1;
877 break;
878
880 /* Some other order changes */
881 break;
882
883 default:
884 if (data < 0) break;
885
886 if (gui_scope) break; // only do this once; from command scope
887 from = GB(data, 0, 8);
888 to = GB(data, 8, 8);
889 /* Moving an order. If one of these is INVALID_VEH_ORDER_ID, then
890 * the order is being created / removed */
891 if (this->selected_order == -1) break;
892
893 if (from == to) break; // no need to change anything
894
895 if (from != this->selected_order) {
896 /* Moving from preceding order? */
897 this->selected_order -= (int)(from <= this->selected_order);
898 /* Moving to preceding order? */
899 this->selected_order += (int)(to <= this->selected_order);
900 break;
901 }
902
903 /* Now we are modifying the selected order */
904 if (to == INVALID_VEH_ORDER_ID) {
905 /* Deleting selected order */
906 this->CloseChildWindows();
907 this->selected_order = -1;
908 break;
909 }
910
911 /* Moving selected order */
912 this->selected_order = to;
913 break;
914 }
915
916 this->vscroll->SetCount(this->vehicle->GetNumOrders() + 1);
917 if (gui_scope) this->UpdateButtonState();
918
919 /* Scroll to the new order. */
920 if (from == INVALID_VEH_ORDER_ID && to != INVALID_VEH_ORDER_ID && !this->vscroll->IsVisible(to)) {
921 this->vscroll->ScrollTowards(to);
922 }
923 }
924
925 void UpdateButtonState()
926 {
927 if (this->vehicle->owner != _local_company) return; // No buttons are displayed with competitor order windows.
928
929 bool shared_orders = this->vehicle->IsOrderListShared();
930 VehicleOrderID sel = this->OrderGetSel();
931 const Order *order = this->vehicle->GetOrder(sel);
932
933 /* Second row. */
934 /* skip */
935 this->SetWidgetDisabledState(WID_O_SKIP, this->vehicle->GetNumOrders() <= 1);
936
937 /* delete / stop sharing */
938 NWidgetStacked *delete_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_BOTTOM_MIDDLE);
939 if (shared_orders && this->selected_order == this->vehicle->GetNumOrders()) {
940 /* The 'End of Shared Orders' order is selected, show the 'stop sharing' button. */
942 } else {
943 /* The 'End of Shared Orders' order isn't selected, show the 'delete' button. */
946 (uint)this->vehicle->GetNumOrders() + ((shared_orders || this->vehicle->GetNumOrders() != 0) ? 1 : 0) <= (uint)this->selected_order);
947
948 /* Set the tooltip of the 'delete' button depending on whether the
949 * 'End of Orders' order or a regular order is selected. */
950 NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_O_DELETE);
951 if (this->selected_order == this->vehicle->GetNumOrders()) {
952 nwi->SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_ALL_TOOLTIP);
953 } else {
954 nwi->SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP);
955 }
956 }
957
958 /* First row. */
961
962 /* Selection widgets. */
963 /* Train or road vehicle. */
964 NWidgetStacked *train_row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW_GROUNDVEHICLE);
965 NWidgetStacked *left_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_LEFT);
966 NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_MIDDLE);
967 NWidgetStacked *right_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_RIGHT);
968 /* Ship or airplane. */
969 NWidgetStacked *row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW);
970 assert(row_sel != nullptr || (train_row_sel != nullptr && left_sel != nullptr && middle_sel != nullptr && right_sel != nullptr));
971
972
973 if (order == nullptr) {
974 if (row_sel != nullptr) {
976 } else {
983 }
987 } else {
990
991 switch (order->GetType()) {
992 case OT_GOTO_STATION:
993 if (row_sel != nullptr) {
995 } else {
1002 }
1005
1006 /* Can only do refitting when stopping at the destination and loading cargo.
1007 * Also enable the button if a refit is already set to allow clearing it. */
1010 ((!this->can_do_refit || !this->can_do_autorefit) && !order->IsRefit()));
1011
1012 break;
1013
1014 case OT_GOTO_WAYPOINT:
1015 if (row_sel != nullptr) {
1017 } else {
1024 }
1028 break;
1029
1030 case OT_GOTO_DEPOT:
1031 if (row_sel != nullptr) {
1033 } else {
1040 }
1041 /* Disable refit button if the order is no 'always go' order.
1042 * However, keep the service button enabled for refit-orders to allow clearing refits (without knowing about ctrl). */
1044 (order->GetDepotOrderType() & ODTFB_SERVICE) || (order->GetDepotActionType() & ODATFB_HALT) ||
1045 (!this->can_do_refit && !order->IsRefit()));
1046 break;
1047
1048 case OT_CONDITIONAL: {
1049 if (row_sel != nullptr) {
1051 } else {
1053 }
1055 /* Set the strings for the dropdown boxes. */
1056 this->GetWidget<NWidgetCore>(WID_O_COND_VARIABLE)->SetString(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv);
1057 this->GetWidget<NWidgetCore>(WID_O_COND_COMPARATOR)->SetString(_order_conditional_condition[order->GetConditionComparator()]);
1060 break;
1061 }
1062
1063 default: // every other order
1064 if (row_sel != nullptr) {
1066 } else {
1072 }
1076 break;
1077 }
1078 }
1079
1080 /* Disable list of vehicles with the same shared orders if there is no list */
1081 this->SetWidgetDisabledState(WID_O_SHARED_ORDER_LIST, !shared_orders);
1082
1083 this->SetDirty();
1084 }
1085
1086 void OnPaint() override
1087 {
1088 if (this->vehicle->owner != _local_company) {
1089 this->selected_order = -1; // Disable selection any selected row at a competitor order window.
1090 } else {
1091 this->SetWidgetLoweredState(WID_O_GOTO, this->goto_type != OPOS_NONE);
1092 }
1093 this->DrawWidgets();
1094 }
1095
1096 void DrawWidget(const Rect &r, WidgetID widget) const override
1097 {
1098 if (widget != WID_O_ORDER_LIST) return;
1099
1100 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
1101 bool rtl = _current_text_dir == TD_RTL;
1102 uint64_t max_value = GetParamMaxValue(this->vehicle->GetNumOrders(), 2);
1103 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;
1104 int middle = rtl ? ir.right - index_column_width : ir.left + index_column_width;
1105
1106 int y = ir.top;
1107 int line_height = this->GetWidget<NWidgetBase>(WID_O_ORDER_LIST)->resize_y;
1108
1109 VehicleOrderID i = this->vscroll->GetPosition();
1110 VehicleOrderID num_orders = this->vehicle->GetNumOrders();
1111
1112 /* First draw the highlighting underground if it exists. */
1113 if (this->order_over != INVALID_VEH_ORDER_ID) {
1114 while (i < num_orders) {
1115 /* Don't draw anything if it extends past the end of the window. */
1116 if (!this->vscroll->IsVisible(i)) break;
1117
1118 if (i != this->selected_order && i == this->order_over) {
1119 /* Highlight dragged order destination. */
1120 int top = (this->order_over < this->selected_order ? y : y + line_height) - WidgetDimensions::scaled.framerect.top;
1121 int bottom = std::min(top + 2, ir.bottom);
1122 top = std::max(top - 3, ir.top);
1123 GfxFillRect(ir.left, top, ir.right, bottom, GetColourGradient(COLOUR_GREY, SHADE_LIGHTEST));
1124 break;
1125 }
1126 y += line_height;
1127
1128 i++;
1129 }
1130
1131 /* Reset counters for drawing the orders. */
1132 y = ir.top;
1133 i = this->vscroll->GetPosition();
1134 }
1135
1136 /* Draw the orders. */
1137 while (i < num_orders) {
1138 /* Don't draw anything if it extends past the end of the window. */
1139 if (!this->vscroll->IsVisible(i)) break;
1140
1141 DrawOrderString(this->vehicle, this->vehicle->GetOrder(i), i, y, i == this->selected_order, false, ir.left, middle, ir.right);
1142 y += line_height;
1143
1144 i++;
1145 }
1146
1147 if (this->vscroll->IsVisible(i)) {
1148 StringID str = this->vehicle->IsOrderListShared() ? STR_ORDERS_END_OF_SHARED_ORDERS : STR_ORDERS_END_OF_ORDERS;
1149 DrawString(rtl ? ir.left : middle, rtl ? middle : ir.right, y, str, (i == this->selected_order) ? TC_WHITE : TC_BLACK);
1150 }
1151 }
1152
1153 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1154 {
1155 switch (widget) {
1156 case WID_O_COND_VALUE: {
1157 VehicleOrderID sel = this->OrderGetSel();
1158 const Order *order = this->vehicle->GetOrder(sel);
1159
1160 if (order != nullptr && order->IsType(OT_CONDITIONAL)) {
1161 uint value = order->GetConditionValue();
1162 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1163 return GetString(STR_JUST_COMMA, value);
1164 }
1165 return {};
1166 }
1167
1168 case WID_O_CAPTION:
1169 return GetString(STR_ORDERS_CAPTION, this->vehicle->index);
1170
1171 case WID_O_DEPOT_ACTION: {
1172 VehicleOrderID sel = this->OrderGetSel();
1173 const Order *order = this->vehicle->GetOrder(sel);
1174 if (order == nullptr || !order->IsType(OT_GOTO_DEPOT)) return {};
1175
1176 /* Select the current action selected in the dropdown. The flags don't match the dropdown so we can't just use an index. */
1177 if (order->GetDepotOrderType() & ODTFB_SERVICE) return GetString(STR_ORDER_DROP_SERVICE_DEPOT);
1178 if (order->GetDepotActionType() & ODATFB_HALT) return GetString(STR_ORDER_DROP_HALT_DEPOT);
1179 if (order->GetDepotActionType() & ODATFB_UNBUNCH) return GetString(STR_ORDER_DROP_UNBUNCH);
1180
1181 return GetString(STR_ORDER_DROP_GO_ALWAYS_DEPOT);
1182 }
1183
1184 default:
1185 return this->Window::GetWidgetString(widget, stringid);
1186 }
1187 }
1188
1189 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1190 {
1191 switch (widget) {
1192 case WID_O_ORDER_LIST: {
1193 if (this->goto_type == OPOS_CONDITIONAL) {
1194 VehicleOrderID order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
1195 if (order_id != INVALID_VEH_ORDER_ID) {
1196 Order order{};
1197 order.MakeConditional(order_id);
1198
1199 Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
1200 }
1202 break;
1203 }
1204
1205 VehicleOrderID sel = this->GetOrderFromPt(pt.y);
1206
1207 if (_ctrl_pressed && sel < this->vehicle->GetNumOrders()) {
1208 TileIndex xy = this->vehicle->GetOrder(sel)->GetLocation(this->vehicle);
1209 if (xy != INVALID_TILE) ScrollMainWindowToTile(xy);
1210 return;
1211 }
1212
1213 /* This order won't be selected any more, close all child windows and dropdowns */
1214 this->CloseChildWindows();
1215
1216 if (sel == INVALID_VEH_ORDER_ID || this->vehicle->owner != _local_company) {
1217 /* Deselect clicked order */
1218 this->selected_order = -1;
1219 } else if (sel == this->selected_order && click_count > 1) {
1220 if (this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
1221 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER,
1222 this->vehicle->tile, this->vehicle->index, sel,
1223 MOF_STOP_LOCATION, (this->vehicle->GetOrder(sel)->GetStopLocation() + 1) % OSL_END);
1224 }
1225 } else {
1226 /* Select clicked order */
1227 this->selected_order = sel;
1228
1229 if (this->vehicle->owner == _local_company) {
1230 /* Activate drag and drop */
1232 }
1233 }
1234
1235 this->UpdateButtonState();
1236 break;
1237 }
1238
1239 case WID_O_SKIP:
1240 this->OrderClick_Skip();
1241 break;
1242
1243 case WID_O_DELETE:
1244 this->OrderClick_Delete();
1245 break;
1246
1247 case WID_O_STOP_SHARING:
1248 this->OrderClick_StopSharing();
1249 break;
1250
1251 case WID_O_NON_STOP:
1252 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1253 this->OrderClick_Nonstop(-1);
1254 } else {
1255 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1256 assert(o != nullptr);
1257 ShowDropDownMenu(this, _order_non_stop_drowdown, o->GetNonStopType(), WID_O_NON_STOP, 0,
1258 o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
1259 }
1260 break;
1261
1262 case WID_O_GOTO:
1263 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1264 if (this->goto_type != OPOS_NONE) {
1266 } else {
1267 this->OrderClick_Goto(OPOS_GOTO);
1268 }
1269 } else {
1270 int sel;
1271 switch (this->goto_type) {
1272 case OPOS_NONE: sel = -1; break;
1273 case OPOS_GOTO: sel = 0; break;
1274 case OPOS_CONDITIONAL: sel = 2; break;
1275 case OPOS_SHARE: sel = 3; break;
1276 default: NOT_REACHED();
1277 }
1278 ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, sel, WID_O_GOTO, 0, 0);
1279 }
1280 break;
1281
1282 case WID_O_FULL_LOAD:
1283 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1285 } else {
1286 ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), WID_O_FULL_LOAD, 0, 2);
1287 }
1288 break;
1289
1290 case WID_O_UNLOAD:
1291 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1292 this->OrderClick_Unload(OUFB_UNLOAD, true);
1293 } else {
1294 ShowDropDownMenu(this, _order_unload_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType(), WID_O_UNLOAD, 0, 8);
1295 }
1296 break;
1297
1298 case WID_O_REFIT:
1299 this->OrderClick_Refit(0, false);
1300 break;
1301
1302 case WID_O_DEPOT_ACTION:
1303 ShowDropDownMenu(this, _order_depot_action_dropdown, DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel())), WID_O_DEPOT_ACTION, 0, 0);
1304 break;
1305
1307 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1308 this->OrderClick_Refit(0, true);
1309 } else {
1310 ShowDropDownMenu(this, _order_refit_action_dropdown, 0, WID_O_REFIT_DROPDOWN, 0, 0);
1311 }
1312 break;
1313
1315 ShowTimetableWindow(this->vehicle);
1316 break;
1317
1318 case WID_O_COND_VARIABLE: {
1319 DropDownList list;
1320 for (const auto &ocv : _order_conditional_variable) {
1321 list.push_back(MakeDropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv, ocv));
1322 }
1323 ShowDropDownList(this, std::move(list), this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), WID_O_COND_VARIABLE);
1324 break;
1325 }
1326
1327 case WID_O_COND_COMPARATOR: {
1328 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1329 assert(o != nullptr);
1330 ShowDropDownMenu(this, _order_conditional_condition, o->GetConditionComparator(), WID_O_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
1331 break;
1332 }
1333
1334 case WID_O_COND_VALUE: {
1335 const Order *order = this->vehicle->GetOrder(this->OrderGetSel());
1336 assert(order != nullptr);
1337 uint value = order->GetConditionValue();
1338 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1339 ShowQueryString(GetString(STR_JUST_INT, value), STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, this, CS_NUMERAL, {});
1340 break;
1341 }
1342
1344 ShowVehicleListWindow(this->vehicle);
1345 break;
1346 }
1347 }
1348
1349 void OnQueryTextFinished(std::optional<std::string> str) override
1350 {
1351 if (!str.has_value() || str->empty()) return;
1352
1353 VehicleOrderID sel = this->OrderGetSel();
1354 auto value = ParseInteger(*str, 10, true);
1355 if (!value.has_value()) return;
1356
1357 switch (this->vehicle->GetOrder(sel)->GetConditionVariable()) {
1358 case OCV_MAX_SPEED:
1359 value = ConvertDisplaySpeedToSpeed(*value, this->vehicle->type);
1360 break;
1361
1362 case OCV_RELIABILITY:
1364 value = Clamp(*value, 0, 100);
1365 break;
1366
1367 default:
1368 break;
1369 }
1370 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel, MOF_COND_VALUE, Clamp(*value, 0, 2047));
1371 }
1372
1373 void OnDropdownSelect(WidgetID widget, int index, int) override
1374 {
1375 switch (widget) {
1376 case WID_O_NON_STOP:
1377 this->OrderClick_Nonstop(index);
1378 break;
1379
1380 case WID_O_FULL_LOAD:
1381 this->OrderClick_FullLoad((OrderLoadFlags)index);
1382 break;
1383
1384 case WID_O_UNLOAD:
1385 this->OrderClick_Unload((OrderUnloadFlags)index);
1386 break;
1387
1388 case WID_O_GOTO:
1389 switch (index) {
1390 case 0: this->OrderClick_Goto(OPOS_GOTO); break;
1391 case 1: this->OrderClick_NearestDepot(); break;
1392 case 2: this->OrderClick_Goto(OPOS_CONDITIONAL); break;
1393 case 3: this->OrderClick_Goto(OPOS_SHARE); break;
1394 default: NOT_REACHED();
1395 }
1396 break;
1397
1398 case WID_O_DEPOT_ACTION:
1399 this->OrderClick_Service(index);
1400 break;
1401
1403 this->OrderClick_Refit(index, true);
1404 break;
1405
1407 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_VARIABLE, index);
1408 break;
1409
1411 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_COMPARATOR, index);
1412 break;
1413 }
1414 }
1415
1416 void OnDragDrop(Point pt, WidgetID widget) override
1417 {
1418 switch (widget) {
1419 case WID_O_ORDER_LIST: {
1420 VehicleOrderID from_order = this->OrderGetSel();
1421 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1422
1423 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()) &&
1424 Command<CMD_MOVE_ORDER>::Post(STR_ERROR_CAN_T_MOVE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, from_order, to_order)) {
1425 this->selected_order = -1;
1426 this->UpdateButtonState();
1427 }
1428 break;
1429 }
1430
1431 case WID_O_DELETE:
1432 this->OrderClick_Delete();
1433 break;
1434
1435 case WID_O_STOP_SHARING:
1436 this->OrderClick_StopSharing();
1437 break;
1438 }
1439
1441
1442 if (this->order_over != INVALID_VEH_ORDER_ID) {
1443 /* End of drag-and-drop, hide dragged order destination highlight. */
1444 this->order_over = INVALID_VEH_ORDER_ID;
1446 }
1447 }
1448
1449 EventState OnHotkey(int hotkey) override
1450 {
1451 if (this->vehicle->owner != _local_company) return ES_NOT_HANDLED;
1452
1453 switch (hotkey) {
1454 case OHK_SKIP: this->OrderClick_Skip(); break;
1455 case OHK_DELETE: this->OrderClick_Delete(); break;
1456 case OHK_GOTO: this->OrderClick_Goto(OPOS_GOTO); break;
1457 case OHK_NONSTOP: this->OrderClick_Nonstop(-1); break;
1458 case OHK_FULLLOAD: this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true); break;
1459 case OHK_UNLOAD: this->OrderClick_Unload(OUFB_UNLOAD, true); break;
1460 case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break;
1461 case OHK_ALWAYS_SERVICE: this->OrderClick_Service(-1); break;
1462 case OHK_TRANSFER: this->OrderClick_Unload(OUFB_TRANSFER, true); break;
1463 case OHK_NO_UNLOAD: this->OrderClick_Unload(OUFB_NO_UNLOAD, true); break;
1464 case OHK_NO_LOAD: this->OrderClick_FullLoad(OLFB_NO_LOAD, true); break;
1465 default: return ES_NOT_HANDLED;
1466 }
1467 return ES_HANDLED;
1468 }
1469
1470 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1471 {
1472 if (this->goto_type == OPOS_GOTO) {
1473 const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
1474 if (cmd.IsType(OT_NOTHING)) return;
1475
1476 if (Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), cmd)) {
1477 /* With quick goto the Go To button stays active */
1479 }
1480 }
1481 }
1482
1483 bool OnVehicleSelect(const Vehicle *v) override
1484 {
1485 /* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet.
1486 * We disallow copying orders of other vehicles if we already have at least one order entry
1487 * ourself as it easily copies orders of vehicles within a station when we mean the station.
1488 * Obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
1489 * TODO: give a warning message */
1490 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1491 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1492
1493 if (Command<CMD_CLONE_ORDER>::Post(share_order ? STR_ERROR_CAN_T_SHARE_ORDER_LIST : STR_ERROR_CAN_T_COPY_ORDER_LIST,
1494 this->vehicle->tile, share_order ? CO_SHARE : CO_COPY, this->vehicle->index, v->index)) {
1495 this->selected_order = -1;
1497 }
1498 return true;
1499 }
1500
1507 bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
1508 {
1509 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1510 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1511
1512 if (!share_order) {
1513 /* If CTRL is not pressed: If all the vehicles in this list have the same orders, then copy orders */
1514 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1515 return VehiclesHaveSameOrderList(v1, v2);
1516 })) {
1517 OnVehicleSelect(*begin);
1518 } else {
1519 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST), WL_INFO);
1520 }
1521 } else {
1522 /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */
1523 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1524 return v1->FirstShared() == v2->FirstShared();
1525 })) {
1526 OnVehicleSelect(*begin);
1527 } else {
1528 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST), WL_INFO);
1529 }
1530 }
1531
1532 return true;
1533 }
1534
1535 void OnPlaceObjectAbort() override
1536 {
1537 this->goto_type = OPOS_NONE;
1539
1540 /* Remove drag highlighting if it exists. */
1541 if (this->order_over != INVALID_VEH_ORDER_ID) {
1542 this->order_over = INVALID_VEH_ORDER_ID;
1544 }
1545 }
1546
1547 void OnMouseDrag(Point pt, WidgetID widget) override
1548 {
1549 if (this->selected_order != -1 && widget == WID_O_ORDER_LIST) {
1550 /* An order is dragged.. */
1551 VehicleOrderID from_order = this->OrderGetSel();
1552 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1553 uint num_orders = this->vehicle->GetNumOrders();
1554
1555 if (from_order != INVALID_VEH_ORDER_ID && from_order <= num_orders) {
1556 if (to_order != INVALID_VEH_ORDER_ID && to_order <= num_orders) { // ..over an existing order.
1557 this->order_over = to_order;
1558 this->SetWidgetDirty(widget);
1559 } else if (from_order != to_order && this->order_over != INVALID_VEH_ORDER_ID) { // ..outside of the order list.
1560 this->order_over = INVALID_VEH_ORDER_ID;
1561 this->SetWidgetDirty(widget);
1562 }
1563 }
1564 }
1565 }
1566
1567 void OnResize() override
1568 {
1569 /* Update the scroll bar */
1570 this->vscroll->SetCapacityFromWidget(this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.Vertical());
1571 }
1572
1573 static inline HotkeyList hotkeys{"order", {
1574 Hotkey('D', "skip", OHK_SKIP),
1575 Hotkey('F', "delete", OHK_DELETE),
1576 Hotkey('G', "goto", OHK_GOTO),
1577 Hotkey('H', "nonstop", OHK_NONSTOP),
1578 Hotkey('J', "fullload", OHK_FULLLOAD),
1579 Hotkey('K', "unload", OHK_UNLOAD),
1580 Hotkey(0, "nearest_depot", OHK_NEAREST_DEPOT),
1581 Hotkey(0, "always_service", OHK_ALWAYS_SERVICE),
1582 Hotkey(0, "transfer", OHK_TRANSFER),
1583 Hotkey(0, "no_unload", OHK_NO_UNLOAD),
1584 Hotkey(0, "no_load", OHK_NO_LOAD),
1585 }};
1586};
1587
1591 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1592 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION),
1593 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1594 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1595 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1596 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1597 EndContainer(),
1599 NWidget(WWT_PANEL, COLOUR_GREY, WID_O_ORDER_LIST), SetMinimalSize(372, 62), SetToolTip(STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_O_SCROLLBAR), EndContainer(),
1601 EndContainer(),
1602
1603 /* First button row. */
1607 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_NON_STOP), SetMinimalSize(93, 12), SetFill(1, 0),
1608 SetStringTip(STR_ORDER_NON_STOP, STR_ORDER_TOOLTIP_NON_STOP), SetResize(1, 0),
1609 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_LEFT),
1610 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_FULL_LOAD), SetMinimalSize(93, 12), SetFill(1, 0),
1611 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1612 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_REFIT), SetMinimalSize(93, 12), SetFill(1, 0),
1613 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1614 EndContainer(),
1616 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_UNLOAD), SetMinimalSize(93, 12), SetFill(1, 0),
1617 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1619 SetStringTip(STR_JUST_STRING), SetResize(1, 0),
1620 EndContainer(),
1621 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_RIGHT),
1622 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(93, 12), SetFill(1, 0), SetResize(1, 0), EndContainer(),
1624 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1625 EndContainer(),
1626 EndContainer(),
1628 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
1629 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1630 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
1631 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1632 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
1633 SetToolTip(STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1634 EndContainer(),
1635 EndContainer(),
1636 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_O_SHARED_ORDER_LIST), SetAspect(1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
1637 EndContainer(),
1638
1639 /* Second button row. */
1642 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
1643 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1645 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
1646 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1647 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
1648 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1649 EndContainer(),
1650 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
1651 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1652 EndContainer(),
1653 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1654 EndContainer(),
1655};
1656
1657static WindowDesc _orders_train_desc(
1658 WDP_AUTO, "view_vehicle_orders_train", 384, 100,
1662 &OrdersWindow::hotkeys
1663);
1664
1668 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1669 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1670 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1671 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1672 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1673 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1674 EndContainer(),
1676 NWidget(WWT_PANEL, COLOUR_GREY, WID_O_ORDER_LIST), SetMinimalSize(372, 62), SetToolTip(STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_O_SCROLLBAR), EndContainer(),
1678 EndContainer(),
1679
1680 /* First button row. */
1682 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_ROW),
1683 /* Load + unload + refit buttons. */
1685 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_FULL_LOAD), SetMinimalSize(124, 12), SetFill(1, 0),
1686 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1687 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_UNLOAD), SetMinimalSize(124, 12), SetFill(1, 0),
1688 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1690 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1691 EndContainer(),
1692 /* Refit + service buttons. */
1694 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_REFIT), SetMinimalSize(186, 12), SetFill(1, 0),
1695 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1697 SetResize(1, 0),
1698 EndContainer(),
1699
1700 /* Buttons for setting a condition. */
1702 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
1703 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1704 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
1705 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1706 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
1707 SetStringTip(STR_JUST_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1708 EndContainer(),
1709 EndContainer(),
1710
1711 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_O_SHARED_ORDER_LIST), SetAspect(1), SetSpriteTip(SPR_SHARED_ORDERS_ICON, STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP),
1712 EndContainer(),
1713
1714 /* Second button row. */
1716 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
1717 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1719 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
1720 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1721 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
1722 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1723 EndContainer(),
1724 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
1725 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1726 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1727 EndContainer(),
1728};
1729
1730static WindowDesc _orders_desc(
1731 WDP_AUTO, "view_vehicle_orders", 384, 100,
1735 &OrdersWindow::hotkeys
1736);
1737
1741 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1742 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1743 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1744 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1745 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1746 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1747 EndContainer(),
1749 NWidget(WWT_PANEL, COLOUR_GREY, WID_O_ORDER_LIST), SetMinimalSize(372, 72), SetToolTip(STR_ORDERS_LIST_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_O_SCROLLBAR), EndContainer(),
1752 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1753 EndContainer(),
1754 EndContainer(),
1755};
1756
1757static WindowDesc _other_orders_desc(
1758 WDP_AUTO, "view_vehicle_orders_competitor", 384, 86,
1762 &OrdersWindow::hotkeys
1763);
1764
1765void ShowOrdersWindow(const Vehicle *v)
1766{
1769 if (BringWindowToFrontById(WC_VEHICLE_ORDERS, v->index) != nullptr) return;
1770
1771 /* Using a different WindowDescs for _local_company causes problems.
1772 * Due to this we have to close order windows in ChangeWindowOwner/CloseCompanyWindows,
1773 * because we cannot change switch the WindowDescs and keeping the old WindowDesc results
1774 * in crashed due to missing widges.
1775 * TODO Rewrite the order GUI to not use different WindowDescs.
1776 */
1777 if (v->owner != _local_company) {
1778 new OrdersWindow(_other_orders_desc, v);
1779 } else {
1780 new OrdersWindow(v->IsGroundVehicle() ? _orders_train_desc : _orders_desc, v);
1781 }
1782}
Base for aircraft.
debug_inline 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:78
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:79
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:1171
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:1443
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:2482
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:2556
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:19
DestinationID GetDepotDestinationIndex(Tile t)
Get the destination index of a 'depot'.
Definition depot_map.h:66
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:451
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:414
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:1287
Functions related to engines.
@ AutoRefit
Automatic refitting is allowed.
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:77
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:958
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:887
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:925
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:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
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:1024
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:251
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:385
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:395
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:302
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:326
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 NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
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 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:955
Hotkey related functions.
Base of all industries.
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.
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.
uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type)
Convert the given (internal) speed to the display speed.
Definition strings.cpp:958
static constexpr NWidgetPart _nested_other_orders_widgets[]
Nested widget definition for competitor orders.
static constexpr NWidgetPart _nested_orders_train_widgets[]
Nested widget definition for "your" train orders.
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 NWidgetPart _nested_orders_widgets[]
Nested widget definition for "your" orders (non-train).
uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
Convert the given display speed to the (internal) speed.
Definition strings.cpp:971
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.
OrderConditionVariable
Variables (of a vehicle) to 'cause' skipping on.
Definition order_type.h:128
@ OCV_AGE
Skip based on the age.
Definition order_type.h:132
@ OCV_UNCONDITIONALLY
Always skip.
Definition order_type.h:134
@ OCV_MAX_SPEED
Skip based on the maximum speed.
Definition order_type.h:131
@ OCV_LOAD_PERCENTAGE
Skip based on the amount of load.
Definition order_type.h:129
@ OCV_REQUIRES_SERVICE
Skip when the vehicle requires service.
Definition order_type.h:133
@ OCV_RELIABILITY
Skip based on the reliability.
Definition order_type.h:130
@ OCV_REMAINING_LIFETIME
Skip based on the remaining lifetime.
Definition order_type.h:135
@ OCV_MAX_RELIABILITY
Skip based on the maximum reliability.
Definition order_type.h:136
OrderStopLocation
Where to stop the trains.
Definition order_type.h:98
@ OSL_PLATFORM_FAR_END
Stop at the far end of the platform.
Definition order_type.h:101
@ MOF_COND_VARIABLE
A conditional variable changes.
Definition order_type.h:165
@ MOF_LOAD
Passes an OrderLoadType.
Definition order_type.h:163
@ MOF_UNLOAD
Passes an OrderUnloadType.
Definition order_type.h:162
@ MOF_STOP_LOCATION
Passes an OrderStopLocation.
Definition order_type.h:161
@ MOF_COND_COMPARATOR
A comparator changes.
Definition order_type.h:166
@ MOF_COND_VALUE
The value to set the condition to.
Definition order_type.h:167
@ MOF_DEPOT_ACTION
Selects the OrderDepotAction.
Definition order_type.h:164
@ MOF_NON_STOP
Passes an OrderNonStopFlags.
Definition order_type.h:160
OrderUnloadFlags
Flags related to the unloading order.
Definition order_type.h:67
@ OUFB_TRANSFER
Transfer all cargo onto the platform.
Definition order_type.h:70
@ OUFB_NO_UNLOAD
Totally no unloading will be done.
Definition order_type.h:71
@ OUF_UNLOAD_IF_POSSIBLE
Unload all cargo that the station accepts.
Definition order_type.h:68
@ OUFB_UNLOAD
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:69
@ DA_SERVICE
Service only if needed.
Definition order_type.h:177
@ DA_STOP
Go to the depot and stop there.
Definition order_type.h:178
@ DA_ALWAYS_GO
Always go to the depot.
Definition order_type.h:176
@ DA_UNBUNCH
Go to the depot and unbunch.
Definition order_type.h:179
@ ODTFB_PART_OF_ORDERS
This depot order is because of a regular order.
Definition order_type.h:111
@ ODTFB_SERVICE
This depot order is because of the servicing limit.
Definition order_type.h:110
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition order_type.h:18
@ ODATFB_UNBUNCH
Service the vehicle and then unbunch it.
Definition order_type.h:121
@ ODATFB_NEAREST_DEPOT
Send the vehicle to the nearest depot.
Definition order_type.h:120
@ ODATFB_HALT
Service the vehicle and then halt it.
Definition order_type.h:119
OrderLoadFlags
Flags related to the loading order.
Definition order_type.h:77
@ OLFB_NO_LOAD
Do not load anything.
Definition order_type.h:81
@ OLF_LOAD_IF_POSSIBLE
Load as long as there is cargo that fits in the train.
Definition order_type.h:78
@ OLF_FULL_LOAD_ANY
Full load a single cargo of the consist.
Definition order_type.h:80
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:143
@ OCC_IS_TRUE
Skip if the variable is true.
Definition order_type.h:150
@ OCC_IS_FALSE
Skip if the variable is false.
Definition order_type.h:151
@ ONSF_NO_STOP_AT_ANY_STATION
The vehicle will not stop at any stations it passes including the destination.
Definition order_type.h:91
@ ONSF_NO_STOP_AT_DESTINATION_STATION
The vehicle will stop at any station it passes except the destination.
Definition order_type.h:90
@ ONSF_STOP_EVERYWHERE
The vehicle will stop at any station it passes and the destination.
Definition order_type.h:88
@ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS
The vehicle will not stop at any stations it passes except the destination.
Definition order_type.h:89
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.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:388
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:1517
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition sprites.h:1396
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:237
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:415
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
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.
uint32_t cached_max_range_sqr
Cached squared maximum range.
Definition aircraft.h:65
uint16_t GetRange() const
Get the range of this aircraft.
Definition aircraft.h:133
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:137
StringID name
Name of this type of cargo.
Definition cargotype.h:91
GUISettings gui
settings related to the GUI
Point pos
logical mouse position
Definition gfx_type.h:126
Dimensions (a width and height) of a rectangle in 2D.
bool new_nonstop
ttdpatch compatible nonstop handling
bool quick_goto
Allow quick access to 'goto button' in vehicle orders window.
uint8_t stop_location
what is the default stop location of trains?
List of hotkeys for a window.
Definition hotkeys.h:37
All data for a single hotkey.
Definition hotkeys.h:21
Defines the internal data of a functional industry.
Definition industry.h:64
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:236
Station * neutral_station
Associated neutral station.
Definition industry.h:94
Partial widget specification to allow NWidgets to be written nested.
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:352
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:89
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition order_base.h:140
OrderConditionVariable GetConditionVariable() const
What variable do we have to compare?
Definition order_base.h:144
void SetLoadType(OrderLoadFlags load_type)
Set how the consist must be loaded.
Definition order_base.h:153
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:99
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition order_base.h:157
VehicleOrderID GetConditionSkipToOrder() const
Get the order to skip to.
Definition order_base.h:148
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition order_base.h:138
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:188
CargoType GetRefitCargo() const
Get the cargo to to refit to.
Definition order_base.h:127
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:72
void MakeGoToStation(StationID destination)
Makes this order a Go To Station order.
Definition order_cmd.cpp:59
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition order_base.h:132
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition order_base.h:159
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
Definition order_cmd.cpp:88
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:179
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:163
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition order_base.h:142
void Free()
'Free' the order
Definition order_cmd.cpp:48
bool IsAutoRefit() const
Is this order a auto-refit order.
Definition order_base.h:120
OrderUnloadFlags GetUnloadType() const
How must the consist be unloaded?
Definition order_base.h:134
OrderConditionComparator GetConditionComparator() const
What is the comparator to use?
Definition order_base.h:146
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:136
bool IsRefit() const
Is this order a refit order.
Definition order_base.h:113
uint16_t GetConditionValue() const
Get the value to base the skip on.
Definition order_base.h:150
void MakeGoToDepot(DestinationID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoType cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition order_cmd.cpp:74
Order window code for all vehicles.
void OrderClick_Refit(int i, bool auto_refit)
Handle the click on the refit button.
void OrderClick_FullLoad(OrderLoadFlags load_type, bool toggle=false)
Handle the click on the full load 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.
const Vehicle * vehicle
Vehicle owning the orders being displayed and manipulated.
void OrderClick_Service(int i)
Handle the click on the service.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OrderClick_Nonstop(int non_stop)
Handle the click on the nonstop button.
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 OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void OrderClick_Unload(OrderUnloadFlags unload_type, bool toggle=false)
Handle the click on the unload button.
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.
bool can_do_autorefit
Vehicle chain can be auto-refitted.
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.
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
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)
Gets station with given index.
static Aircraft * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
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.
bool HasUnbunchingOrder() const
Check if the current vehicle has an unbunching order.
Definition vehicle.cpp:2451
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
OrderList * orders
Pointer to the order list for this vehicle.
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
bool HasFullLoadOrder() const
Check if the current vehicle has a full load order.
Definition vehicle.cpp:2431
Vehicle * PreviousShared() const
Get the previous vehicle of the shared vehicle chain.
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
TileIndex tile
Current tile index.
bool HasConditionalOrder() const
Check if the current vehicle has a conditional order.
Definition vehicle.cpp:2442
Owner owner
Which company owns the vehicle?
High level window description.
Definition window_gui.h:167
Data structure for an opened window.
Definition window_gui.h:273
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1778
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:777
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:469
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:555
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:503
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1064
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:391
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1768
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:316
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:441
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:400
int top
y position of top edge of the window
Definition window_gui.h:310
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:312
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:381
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Stuff related to the text buffer GUI.
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_INDUSTRY
Part of an industry.
Definition tile_type.h:56
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:3250
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3019
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:75
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:67
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:58
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:53
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:77
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:69
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:61
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:60
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:57
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:62
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:72
@ 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:1182
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1265
@ Construction
This window is used for construction; close it whenever changing company.
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:945
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
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: