OpenTTD Source 15.0-beta2
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"
37
39
40#include "table/strings.h"
41
42#include "safeguards.h"
43
44
46static const StringID _station_load_types[][5][5] = {
47 {
48 /* No refitting. */
49 {
52 STR_ORDER_FULL_LOAD,
53 STR_ORDER_FULL_LOAD_ANY,
54 STR_ORDER_NO_LOAD,
55 }, {
56 STR_ORDER_UNLOAD,
58 STR_ORDER_UNLOAD_FULL_LOAD,
59 STR_ORDER_UNLOAD_FULL_LOAD_ANY,
60 STR_ORDER_UNLOAD_NO_LOAD,
61 }, {
62 STR_ORDER_TRANSFER,
64 STR_ORDER_TRANSFER_FULL_LOAD,
65 STR_ORDER_TRANSFER_FULL_LOAD_ANY,
66 STR_ORDER_TRANSFER_NO_LOAD,
67 }, {
68 /* Unload and transfer do not work together. */
74 }, {
75 STR_ORDER_NO_UNLOAD,
77 STR_ORDER_NO_UNLOAD_FULL_LOAD,
78 STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY,
79 STR_ORDER_NO_UNLOAD_NO_LOAD,
80 }
81 }, {
82 /* With auto-refitting. No loading and auto-refitting do not work together. */
83 {
84 STR_ORDER_AUTO_REFIT,
86 STR_ORDER_FULL_LOAD_REFIT,
87 STR_ORDER_FULL_LOAD_ANY_REFIT,
89 }, {
90 STR_ORDER_UNLOAD_REFIT,
92 STR_ORDER_UNLOAD_FULL_LOAD_REFIT,
93 STR_ORDER_UNLOAD_FULL_LOAD_ANY_REFIT,
95 }, {
96 STR_ORDER_TRANSFER_REFIT,
98 STR_ORDER_TRANSFER_FULL_LOAD_REFIT,
99 STR_ORDER_TRANSFER_FULL_LOAD_ANY_REFIT,
101 }, {
102 /* Unload and transfer do not work together. */
108 }, {
109 STR_ORDER_NO_UNLOAD_REFIT,
111 STR_ORDER_NO_UNLOAD_FULL_LOAD_REFIT,
112 STR_ORDER_NO_UNLOAD_FULL_LOAD_ANY_REFIT,
114 }
115 }
116};
117
118static const StringID _order_non_stop_drowdown[] = {
119 STR_ORDER_GO_TO,
120 STR_ORDER_GO_NON_STOP_TO,
121 STR_ORDER_GO_VIA,
122 STR_ORDER_GO_NON_STOP_VIA,
123};
124
125static const StringID _order_full_load_drowdown[] = {
126 STR_ORDER_DROP_LOAD_IF_POSSIBLE,
127 STR_EMPTY,
128 STR_ORDER_DROP_FULL_LOAD_ALL,
129 STR_ORDER_DROP_FULL_LOAD_ANY,
130 STR_ORDER_DROP_NO_LOADING,
131};
132
133static const StringID _order_unload_drowdown[] = {
134 STR_ORDER_DROP_UNLOAD_IF_ACCEPTED,
135 STR_ORDER_DROP_UNLOAD,
136 STR_ORDER_DROP_TRANSFER,
137 STR_EMPTY,
138 STR_ORDER_DROP_NO_UNLOADING,
139};
140
141static const StringID _order_goto_dropdown[] = {
142 STR_ORDER_GO_TO,
143 STR_ORDER_GO_TO_NEAREST_DEPOT,
144 STR_ORDER_CONDITIONAL,
145 STR_ORDER_SHARE,
146};
147
148static const StringID _order_goto_dropdown_aircraft[] = {
149 STR_ORDER_GO_TO,
150 STR_ORDER_GO_TO_NEAREST_HANGAR,
151 STR_ORDER_CONDITIONAL,
152 STR_ORDER_SHARE,
153};
154
166
167static const StringID _order_conditional_condition[] = {
168 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,
169 STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,
170 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,
171 STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS,
172 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,
173 STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS,
174 STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,
175 STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,
176};
177
178extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type);
179extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type);
180
181static const StringID _order_depot_action_dropdown[] = {
182 STR_ORDER_DROP_GO_ALWAYS_DEPOT,
183 STR_ORDER_DROP_SERVICE_DEPOT,
184 STR_ORDER_DROP_HALT_DEPOT,
185 STR_ORDER_DROP_UNBUNCH,
186};
187
188static int DepotActionStringIndex(const Order *order)
189{
190 if (order->GetDepotActionType() & ODATFB_HALT) {
191 return DA_STOP;
192 } else if (order->GetDepotOrderType() & ODTFB_SERVICE) {
193 return DA_SERVICE;
194 } else if (order->GetDepotActionType() & ODATFB_UNBUNCH) {
195 return DA_UNBUNCH;
196 } else {
197 return DA_ALWAYS_GO;
198 }
199}
200
201static const StringID _order_refit_action_dropdown[] = {
202 STR_ORDER_DROP_REFIT_AUTO,
203 STR_ORDER_DROP_REFIT_AUTO_ANY,
204};
205
206static StringID GetOrderGoToString(const Order &order)
207{
208 if (order.GetDepotOrderType() & ODTFB_SERVICE) {
209 return (order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_SERVICE_NON_STOP_AT : STR_ORDER_SERVICE_AT;
210 } else {
211 return (order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO : STR_ORDER_GO_TO;
212 }
213}
214
227void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable, int left, int middle, int right)
228{
229 bool rtl = _current_text_dir == TD_RTL;
230
231 SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
232 Dimension sprite_size = GetSpriteSize(sprite);
233 if (v->cur_real_order_index == order_index) {
234 /* Draw two arrows before the next real order. */
235 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
236 DrawSprite(sprite, PAL_NONE, rtl ? right - 2 * sprite_size.width : left + sprite_size.width, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
237 } else if (v->cur_implicit_order_index == order_index) {
238 /* Draw one arrow before the next implicit order; the next real order will still get two arrows. */
239 DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)GetCharacterHeight(FS_NORMAL) - (int)sprite_size.height) / 2);
240 }
241
242 TextColour colour = TC_BLACK;
243 if (order->IsType(OT_IMPLICIT)) {
244 colour = (selected ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
245 } else if (selected) {
246 colour = TC_WHITE;
247 }
248
249 DrawString(left, rtl ? right - 2 * sprite_size.width - 3 : middle, y, GetString(STR_ORDER_INDEX, order_index + 1), colour, SA_RIGHT | SA_FORCE);
250
251 std::string line;
252
253 switch (order->GetType()) {
254 case OT_DUMMY:
255 line = GetString(STR_INVALID_ORDER);
256 break;
257
258 case OT_IMPLICIT:
259 line = GetString(STR_ORDER_GO_TO_STATION, STR_ORDER_GO_TO, order->GetDestination());
260 if (!timetable) line += GetString(STR_ORDER_IMPLICIT);
261 break;
262
263 case OT_GOTO_STATION: {
264 OrderLoadFlags load = order->GetLoadType();
265 OrderUnloadFlags unload = order->GetUnloadType();
266 bool valid_station = CanVehicleUseStation(v, Station::Get(order->GetDestination().ToStationID()));
267
268 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());
269 if (timetable) {
270 /* Show only wait time in the timetable window. */
271 if (order->GetWaitTime() > 0) {
272 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
273 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_STAY_FOR : STR_TIMETABLE_STAY_FOR_ESTIMATED, str, value);
274 }
275 } else {
276 /* Show non-stop, refit and stop location only in the order window. */
278 StringID str = _station_load_types[order->IsRefit()][unload][load];
279 if (str != INVALID_STRING_ID) {
280 if (order->IsRefit()) {
281 line += GetString(str, order->IsAutoRefit() ? STR_ORDER_AUTO_REFIT_ANY : CargoSpec::Get(order->GetRefitCargo())->name);
282 } else {
283 line += GetString(str);
284 }
285 }
286 }
287
288 if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) {
289 /* Only show the stopping location if other than the default chosen by the player. */
291 line += GetString(STR_ORDER_STOP_LOCATION_NEAR_END + order->GetStopLocation());
292 }
293 }
294 }
295 break;
296 }
297
298 case OT_GOTO_DEPOT:
299 if (!(order->GetDepotActionType() & ODATFB_NEAREST_DEPOT)) {
300 /* Going to a specific depot. */
301 line = GetString(STR_ORDER_GO_TO_DEPOT_FORMAT, GetOrderGoToString(*order), v->type, order->GetDestination());
302 } else if (v->type == VEH_AIRCRAFT) {
303 /* Going to the nearest hangar. */
304 line = GetString(STR_ORDER_GO_TO_NEAREST_HANGAR_FORMAT, GetOrderGoToString(*order));
305 } else {
306 /* Going to the nearest depot. */
307 line = GetString(STR_ORDER_GO_TO_NEAREST_DEPOT_FORMAT, GetOrderGoToString(*order), STR_ORDER_TRAIN_DEPOT + v->type);
308 }
309
310 /* Do not show stopping in the depot in the timetable window. */
311 if (!timetable && (order->GetDepotActionType() & ODATFB_HALT)) {
312 line += GetString(STR_ORDER_STOP_ORDER);
313 }
314
315 /* Do not show refitting in the depot in the timetable window. */
316 if (!timetable && order->IsRefit()) {
317 line += GetString((order->GetDepotActionType() & ODATFB_HALT) ? STR_ORDER_REFIT_STOP_ORDER : STR_ORDER_REFIT_ORDER, CargoSpec::Get(order->GetRefitCargo())->name);
318 }
319
320 /* Show unbunching depot in both order and timetable windows. */
321 if (order->GetDepotActionType() & ODATFB_UNBUNCH) {
322 line += GetString(STR_ORDER_WAIT_TO_UNBUNCH);
323 }
324 break;
325
326 case OT_GOTO_WAYPOINT:
327 line = GetString((order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_ORDER_GO_NON_STOP_TO_WAYPOINT : STR_ORDER_GO_TO_WAYPOINT, order->GetDestination());
328 break;
329
330 case OT_CONDITIONAL:
332 line = GetString(STR_ORDER_CONDITIONAL_UNCONDITIONAL, order->GetConditionSkipToOrder() + 1);
333 } else {
335
336 uint value = order->GetConditionValue();
337 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, v->type);
338
339 line = GetString((occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_ORDER_CONDITIONAL_TRUE_FALSE : STR_ORDER_CONDITIONAL_NUM,
340 order->GetConditionSkipToOrder() + 1,
341 STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable(),
342 STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ,
343 value);
344 }
345
346 if (timetable && order->GetWaitTime() > 0) {
347 auto [str, value] = GetTimetableParameters(order->GetWaitTime());
348 line += GetString(order->IsWaitTimetabled() ? STR_TIMETABLE_AND_TRAVEL_FOR : STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED, str, value);
349 }
350 break;
351
352 default: NOT_REACHED();
353 }
354
355 /* Check range for aircraft. */
356 if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->GetRange() > 0 && order->IsGotoOrder()) {
357 const Order *next = order->next != nullptr ? order->next : v->GetFirstOrder();
358 if (GetOrderDistance(order, next, 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 /* Override the index as it is not coming from a pool, so would not be initialised correctly. */
375 Order order;
376 order.index = OrderID::Begin();
377
378 /* check depot first */
379 if (IsDepotTypeTile(tile, (TransportType)(uint)v->type) && IsTileOwner(tile, _local_company)) {
383
384 if (_ctrl_pressed) {
385 /* Check to see if we are allowed to make this an unbunching order. */
386 bool failed = false;
387 if (v->HasFullLoadOrder()) {
388 /* We don't allow unbunching if the vehicle has a full load order. */
389 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD), WL_INFO);
390 failed = true;
391 } else if (v->HasUnbunchingOrder()) {
392 /* Don't allow a new unbunching order if we already have one. */
393 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED), WL_INFO);
394 failed = true;
395 } else if (v->HasConditionalOrder()) {
396 /* We don't allow unbunching if the vehicle has a conditional order. */
397 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_INSERT_NEW_ORDER), GetEncodedString(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL), WL_INFO);
398 failed = true;
399 }
400
401 /* Return an empty order to bail out. */
402 if (failed) {
403 order.Free();
404 return order;
405 }
406
407 /* Now we are allowed to set the action type. */
409 }
410
411 return order;
412 }
413
414 /* check rail waypoint */
415 if (IsRailWaypointTile(tile) &&
416 v->type == VEH_TRAIN &&
420 return order;
421 }
422
423 /* check road waypoint */
424 if (IsRoadWaypointTile(tile) &&
425 v->type == VEH_ROAD &&
429 return order;
430 }
431
432 /* check buoy (no ownership) */
433 if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
435 return order;
436 }
437
438 /* check for station or industry with neutral station */
439 if (IsTileType(tile, MP_STATION) || IsTileType(tile, MP_INDUSTRY)) {
440 const Station *st = nullptr;
441
442 if (IsTileType(tile, MP_STATION)) {
443 st = Station::GetByTile(tile);
444 } else {
445 const Industry *in = Industry::GetByTile(tile);
446 st = in->neutral_station;
447 }
448 if (st != nullptr && (st->owner == _local_company || st->owner == OWNER_NONE)) {
449 StationFacilities facil;
450 switch (v->type) {
451 case VEH_SHIP: facil = StationFacility::Dock; break;
452 case VEH_TRAIN: facil = StationFacility::Train; break;
453 case VEH_AIRCRAFT: facil = StationFacility::Airport; break;
455 default: NOT_REACHED();
456 }
457 if (st->facilities.Any(facil)) {
458 order.MakeGoToStation(st->index);
462 return order;
463 }
464 }
465 }
466
467 /* not found */
468 order.Free();
469 return order;
470}
471
473enum OrderHotKeys : int32_t {
474 OHK_SKIP,
475 OHK_DELETE,
476 OHK_GOTO,
477 OHK_NONSTOP,
478 OHK_FULLLOAD,
479 OHK_UNLOAD,
480 OHK_NEAREST_DEPOT,
481 OHK_ALWAYS_SERVICE,
482 OHK_TRANSFER,
483 OHK_NO_UNLOAD,
484 OHK_NO_LOAD,
485};
486
527struct OrdersWindow : public Window {
528private:
530 enum OrderPlaceObjectState : uint8_t {
531 OPOS_NONE,
532 OPOS_GOTO,
533 OPOS_CONDITIONAL,
534 OPOS_SHARE,
535 OPOS_END,
536 };
537
539 enum DisplayPane : uint8_t {
540 /* WID_O_SEL_TOP_ROW_GROUNDVEHICLE */
543
544 /* WID_O_SEL_TOP_LEFT */
547
548 /* WID_O_SEL_TOP_MIDDLE */
551
552 /* WID_O_SEL_TOP_RIGHT */
555
556 /* WID_O_SEL_TOP_ROW */
560
561 /* WID_O_SEL_BOTTOM_MIDDLE */
564 };
565
566 int selected_order = -1;
568 OrderPlaceObjectState goto_type = OPOS_NONE;
569 const Vehicle *vehicle = nullptr;
570 Scrollbar *vscroll = nullptr;
571 bool can_do_refit = false;
572 bool can_do_autorefit = false;
573
580 {
581 int num = this->selected_order;
582 return (num >= 0 && num < vehicle->GetNumOrders()) ? num : vehicle->GetNumOrders();
583 }
584
594 {
595 int32_t sel = this->vscroll->GetScrolledRowFromWidget(y, this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.top);
596 if (sel == INT32_MAX) return INVALID_VEH_ORDER_ID;
597 /* One past the orders is the 'End of Orders' line. */
598 assert(IsInsideBS(sel, 0, vehicle->GetNumOrders() + 1));
599 return sel;
600 }
601
606 {
607 assert(type > OPOS_NONE && type < OPOS_END);
608
609 static const HighLightStyle goto_place_style[OPOS_END - 1] = {
610 HT_RECT | HT_VEHICLE, // OPOS_GOTO
611 HT_NONE, // OPOS_CONDITIONAL
612 HT_VEHICLE, // OPOS_SHARE
613 };
614 SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, goto_place_style[type - 1], this);
615 this->goto_type = type;
617 }
618
624 void OrderClick_FullLoad(OrderLoadFlags load_type, bool toggle = false)
625 {
626 VehicleOrderID sel_ord = this->OrderGetSel();
627 const Order *order = this->vehicle->GetOrder(sel_ord);
628
629 if (order == nullptr) return;
630
631 if (toggle && order->GetLoadType() == load_type) {
632 load_type = OLF_LOAD_IF_POSSIBLE; // reset to 'default'
633 }
634 if (order->GetLoadType() == load_type) return; // If we still match, do nothing
635
636 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, load_type);
637 }
638
643 {
644 VehicleOrderID sel_ord = this->OrderGetSel();
645
646 if (i < 0) {
647 const Order *order = this->vehicle->GetOrder(sel_ord);
648 if (order == nullptr) return;
650 }
651 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_DEPOT_ACTION, i);
652 }
653
658 {
659 Order order;
660 order.next = nullptr;
661 order.index = OrderID::Begin();
662 order.MakeGoToDepot(DepotID::Invalid(), ODTFB_PART_OF_ORDERS,
665
666 Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
667 }
668
674 void OrderClick_Unload(OrderUnloadFlags unload_type, bool toggle = false)
675 {
676 VehicleOrderID sel_ord = this->OrderGetSel();
677 const Order *order = this->vehicle->GetOrder(sel_ord);
678
679 if (order == nullptr) return;
680
681 if (toggle && order->GetUnloadType() == unload_type) {
682 unload_type = OUF_UNLOAD_IF_POSSIBLE;
683 }
684 if (order->GetUnloadType() == unload_type) return; // If we still match, do nothing
685
686 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, sel_ord, MOF_UNLOAD, unload_type);
687
688 /* Transfer and unload orders with leave empty as default */
689 if (unload_type == OUFB_TRANSFER || unload_type == OUFB_UNLOAD) {
690 Command<CMD_MODIFY_ORDER>::Post(this->vehicle->tile, this->vehicle->index, sel_ord, MOF_LOAD, OLFB_NO_LOAD);
692 }
693 }
694
699 void OrderClick_Nonstop(int non_stop)
700 {
701 if (!this->vehicle->IsGroundVehicle()) return;
702
703 VehicleOrderID sel_ord = this->OrderGetSel();
704 const Order *order = this->vehicle->GetOrder(sel_ord);
705
706 if (order == nullptr || order->GetNonStopType() == non_stop) return;
707
708 /* Keypress if negative, so 'toggle' to the next */
709 if (non_stop < 0) {
711 }
712
714 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);
715 }
716
722 {
723 /* Don't skip when there's nothing to skip */
724 if (_ctrl_pressed && this->vehicle->cur_implicit_order_index == this->OrderGetSel()) return;
725 if (this->vehicle->GetNumOrders() <= 1) return;
726
727 Command<CMD_SKIP_TO_ORDER>::Post(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER,
728 this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_implicit_order_index + 1) % this->vehicle->GetNumOrders()));
729 }
730
735 {
736 /* When networking, move one order lower */
737 int selected = this->selected_order + (int)_networking;
738
739 if (Command<CMD_DELETE_ORDER>::Post(STR_ERROR_CAN_T_DELETE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel())) {
740 this->selected_order = selected >= this->vehicle->GetNumOrders() ? -1 : selected;
741 this->UpdateButtonState();
742 }
743 }
744
752 {
753 /* Don't try to stop sharing orders if 'End of Shared Orders' isn't selected. */
754 if (!this->vehicle->IsOrderListShared() || this->selected_order != this->vehicle->GetNumOrders()) return;
755 /* If Ctrl is pressed, delete the order list as if we clicked the 'Delete' button. */
756 if (_ctrl_pressed) {
757 this->OrderClick_Delete();
758 return;
759 }
760
761 /* Get another vehicle that share orders with this vehicle. */
762 Vehicle *other_shared = (this->vehicle->FirstShared() == this->vehicle) ? this->vehicle->NextShared() : this->vehicle->PreviousShared();
763 /* Copy the order list of the other vehicle. */
764 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)) {
765 this->UpdateButtonState();
766 }
767 }
768
775 void OrderClick_Refit(int i, bool auto_refit)
776 {
777 if (_ctrl_pressed) {
778 /* Cancel refitting */
779 Command<CMD_ORDER_REFIT>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_NO_REFIT);
780 } else {
781 if (i == 1) { // Auto-refit to available cargo type.
782 Command<CMD_ORDER_REFIT>::Post(this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), CARGO_AUTO_REFIT);
783 } else {
784 ShowVehicleRefitWindow(this->vehicle, this->OrderGetSel(), this, auto_refit);
785 }
786 }
787 }
788
791 {
792 this->can_do_refit = false;
793 this->can_do_autorefit = false;
794 for (const Vehicle *w = this->vehicle; w != nullptr; w = w->IsGroundVehicle() ? w->Next() : nullptr) {
795 if (IsEngineRefittable(w->engine_type)) this->can_do_refit = true;
796 if (Engine::Get(w->engine_type)->info.misc_flags.Test(EngineMiscFlag::AutoRefit)) this->can_do_autorefit = true;
797 }
798 }
799
800public:
801 OrdersWindow(WindowDesc &desc, const Vehicle *v) : Window(desc)
802 {
803 this->vehicle = v;
804
805 this->CreateNestedTree();
806 this->vscroll = this->GetScrollbar(WID_O_SCROLLBAR);
807 if (NWidgetCore *nwid = this->GetWidget<NWidgetCore>(WID_O_DEPOT_ACTION); nwid != nullptr) {
808 nwid->SetToolTip(STR_ORDER_TRAIN_DEPOT_ACTION_TOOLTIP + v->type);
809 }
810 this->FinishInitNested(v->index);
811
812 this->owner = v->owner;
813
814 this->UpdateAutoRefitState();
815
817 /* If there are less than 2 station, make Go To active. */
818 int station_orders = 0;
819 for (const Order *order : v->Orders()) {
820 if (order->IsType(OT_GOTO_STATION)) station_orders++;
821 }
822
823 if (station_orders < 2) this->OrderClick_Goto(OPOS_GOTO);
824 }
826 }
827
828 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
829 {
830 switch (widget) {
831 case WID_O_ORDER_LIST:
833 size.height = 6 * resize.height + padding.height;
834 break;
835
836 case WID_O_COND_VARIABLE: {
837 Dimension d = {0, 0};
838 for (const auto &ocv : _order_conditional_variable) {
839 d = maxdim(d, GetStringBoundingBox(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv));
840 }
841 d.width += padding.width;
842 d.height += padding.height;
843 size = maxdim(size, d);
844 break;
845 }
846
848 Dimension d = GetStringListBoundingBox(_order_conditional_condition);
849 d.width += padding.width;
850 d.height += padding.height;
851 size = maxdim(size, d);
852 break;
853 }
854 }
855 }
856
862 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
863 {
866
867 switch (data) {
868 case VIWD_AUTOREPLACE:
869 /* Autoreplace replaced the vehicle */
870 this->vehicle = Vehicle::Get(this->window_number);
871 [[fallthrough]];
872
874 /* Vehicle composition was changed. */
875 this->UpdateAutoRefitState();
876 break;
877
879 /* Removed / replaced all orders (after deleting / sharing) */
880 if (this->selected_order == -1) break;
881
882 this->CloseChildWindows();
883 this->selected_order = -1;
884 break;
885
887 /* Some other order changes */
888 break;
889
890 default:
891 if (data < 0) break;
892
893 if (gui_scope) break; // only do this once; from command scope
894 from = GB(data, 0, 8);
895 to = GB(data, 8, 8);
896 /* Moving an order. If one of these is INVALID_VEH_ORDER_ID, then
897 * the order is being created / removed */
898 if (this->selected_order == -1) break;
899
900 if (from == to) break; // no need to change anything
901
902 if (from != this->selected_order) {
903 /* Moving from preceding order? */
904 this->selected_order -= (int)(from <= this->selected_order);
905 /* Moving to preceding order? */
906 this->selected_order += (int)(to <= this->selected_order);
907 break;
908 }
909
910 /* Now we are modifying the selected order */
911 if (to == INVALID_VEH_ORDER_ID) {
912 /* Deleting selected order */
913 this->CloseChildWindows();
914 this->selected_order = -1;
915 break;
916 }
917
918 /* Moving selected order */
919 this->selected_order = to;
920 break;
921 }
922
923 this->vscroll->SetCount(this->vehicle->GetNumOrders() + 1);
924 if (gui_scope) this->UpdateButtonState();
925
926 /* Scroll to the new order. */
927 if (from == INVALID_VEH_ORDER_ID && to != INVALID_VEH_ORDER_ID && !this->vscroll->IsVisible(to)) {
928 this->vscroll->ScrollTowards(to);
929 }
930 }
931
932 void UpdateButtonState()
933 {
934 if (this->vehicle->owner != _local_company) return; // No buttons are displayed with competitor order windows.
935
936 bool shared_orders = this->vehicle->IsOrderListShared();
937 VehicleOrderID sel = this->OrderGetSel();
938 const Order *order = this->vehicle->GetOrder(sel);
939
940 /* Second row. */
941 /* skip */
942 this->SetWidgetDisabledState(WID_O_SKIP, this->vehicle->GetNumOrders() <= 1);
943
944 /* delete / stop sharing */
945 NWidgetStacked *delete_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_BOTTOM_MIDDLE);
946 if (shared_orders && this->selected_order == this->vehicle->GetNumOrders()) {
947 /* The 'End of Shared Orders' order is selected, show the 'stop sharing' button. */
949 } else {
950 /* The 'End of Shared Orders' order isn't selected, show the 'delete' button. */
953 (uint)this->vehicle->GetNumOrders() + ((shared_orders || this->vehicle->GetNumOrders() != 0) ? 1 : 0) <= (uint)this->selected_order);
954
955 /* Set the tooltip of the 'delete' button depending on whether the
956 * 'End of Orders' order or a regular order is selected. */
957 NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_O_DELETE);
958 if (this->selected_order == this->vehicle->GetNumOrders()) {
959 nwi->SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_ALL_TOOLTIP);
960 } else {
961 nwi->SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP);
962 }
963 }
964
965 /* First row. */
968
969 /* Selection widgets. */
970 /* Train or road vehicle. */
971 NWidgetStacked *train_row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW_GROUNDVEHICLE);
972 NWidgetStacked *left_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_LEFT);
973 NWidgetStacked *middle_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_MIDDLE);
974 NWidgetStacked *right_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_RIGHT);
975 /* Ship or airplane. */
976 NWidgetStacked *row_sel = this->GetWidget<NWidgetStacked>(WID_O_SEL_TOP_ROW);
977 assert(row_sel != nullptr || (train_row_sel != nullptr && left_sel != nullptr && middle_sel != nullptr && right_sel != nullptr));
978
979
980 if (order == nullptr) {
981 if (row_sel != nullptr) {
983 } else {
990 }
994 } else {
997
998 switch (order->GetType()) {
999 case OT_GOTO_STATION:
1000 if (row_sel != nullptr) {
1002 } else {
1009 }
1012
1013 /* Can only do refitting when stopping at the destination and loading cargo.
1014 * Also enable the button if a refit is already set to allow clearing it. */
1017 ((!this->can_do_refit || !this->can_do_autorefit) && !order->IsRefit()));
1018
1019 break;
1020
1021 case OT_GOTO_WAYPOINT:
1022 if (row_sel != nullptr) {
1024 } else {
1031 }
1035 break;
1036
1037 case OT_GOTO_DEPOT:
1038 if (row_sel != nullptr) {
1040 } else {
1047 }
1048 /* Disable refit button if the order is no 'always go' order.
1049 * However, keep the service button enabled for refit-orders to allow clearing refits (without knowing about ctrl). */
1051 (order->GetDepotOrderType() & ODTFB_SERVICE) || (order->GetDepotActionType() & ODATFB_HALT) ||
1052 (!this->can_do_refit && !order->IsRefit()));
1053 break;
1054
1055 case OT_CONDITIONAL: {
1056 if (row_sel != nullptr) {
1058 } else {
1060 }
1062 /* Set the strings for the dropdown boxes. */
1063 this->GetWidget<NWidgetCore>(WID_O_COND_VARIABLE)->SetString(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv);
1064 this->GetWidget<NWidgetCore>(WID_O_COND_COMPARATOR)->SetString(_order_conditional_condition[order->GetConditionComparator()]);
1067 break;
1068 }
1069
1070 default: // every other order
1071 if (row_sel != nullptr) {
1073 } else {
1079 }
1083 break;
1084 }
1085 }
1086
1087 /* Disable list of vehicles with the same shared orders if there is no list */
1088 this->SetWidgetDisabledState(WID_O_SHARED_ORDER_LIST, !shared_orders);
1089
1090 this->SetDirty();
1091 }
1092
1093 void OnPaint() override
1094 {
1095 if (this->vehicle->owner != _local_company) {
1096 this->selected_order = -1; // Disable selection any selected row at a competitor order window.
1097 } else {
1098 this->SetWidgetLoweredState(WID_O_GOTO, this->goto_type != OPOS_NONE);
1099 }
1100 this->DrawWidgets();
1101 }
1102
1103 void DrawWidget(const Rect &r, WidgetID widget) const override
1104 {
1105 if (widget != WID_O_ORDER_LIST) return;
1106
1107 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect);
1108 bool rtl = _current_text_dir == TD_RTL;
1109 uint64_t max_value = GetParamMaxValue(this->vehicle->GetNumOrders(), 2);
1110 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;
1111 int middle = rtl ? ir.right - index_column_width : ir.left + index_column_width;
1112
1113 int y = ir.top;
1114 int line_height = this->GetWidget<NWidgetBase>(WID_O_ORDER_LIST)->resize_y;
1115
1116 int i = this->vscroll->GetPosition();
1117 const Order *order = this->vehicle->GetOrder(i);
1118 /* First draw the highlighting underground if it exists. */
1119 if (this->order_over != INVALID_VEH_ORDER_ID) {
1120 while (order != nullptr) {
1121 /* Don't draw anything if it extends past the end of the window. */
1122 if (!this->vscroll->IsVisible(i)) break;
1123
1124 if (i != this->selected_order && i == this->order_over) {
1125 /* Highlight dragged order destination. */
1126 int top = (this->order_over < this->selected_order ? y : y + line_height) - WidgetDimensions::scaled.framerect.top;
1127 int bottom = std::min(top + 2, ir.bottom);
1128 top = std::max(top - 3, ir.top);
1129 GfxFillRect(ir.left, top, ir.right, bottom, GetColourGradient(COLOUR_GREY, SHADE_LIGHTEST));
1130 break;
1131 }
1132 y += line_height;
1133
1134 i++;
1135 order = order->next;
1136 }
1137
1138 /* Reset counters for drawing the orders. */
1139 y = ir.top;
1140 i = this->vscroll->GetPosition();
1141 order = this->vehicle->GetOrder(i);
1142 }
1143
1144 /* Draw the orders. */
1145 while (order != nullptr) {
1146 /* Don't draw anything if it extends past the end of the window. */
1147 if (!this->vscroll->IsVisible(i)) break;
1148
1149 DrawOrderString(this->vehicle, order, i, y, i == this->selected_order, false, ir.left, middle, ir.right);
1150 y += line_height;
1151
1152 i++;
1153 order = order->next;
1154 }
1155
1156 if (this->vscroll->IsVisible(i)) {
1157 StringID str = this->vehicle->IsOrderListShared() ? STR_ORDERS_END_OF_SHARED_ORDERS : STR_ORDERS_END_OF_ORDERS;
1158 DrawString(rtl ? ir.left : middle, rtl ? middle : ir.right, y, str, (i == this->selected_order) ? TC_WHITE : TC_BLACK);
1159 }
1160 }
1161
1162 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1163 {
1164 switch (widget) {
1165 case WID_O_COND_VALUE: {
1166 VehicleOrderID sel = this->OrderGetSel();
1167 const Order *order = this->vehicle->GetOrder(sel);
1168
1169 if (order != nullptr && order->IsType(OT_CONDITIONAL)) {
1170 uint value = order->GetConditionValue();
1171 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1172 return GetString(STR_JUST_COMMA, value);
1173 }
1174 return {};
1175 }
1176
1177 case WID_O_CAPTION:
1178 return GetString(STR_ORDERS_CAPTION, this->vehicle->index);
1179
1180 case WID_O_DEPOT_ACTION: {
1181 VehicleOrderID sel = this->OrderGetSel();
1182 const Order *order = this->vehicle->GetOrder(sel);
1183 if (order == nullptr || !order->IsType(OT_GOTO_DEPOT)) return {};
1184
1185 /* Select the current action selected in the dropdown. The flags don't match the dropdown so we can't just use an index. */
1186 if (order->GetDepotOrderType() & ODTFB_SERVICE) return GetString(STR_ORDER_DROP_SERVICE_DEPOT);
1187 if (order->GetDepotActionType() & ODATFB_HALT) return GetString(STR_ORDER_DROP_HALT_DEPOT);
1188 if (order->GetDepotActionType() & ODATFB_UNBUNCH) return GetString(STR_ORDER_DROP_UNBUNCH);
1189
1190 return GetString(STR_ORDER_DROP_GO_ALWAYS_DEPOT);
1191 }
1192
1193 default:
1194 return this->Window::GetWidgetString(widget, stringid);
1195 }
1196 }
1197
1198 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1199 {
1200 switch (widget) {
1201 case WID_O_ORDER_LIST: {
1202 if (this->goto_type == OPOS_CONDITIONAL) {
1203 VehicleOrderID order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
1204 if (order_id != INVALID_VEH_ORDER_ID) {
1205 Order order;
1206 order.next = nullptr;
1207 order.index = OrderID::Begin();
1208 order.MakeConditional(order_id);
1209
1210 Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), order);
1211 }
1213 break;
1214 }
1215
1216 VehicleOrderID sel = this->GetOrderFromPt(pt.y);
1217
1218 if (_ctrl_pressed && sel < this->vehicle->GetNumOrders()) {
1219 TileIndex xy = this->vehicle->GetOrder(sel)->GetLocation(this->vehicle);
1220 if (xy != INVALID_TILE) ScrollMainWindowToTile(xy);
1221 return;
1222 }
1223
1224 /* This order won't be selected any more, close all child windows and dropdowns */
1225 this->CloseChildWindows();
1226
1227 if (sel == INVALID_VEH_ORDER_ID || this->vehicle->owner != _local_company) {
1228 /* Deselect clicked order */
1229 this->selected_order = -1;
1230 } else if (sel == this->selected_order) {
1231 if (click_count > 1 && this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
1232 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER,
1233 this->vehicle->tile, this->vehicle->index, sel,
1234 MOF_STOP_LOCATION, (this->vehicle->GetOrder(sel)->GetStopLocation() + 1) % OSL_END);
1235 }
1236 } else {
1237 /* Select clicked order */
1238 this->selected_order = sel;
1239
1240 if (this->vehicle->owner == _local_company) {
1241 /* Activate drag and drop */
1243 }
1244 }
1245
1246 this->UpdateButtonState();
1247 break;
1248 }
1249
1250 case WID_O_SKIP:
1251 this->OrderClick_Skip();
1252 break;
1253
1254 case WID_O_DELETE:
1255 this->OrderClick_Delete();
1256 break;
1257
1258 case WID_O_STOP_SHARING:
1259 this->OrderClick_StopSharing();
1260 break;
1261
1262 case WID_O_NON_STOP:
1263 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1264 this->OrderClick_Nonstop(-1);
1265 } else {
1266 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1267 assert(o != nullptr);
1268 ShowDropDownMenu(this, _order_non_stop_drowdown, o->GetNonStopType(), WID_O_NON_STOP, 0,
1269 o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
1270 }
1271 break;
1272
1273 case WID_O_GOTO:
1274 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1275 if (this->goto_type != OPOS_NONE) {
1277 } else {
1278 this->OrderClick_Goto(OPOS_GOTO);
1279 }
1280 } else {
1281 int sel;
1282 switch (this->goto_type) {
1283 case OPOS_NONE: sel = -1; break;
1284 case OPOS_GOTO: sel = 0; break;
1285 case OPOS_CONDITIONAL: sel = 2; break;
1286 case OPOS_SHARE: sel = 3; break;
1287 default: NOT_REACHED();
1288 }
1289 ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, sel, WID_O_GOTO, 0, 0);
1290 }
1291 break;
1292
1293 case WID_O_FULL_LOAD:
1294 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1296 } else {
1297 ShowDropDownMenu(this, _order_full_load_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetLoadType(), WID_O_FULL_LOAD, 0, 2);
1298 }
1299 break;
1300
1301 case WID_O_UNLOAD:
1302 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1303 this->OrderClick_Unload(OUFB_UNLOAD, true);
1304 } else {
1305 ShowDropDownMenu(this, _order_unload_drowdown, this->vehicle->GetOrder(this->OrderGetSel())->GetUnloadType(), WID_O_UNLOAD, 0, 8);
1306 }
1307 break;
1308
1309 case WID_O_REFIT:
1310 this->OrderClick_Refit(0, false);
1311 break;
1312
1313 case WID_O_DEPOT_ACTION:
1314 ShowDropDownMenu(this, _order_depot_action_dropdown, DepotActionStringIndex(this->vehicle->GetOrder(this->OrderGetSel())), WID_O_DEPOT_ACTION, 0, 0);
1315 break;
1316
1318 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
1319 this->OrderClick_Refit(0, true);
1320 } else {
1321 ShowDropDownMenu(this, _order_refit_action_dropdown, 0, WID_O_REFIT_DROPDOWN, 0, 0);
1322 }
1323 break;
1324
1326 ShowTimetableWindow(this->vehicle);
1327 break;
1328
1329 case WID_O_COND_VARIABLE: {
1330 DropDownList list;
1331 for (const auto &ocv : _order_conditional_variable) {
1332 list.push_back(MakeDropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + ocv, ocv));
1333 }
1334 ShowDropDownList(this, std::move(list), this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), WID_O_COND_VARIABLE);
1335 break;
1336 }
1337
1338 case WID_O_COND_COMPARATOR: {
1339 const Order *o = this->vehicle->GetOrder(this->OrderGetSel());
1340 assert(o != nullptr);
1341 ShowDropDownMenu(this, _order_conditional_condition, o->GetConditionComparator(), WID_O_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
1342 break;
1343 }
1344
1345 case WID_O_COND_VALUE: {
1346 const Order *order = this->vehicle->GetOrder(this->OrderGetSel());
1347 assert(order != nullptr);
1348 uint value = order->GetConditionValue();
1349 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value, this->vehicle->type);
1350 ShowQueryString(GetString(STR_JUST_INT, value), STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, this, CS_NUMERAL, {});
1351 break;
1352 }
1353
1355 ShowVehicleListWindow(this->vehicle);
1356 break;
1357 }
1358 }
1359
1360 void OnQueryTextFinished(std::optional<std::string> str) override
1361 {
1362 if (!str.has_value() || str->empty()) return;
1363
1364 VehicleOrderID sel = this->OrderGetSel();
1365 uint value = atoi(str->c_str());
1366
1367 switch (this->vehicle->GetOrder(sel)->GetConditionVariable()) {
1368 case OCV_MAX_SPEED:
1369 value = ConvertDisplaySpeedToSpeed(value, this->vehicle->type);
1370 break;
1371
1372 case OCV_RELIABILITY:
1374 value = Clamp(value, 0, 100);
1375 break;
1376
1377 default:
1378 break;
1379 }
1380 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));
1381 }
1382
1383 void OnDropdownSelect(WidgetID widget, int index) override
1384 {
1385 switch (widget) {
1386 case WID_O_NON_STOP:
1387 this->OrderClick_Nonstop(index);
1388 break;
1389
1390 case WID_O_FULL_LOAD:
1391 this->OrderClick_FullLoad((OrderLoadFlags)index);
1392 break;
1393
1394 case WID_O_UNLOAD:
1395 this->OrderClick_Unload((OrderUnloadFlags)index);
1396 break;
1397
1398 case WID_O_GOTO:
1399 switch (index) {
1400 case 0: this->OrderClick_Goto(OPOS_GOTO); break;
1401 case 1: this->OrderClick_NearestDepot(); break;
1402 case 2: this->OrderClick_Goto(OPOS_CONDITIONAL); break;
1403 case 3: this->OrderClick_Goto(OPOS_SHARE); break;
1404 default: NOT_REACHED();
1405 }
1406 break;
1407
1408 case WID_O_DEPOT_ACTION:
1409 this->OrderClick_Service(index);
1410 break;
1411
1413 this->OrderClick_Refit(index, true);
1414 break;
1415
1417 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_VARIABLE, index);
1418 break;
1419
1421 Command<CMD_MODIFY_ORDER>::Post(STR_ERROR_CAN_T_MODIFY_THIS_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), MOF_COND_COMPARATOR, index);
1422 break;
1423 }
1424 }
1425
1426 void OnDragDrop(Point pt, WidgetID widget) override
1427 {
1428 switch (widget) {
1429 case WID_O_ORDER_LIST: {
1430 VehicleOrderID from_order = this->OrderGetSel();
1431 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1432
1433 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()) &&
1434 Command<CMD_MOVE_ORDER>::Post(STR_ERROR_CAN_T_MOVE_THIS_ORDER, this->vehicle->tile, this->vehicle->index, from_order, to_order)) {
1435 this->selected_order = -1;
1436 this->UpdateButtonState();
1437 }
1438 break;
1439 }
1440
1441 case WID_O_DELETE:
1442 this->OrderClick_Delete();
1443 break;
1444
1445 case WID_O_STOP_SHARING:
1446 this->OrderClick_StopSharing();
1447 break;
1448 }
1449
1451
1452 if (this->order_over != INVALID_VEH_ORDER_ID) {
1453 /* End of drag-and-drop, hide dragged order destination highlight. */
1454 this->order_over = INVALID_VEH_ORDER_ID;
1456 }
1457 }
1458
1459 EventState OnHotkey(int hotkey) override
1460 {
1461 if (this->vehicle->owner != _local_company) return ES_NOT_HANDLED;
1462
1463 switch (hotkey) {
1464 case OHK_SKIP: this->OrderClick_Skip(); break;
1465 case OHK_DELETE: this->OrderClick_Delete(); break;
1466 case OHK_GOTO: this->OrderClick_Goto(OPOS_GOTO); break;
1467 case OHK_NONSTOP: this->OrderClick_Nonstop(-1); break;
1468 case OHK_FULLLOAD: this->OrderClick_FullLoad(OLF_FULL_LOAD_ANY, true); break;
1469 case OHK_UNLOAD: this->OrderClick_Unload(OUFB_UNLOAD, true); break;
1470 case OHK_NEAREST_DEPOT: this->OrderClick_NearestDepot(); break;
1471 case OHK_ALWAYS_SERVICE: this->OrderClick_Service(-1); break;
1472 case OHK_TRANSFER: this->OrderClick_Unload(OUFB_TRANSFER, true); break;
1473 case OHK_NO_UNLOAD: this->OrderClick_Unload(OUFB_NO_UNLOAD, true); break;
1474 case OHK_NO_LOAD: this->OrderClick_FullLoad(OLFB_NO_LOAD, true); break;
1475 default: return ES_NOT_HANDLED;
1476 }
1477 return ES_HANDLED;
1478 }
1479
1480 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1481 {
1482 if (this->goto_type == OPOS_GOTO) {
1483 const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
1484 if (cmd.IsType(OT_NOTHING)) return;
1485
1486 if (Command<CMD_INSERT_ORDER>::Post(STR_ERROR_CAN_T_INSERT_NEW_ORDER, this->vehicle->tile, this->vehicle->index, this->OrderGetSel(), cmd)) {
1487 /* With quick goto the Go To button stays active */
1489 }
1490 }
1491 }
1492
1493 bool OnVehicleSelect(const Vehicle *v) override
1494 {
1495 /* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet.
1496 * We disallow copying orders of other vehicles if we already have at least one order entry
1497 * ourself as it easily copies orders of vehicles within a station when we mean the station.
1498 * Obviously if you press CTRL on a non-empty orders vehicle you know what you are doing
1499 * TODO: give a warning message */
1500 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1501 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1502
1503 if (Command<CMD_CLONE_ORDER>::Post(share_order ? STR_ERROR_CAN_T_SHARE_ORDER_LIST : STR_ERROR_CAN_T_COPY_ORDER_LIST,
1504 this->vehicle->tile, share_order ? CO_SHARE : CO_COPY, this->vehicle->index, v->index)) {
1505 this->selected_order = -1;
1507 }
1508 return true;
1509 }
1510
1517 bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
1518 {
1519 bool share_order = _ctrl_pressed || this->goto_type == OPOS_SHARE;
1520 if (this->vehicle->GetNumOrders() != 0 && !share_order) return false;
1521
1522 if (!share_order) {
1523 /* If CTRL is not pressed: If all the vehicles in this list have the same orders, then copy orders */
1524 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1525 return VehiclesHaveSameOrderList(v1, v2);
1526 })) {
1527 OnVehicleSelect(*begin);
1528 } else {
1529 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST), WL_INFO);
1530 }
1531 } else {
1532 /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */
1533 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
1534 return v1->FirstShared() == v2->FirstShared();
1535 })) {
1536 OnVehicleSelect(*begin);
1537 } else {
1538 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_LIST), GetEncodedString(STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST), WL_INFO);
1539 }
1540 }
1541
1542 return true;
1543 }
1544
1545 void OnPlaceObjectAbort() override
1546 {
1547 this->goto_type = OPOS_NONE;
1549
1550 /* Remove drag highlighting if it exists. */
1551 if (this->order_over != INVALID_VEH_ORDER_ID) {
1552 this->order_over = INVALID_VEH_ORDER_ID;
1554 }
1555 }
1556
1557 void OnMouseDrag(Point pt, WidgetID widget) override
1558 {
1559 if (this->selected_order != -1 && widget == WID_O_ORDER_LIST) {
1560 /* An order is dragged.. */
1561 VehicleOrderID from_order = this->OrderGetSel();
1562 VehicleOrderID to_order = this->GetOrderFromPt(pt.y);
1563 uint num_orders = this->vehicle->GetNumOrders();
1564
1565 if (from_order != INVALID_VEH_ORDER_ID && from_order <= num_orders) {
1566 if (to_order != INVALID_VEH_ORDER_ID && to_order <= num_orders) { // ..over an existing order.
1567 this->order_over = to_order;
1568 this->SetWidgetDirty(widget);
1569 } else if (from_order != to_order && this->order_over != INVALID_VEH_ORDER_ID) { // ..outside of the order list.
1570 this->order_over = INVALID_VEH_ORDER_ID;
1571 this->SetWidgetDirty(widget);
1572 }
1573 }
1574 }
1575 }
1576
1577 void OnResize() override
1578 {
1579 /* Update the scroll bar */
1580 this->vscroll->SetCapacityFromWidget(this, WID_O_ORDER_LIST, WidgetDimensions::scaled.framerect.Vertical());
1581 }
1582
1583 static inline HotkeyList hotkeys{"order", {
1584 Hotkey('D', "skip", OHK_SKIP),
1585 Hotkey('F', "delete", OHK_DELETE),
1586 Hotkey('G', "goto", OHK_GOTO),
1587 Hotkey('H', "nonstop", OHK_NONSTOP),
1588 Hotkey('J', "fullload", OHK_FULLLOAD),
1589 Hotkey('K', "unload", OHK_UNLOAD),
1590 Hotkey(0, "nearest_depot", OHK_NEAREST_DEPOT),
1591 Hotkey(0, "always_service", OHK_ALWAYS_SERVICE),
1592 Hotkey(0, "transfer", OHK_TRANSFER),
1593 Hotkey(0, "no_unload", OHK_NO_UNLOAD),
1594 Hotkey(0, "no_load", OHK_NO_LOAD),
1595 }};
1596};
1597
1601 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1602 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION),
1603 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1604 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1605 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1606 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1607 EndContainer(),
1609 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(),
1611 EndContainer(),
1612
1613 /* First button row. */
1617 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_NON_STOP), SetMinimalSize(93, 12), SetFill(1, 0),
1618 SetStringTip(STR_ORDER_NON_STOP, STR_ORDER_TOOLTIP_NON_STOP), SetResize(1, 0),
1619 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_LEFT),
1620 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_FULL_LOAD), SetMinimalSize(93, 12), SetFill(1, 0),
1621 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1622 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_REFIT), SetMinimalSize(93, 12), SetFill(1, 0),
1623 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1624 EndContainer(),
1626 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_UNLOAD), SetMinimalSize(93, 12), SetFill(1, 0),
1627 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1629 SetStringTip(STR_JUST_STRING), SetResize(1, 0),
1630 EndContainer(),
1631 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_RIGHT),
1632 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(93, 12), SetFill(1, 0), SetResize(1, 0), EndContainer(),
1634 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1635 EndContainer(),
1636 EndContainer(),
1638 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
1639 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1640 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
1641 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1642 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
1643 SetToolTip(STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1644 EndContainer(),
1645 EndContainer(),
1646 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),
1647 EndContainer(),
1648
1649 /* Second button row. */
1652 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
1653 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1655 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
1656 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1657 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
1658 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1659 EndContainer(),
1660 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
1661 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1662 EndContainer(),
1663 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1664 EndContainer(),
1665};
1666
1667static WindowDesc _orders_train_desc(
1668 WDP_AUTO, "view_vehicle_orders_train", 384, 100,
1672 &OrdersWindow::hotkeys
1673);
1674
1678 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1679 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1680 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1681 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1682 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1683 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1684 EndContainer(),
1686 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(),
1688 EndContainer(),
1689
1690 /* First button row. */
1692 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_O_SEL_TOP_ROW),
1693 /* Load + unload + refit buttons. */
1695 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_FULL_LOAD), SetMinimalSize(124, 12), SetFill(1, 0),
1696 SetStringTip(STR_ORDER_TOGGLE_FULL_LOAD, STR_ORDER_TOOLTIP_FULL_LOAD), SetResize(1, 0),
1697 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_UNLOAD), SetMinimalSize(124, 12), SetFill(1, 0),
1698 SetStringTip(STR_ORDER_TOGGLE_UNLOAD, STR_ORDER_TOOLTIP_UNLOAD), SetResize(1, 0),
1700 SetStringTip(STR_ORDER_REFIT_AUTO, STR_ORDER_REFIT_AUTO_TOOLTIP), SetResize(1, 0),
1701 EndContainer(),
1702 /* Refit + service buttons. */
1704 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_REFIT), SetMinimalSize(186, 12), SetFill(1, 0),
1705 SetStringTip(STR_ORDER_REFIT, STR_ORDER_REFIT_TOOLTIP), SetResize(1, 0),
1707 SetResize(1, 0),
1708 EndContainer(),
1709
1710 /* Buttons for setting a condition. */
1712 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_VARIABLE), SetMinimalSize(124, 12), SetFill(1, 0),
1713 SetToolTip(STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP), SetResize(1, 0),
1714 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_COMPARATOR), SetMinimalSize(124, 12), SetFill(1, 0),
1715 SetToolTip(STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP), SetResize(1, 0),
1716 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_COND_VALUE), SetMinimalSize(124, 12), SetFill(1, 0),
1717 SetStringTip(STR_JUST_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
1718 EndContainer(),
1719 EndContainer(),
1720
1721 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),
1722 EndContainer(),
1723
1724 /* Second button row. */
1726 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_SKIP), SetMinimalSize(124, 12), SetFill(1, 0),
1727 SetStringTip(STR_ORDERS_SKIP_BUTTON, STR_ORDERS_SKIP_TOOLTIP), SetResize(1, 0),
1729 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_DELETE), SetMinimalSize(124, 12), SetFill(1, 0),
1730 SetStringTip(STR_ORDERS_DELETE_BUTTON, STR_ORDERS_DELETE_TOOLTIP), SetResize(1, 0),
1731 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_STOP_SHARING), SetMinimalSize(124, 12), SetFill(1, 0),
1732 SetStringTip(STR_ORDERS_STOP_SHARING_BUTTON, STR_ORDERS_STOP_SHARING_TOOLTIP), SetResize(1, 0),
1733 EndContainer(),
1734 NWidget(NWID_BUTTON_DROPDOWN, COLOUR_GREY, WID_O_GOTO), SetMinimalSize(124, 12), SetFill(1, 0),
1735 SetStringTip(STR_ORDERS_GO_TO_BUTTON, STR_ORDERS_GO_TO_TOOLTIP), SetResize(1, 0),
1736 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1737 EndContainer(),
1738};
1739
1740static WindowDesc _orders_desc(
1741 WDP_AUTO, "view_vehicle_orders", 384, 100,
1745 &OrdersWindow::hotkeys
1746);
1747
1751 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1752 NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1753 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetStringTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
1754 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1755 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1756 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1757 EndContainer(),
1759 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(),
1762 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1763 EndContainer(),
1764 EndContainer(),
1765};
1766
1767static WindowDesc _other_orders_desc(
1768 WDP_AUTO, "view_vehicle_orders_competitor", 384, 86,
1772 &OrdersWindow::hotkeys
1773);
1774
1775void ShowOrdersWindow(const Vehicle *v)
1776{
1779 if (BringWindowToFrontById(WC_VEHICLE_ORDERS, v->index) != nullptr) return;
1780
1781 /* Using a different WindowDescs for _local_company causes problems.
1782 * Due to this we have to close order windows in ChangeWindowOwner/CloseCompanyWindows,
1783 * because we cannot change switch the WindowDescs and keeping the old WindowDesc results
1784 * in crashed due to missing widges.
1785 * TODO Rewrite the order GUI to not use different WindowDescs.
1786 */
1787 if (v->owner != _local_company) {
1788 new OrdersWindow(_other_orders_desc, v);
1789 } else {
1790 new OrdersWindow(v->IsGroundVehicle() ? _orders_train_desc : _orders_desc, v);
1791 }
1792}
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:1138
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:1410
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:2449
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:2523
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:29
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:444
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:407
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:1296
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:923
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:890
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:989
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:245
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:379
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:389
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:296
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:320
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:945
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:66
Basic functions/variables used all over the place.
uint GetOrderDistance(const Order *prev, const Order *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:954
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:46
static constexpr NWidgetPart _nested_orders_widgets[]
Nested widget definition for "your" orders (non-train).
void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable, int left, int middle, int right)
Draws an order in order or timetable GUI.
uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
Convert the given display speed to the (internal) speed.
Definition strings.cpp:967
OrderConditionVariable
Variables (of a vehicle) to 'cause' skipping on.
Definition order_type.h:129
@ OCV_AGE
Skip based on the age.
Definition order_type.h:133
@ OCV_UNCONDITIONALLY
Always skip.
Definition order_type.h:135
@ OCV_MAX_SPEED
Skip based on the maximum speed.
Definition order_type.h:132
@ OCV_LOAD_PERCENTAGE
Skip based on the amount of load.
Definition order_type.h:130
@ OCV_REQUIRES_SERVICE
Skip when the vehicle requires service.
Definition order_type.h:134
@ OCV_RELIABILITY
Skip based on the reliability.
Definition order_type.h:131
@ OCV_REMAINING_LIFETIME
Skip based on the remaining lifetime.
Definition order_type.h:136
@ OCV_MAX_RELIABILITY
Skip based on the maximum reliability.
Definition order_type.h:137
OrderStopLocation
Where to stop the trains.
Definition order_type.h:99
@ OSL_PLATFORM_FAR_END
Stop at the far end of the platform.
Definition order_type.h:102
@ 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
OrderUnloadFlags
Flags related to the unloading order.
Definition order_type.h:68
@ OUFB_TRANSFER
Transfer all cargo onto the platform.
Definition order_type.h:71
@ OUFB_NO_UNLOAD
Totally no unloading will be done.
Definition order_type.h:72
@ OUF_UNLOAD_IF_POSSIBLE
Unload all cargo that the station accepts.
Definition order_type.h:69
@ OUFB_UNLOAD
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:70
@ DA_SERVICE
Service only if needed.
Definition order_type.h:178
@ DA_STOP
Go to the depot and stop there.
Definition order_type.h:179
@ DA_ALWAYS_GO
Always go to the depot.
Definition order_type.h:177
@ DA_UNBUNCH
Go to the depot and unbunch.
Definition order_type.h:180
@ ODTFB_PART_OF_ORDERS
This depot order is because of a regular order.
Definition order_type.h:112
@ ODTFB_SERVICE
This depot order is because of the servicing limit.
Definition order_type.h:111
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:122
@ ODATFB_NEAREST_DEPOT
Send the vehicle to the nearest depot.
Definition order_type.h:121
@ ODATFB_HALT
Service the vehicle and then halt it.
Definition order_type.h:120
OrderLoadFlags
Flags related to the loading order.
Definition order_type.h:78
@ OLFB_NO_LOAD
Do not load anything.
Definition order_type.h:82
@ OLF_LOAD_IF_POSSIBLE
Load as long as there is cargo that fits in the train.
Definition order_type.h:79
@ OLF_FULL_LOAD_ANY
Full load a single cargo of the consist.
Definition order_type.h:81
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition order_type.h:40
OrderConditionComparator
Comparator for the skip reasoning.
Definition order_type.h:144
@ OCC_IS_TRUE
Skip if the variable is true.
Definition order_type.h:151
@ OCC_IS_FALSE
Skip if the variable is false.
Definition order_type.h:152
@ ONSF_NO_STOP_AT_ANY_STATION
The vehicle will not stop at any stations it passes including the destination.
Definition order_type.h:92
@ ONSF_NO_STOP_AT_DESTINATION_STATION
The vehicle will stop at any station it passes except the destination.
Definition order_type.h:91
@ ONSF_STOP_EVERYWHERE
The vehicle will stop at any station it passes and the destination.
Definition order_type.h:89
@ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS
The vehicle will not stop at any stations it passes except the destination.
Definition order_type.h:90
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:387
Road vehicle states.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:58
static const CursorID ANIMCURSOR_PICKSTATION
716 - 718 - goto-order icon
Definition sprites.h:1515
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition sprites.h:1394
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.
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:246
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:424
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.
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:63
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:235
Station * neutral_station
Associated neutral station.
Definition industry.h:93
Partial widget specification to allow NWidgets to be written nested.
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:93
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition order_base.h:144
OrderConditionVariable GetConditionVariable() const
What variable do we have to compare?
Definition order_base.h:148
void SetLoadType(OrderLoadFlags load_type)
Set how the consist must be loaded.
Definition order_base.h:157
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:103
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:70
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition order_base.h:161
VehicleOrderID GetConditionSkipToOrder() const
Get the order to skip to.
Definition order_base.h:152
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition order_base.h:142
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:192
CargoType GetRefitCargo() const
Get the cargo to to refit to.
Definition order_base.h:131
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:76
void MakeGoToStation(StationID destination)
Makes this order a Go To Station order.
Definition order_cmd.cpp:75
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition order_base.h:136
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition order_base.h:163
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:183
Order * next
Pointer to next order. If nullptr, end of list.
Definition order_base.h:59
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:167
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition order_base.h:146
void Free()
'Free' the order
Definition order_cmd.cpp:63
bool IsAutoRefit() const
Is this order a auto-refit order.
Definition order_base.h:124
OrderUnloadFlags GetUnloadType() const
How must the consist be unloaded?
Definition order_base.h:138
OrderConditionComparator GetConditionComparator() const
What is the comparator to use?
Definition order_base.h:150
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:140
bool IsRefit() const
Is this order a refit order.
Definition order_base.h:117
uint16_t GetConditionValue() const
Get the value to base the skip on.
Definition order_base.h:154
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:90
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 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 OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
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:2482
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Order * GetFirstOrder() const
Get the first order of the vehicles order list.
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:2458
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:2470
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:1736
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
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:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1040
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:1726
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
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
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:3280
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3049
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:73
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ 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:56
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:60
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ 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:1143
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
@ 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:936
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
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: