OpenTTD Source: src/vehicle_gui.cpp Source File

OpenTTD Source 14.0-RC3

vehicle_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 "debug.h"
12 #include "company_func.h"
13 #include "gui.h"
14 #include "textbuf_gui.h"
15 #include "command_func.h"
16 #include "vehicle_gui_base.h"
17 #include "viewport_func.h"
18 #include "newgrf_text.h"
19 #include "newgrf_debug.h"
20 #include "roadveh.h"
21 #include "train.h"
22 #include "aircraft.h"
23 #include "depot_map.h"
24 #include "group_gui.h"
25 #include "strings_func.h"
26 #include "vehicle_func.h"
27 #include "autoreplace_gui.h"
28 #include "string_func.h"
29 #include "widgets/dropdown_func.h"
30 #include "timetable.h"
31 #include "articulated_vehicles.h"
32 #include "spritecache.h"
33 #include "core/geometry_func.hpp"
34 #include "core/container_func.hpp"
35 #include "company_base.h"
36 #include "engine_func.h"
37 #include "station_base.h"
38 #include "tilehighlight_func.h"
39 #include "zoom_func.h"
40 #include "depot_cmd.h"
41 #include "vehicle_cmd.h"
42 #include "order_cmd.h"
43 #include "roadveh_cmd.h"
44 #include "train_cmd.h"
45 #include "hotkeys.h"
46 #include "group_cmd.h"
47
48 #include "safeguards.h"
49
50
51 BaseVehicleListWindow::GroupBy _grouping[VLT_END][VEH_COMPANY_END];
52 Sorting _sorting[BaseVehicleListWindow::GB_END];
53
54 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleNumberSorter;
55 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleNameSorter;
56 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleAgeSorter;
57 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleProfitThisYearSorter;
58 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleProfitLastYearSorter;
59 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleCargoSorter;
60 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleReliabilitySorter;
61 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleMaxSpeedSorter;
62 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleModelSorter;
63 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleValueSorter;
64 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleLengthSorter;
65 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleTimeToLiveSorter;
66 static BaseVehicleListWindow::VehicleIndividualSortFunction VehicleTimetableDelaySorter;
67 static BaseVehicleListWindow::VehicleGroupSortFunction VehicleGroupLengthSorter;
68 static BaseVehicleListWindow::VehicleGroupSortFunction VehicleGroupTotalProfitThisYearSorter;
69 static BaseVehicleListWindow::VehicleGroupSortFunction VehicleGroupTotalProfitLastYearSorter;
70 static BaseVehicleListWindow::VehicleGroupSortFunction VehicleGroupAverageProfitThisYearSorter;
71 static BaseVehicleListWindow::VehicleGroupSortFunction VehicleGroupAverageProfitLastYearSorter;
72
74 template <BaseVehicleListWindow::VehicleIndividualSortFunction func>
75 static bool VehicleIndividualToGroupSorterWrapper(GUIVehicleGroup const &a, GUIVehicleGroup const &b)
76 {
77 return func(*(a.vehicles_begin), *(b.vehicles_begin));
78 }
79
80 BaseVehicleListWindow::VehicleGroupSortFunction * const BaseVehicleListWindow::vehicle_group_none_sorter_funcs[] = {
81 &VehicleIndividualToGroupSorterWrapper<VehicleNumberSorter>,
82 &VehicleIndividualToGroupSorterWrapper<VehicleNameSorter>,
83 &VehicleIndividualToGroupSorterWrapper<VehicleAgeSorter>,
84 &VehicleIndividualToGroupSorterWrapper<VehicleProfitThisYearSorter>,
85 &VehicleIndividualToGroupSorterWrapper<VehicleProfitLastYearSorter>,
86 &VehicleIndividualToGroupSorterWrapper<VehicleCargoSorter>,
87 &VehicleIndividualToGroupSorterWrapper<VehicleReliabilitySorter>,
88 &VehicleIndividualToGroupSorterWrapper<VehicleMaxSpeedSorter>,
89 &VehicleIndividualToGroupSorterWrapper<VehicleModelSorter>,
90 &VehicleIndividualToGroupSorterWrapper<VehicleValueSorter>,
91 &VehicleIndividualToGroupSorterWrapper<VehicleLengthSorter>,
92 &VehicleIndividualToGroupSorterWrapper<VehicleTimeToLiveSorter>,
93 &VehicleIndividualToGroupSorterWrapper<VehicleTimetableDelaySorter>,
94 };
95
96 const StringID BaseVehicleListWindow::vehicle_group_none_sorter_names_calendar[] = {
97 STR_SORT_BY_NUMBER,
98 STR_SORT_BY_NAME,
99 STR_SORT_BY_AGE,
100 STR_SORT_BY_PROFIT_THIS_YEAR,
101 STR_SORT_BY_PROFIT_LAST_YEAR,
102 STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE,
103 STR_SORT_BY_RELIABILITY,
104 STR_SORT_BY_MAX_SPEED,
105 STR_SORT_BY_MODEL,
106 STR_SORT_BY_VALUE,
107 STR_SORT_BY_LENGTH,
108 STR_SORT_BY_LIFE_TIME,
109 STR_SORT_BY_TIMETABLE_DELAY,
110 INVALID_STRING_ID
111 };
112
113 const StringID BaseVehicleListWindow::vehicle_group_none_sorter_names_wallclock[] = {
114 STR_SORT_BY_NUMBER,
115 STR_SORT_BY_NAME,
116 STR_SORT_BY_AGE,
117 STR_SORT_BY_PROFIT_THIS_PERIOD,
118 STR_SORT_BY_PROFIT_LAST_PERIOD,
119 STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE,
120 STR_SORT_BY_RELIABILITY,
121 STR_SORT_BY_MAX_SPEED,
122 STR_SORT_BY_MODEL,
123 STR_SORT_BY_VALUE,
124 STR_SORT_BY_LENGTH,
125 STR_SORT_BY_LIFE_TIME,
126 STR_SORT_BY_TIMETABLE_DELAY,
127 INVALID_STRING_ID
128 };
129
130 BaseVehicleListWindow::VehicleGroupSortFunction * const BaseVehicleListWindow::vehicle_group_shared_orders_sorter_funcs[] = {
131 &VehicleGroupLengthSorter,
132 &VehicleGroupTotalProfitThisYearSorter,
133 &VehicleGroupTotalProfitLastYearSorter,
134 &VehicleGroupAverageProfitThisYearSorter,
135 &VehicleGroupAverageProfitLastYearSorter,
136 };
137
138 const StringID BaseVehicleListWindow::vehicle_group_shared_orders_sorter_names_calendar[] = {
139 STR_SORT_BY_NUM_VEHICLES,
140 STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR,
141 STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR,
142 STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR,
143 STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR,
144 INVALID_STRING_ID
145 };
146
147 const StringID BaseVehicleListWindow::vehicle_group_shared_orders_sorter_names_wallclock[] = {
148 STR_SORT_BY_NUM_VEHICLES,
149 STR_SORT_BY_TOTAL_PROFIT_THIS_PERIOD,
150 STR_SORT_BY_TOTAL_PROFIT_LAST_PERIOD,
151 STR_SORT_BY_AVERAGE_PROFIT_THIS_PERIOD,
152 STR_SORT_BY_AVERAGE_PROFIT_LAST_PERIOD,
153 INVALID_STRING_ID
154 };
155
156 const StringID BaseVehicleListWindow::vehicle_group_by_names[] = {
157 STR_GROUP_BY_NONE,
158 STR_GROUP_BY_SHARED_ORDERS,
159 INVALID_STRING_ID
160 };
161
162 const StringID BaseVehicleListWindow::vehicle_depot_name[] = {
163 STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT,
164 STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT,
165 STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT,
166 STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR
167 };
168
169 BaseVehicleListWindow::BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(VehicleListIdentifier::UnPack(wno))
170 {
171 this->vehicle_sel = INVALID_VEHICLE;
172 this->grouping = _grouping[vli.type][vli.vtype];
173 this->UpdateSortingFromGrouping();
174 }
175
176 const StringID *BaseVehicleListWindow::GetVehicleSorterNames()
177 {
178 switch (this->grouping) {
179 case GB_NONE:
180 return TimerGameEconomy::UsingWallclockUnits() ? vehicle_group_none_sorter_names_wallclock : vehicle_group_none_sorter_names_calendar;
181 case GB_SHARED_ORDERS:
182 return TimerGameEconomy::UsingWallclockUnits() ? vehicle_group_shared_orders_sorter_names_wallclock : vehicle_group_shared_orders_sorter_names_calendar;
183 default:
184 NOT_REACHED();
185 }
186 }
187
193 uint CountDigitsForAllocatingSpace(uint number)
194 {
195 if (number >= 10000) return 5;
196 if (number >= 1000) return 4;
197 if (number >= 100) return 3;
198
199 /*
200 * When the smallest unit number is less than 10, it is
201 * quite likely that it will expand to become more than
202 * 10 quite soon.
203 */
204 return 2;
205 }
206
212 uint GetUnitNumberDigits(VehicleList &vehicles)
213 {
214 uint unitnumber = 0;
215 for (const Vehicle *v : vehicles) {
216 unitnumber = std::max<uint>(unitnumber, v->unitnumber);
217 }
218
219 return CountDigitsForAllocatingSpace(unitnumber);
220 }
221
222 void BaseVehicleListWindow::BuildVehicleList()
223 {
224 if (!this->vehgroups.NeedRebuild()) return;
225
226 Debug(misc, 3, "Building vehicle list type {} for company {} given index {}", this->vli.type, this->vli.company, this->vli.index);
227
228 this->vehgroups.clear();
229
230 GenerateVehicleSortList(&this->vehicles, this->vli);
231
232 CargoTypes used = 0;
233 for (const Vehicle *v : this->vehicles) {
234 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
235 if (u->cargo_cap > 0) SetBit(used, u->cargo_type);
236 }
237 }
238 this->used_cargoes = used;
239
240 if (this->grouping == GB_NONE) {
241 uint max_unitnumber = 0;
242 for (auto it = this->vehicles.begin(); it != this->vehicles.end(); ++it) {
243 this->vehgroups.emplace_back(it, it + 1);
244
245 max_unitnumber = std::max<uint>(max_unitnumber, (*it)->unitnumber);
246 }
247 this->unitnumber_digits = CountDigitsForAllocatingSpace(max_unitnumber);
248 } else {
249 /* Sort by the primary vehicle; we just want all vehicles that share the same orders to form a contiguous range. */
250 std::stable_sort(this->vehicles.begin(), this->vehicles.end(), [](const Vehicle * const &u, const Vehicle * const &v) {
251 return u->FirstShared() < v->FirstShared();
252 });
253
254 uint max_num_vehicles = 0;
255
256 VehicleList::const_iterator begin = this->vehicles.begin();
257 while (begin != this->vehicles.end()) {
258 VehicleList::const_iterator end = std::find_if_not(begin, this->vehicles.cend(), [first_shared = (*begin)->FirstShared()](const Vehicle * const &v) {
259 return v->FirstShared() == first_shared;
260 });
261
262 this->vehgroups.emplace_back(begin, end);
263
264 max_num_vehicles = std::max<uint>(max_num_vehicles, static_cast<uint>(end - begin));
265
266 begin = end;
267 }
268
269 this->unitnumber_digits = CountDigitsForAllocatingSpace(max_num_vehicles);
270 }
271 this->FilterVehicleList();
272
273 this->vehgroups.RebuildDone();
274 this->vscroll->SetCount(this->vehgroups.size());
275 }
276
284 static bool CargoFilterSingle(const Vehicle *v, const CargoID cid)
285 {
286 if (cid == CargoFilterCriteria::CF_ANY) {
287 return true;
288 } else if (cid == CargoFilterCriteria::CF_NONE) {
289 for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
290 if (w->cargo_cap > 0) {
291 return false;
292 }
293 }
294 return true;
295 } else if (cid == CargoFilterCriteria::CF_FREIGHT) {
296 bool have_capacity = false;
297 for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
298 if (w->cargo_cap > 0) {
299 if (IsCargoInClass(w->cargo_type, CC_PASSENGERS)) {
300 return false;
301 } else {
302 have_capacity = true;
303 }
304 }
305 }
306 return have_capacity;
307 } else {
308 for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
309 if (w->cargo_cap > 0 && w->cargo_type == cid) {
310 return true;
311 }
312 }
313 return false;
314 }
315 }
316
324 static bool CargoFilter(const GUIVehicleGroup *vehgroup, const CargoID cid)
325 {
326 auto it = vehgroup->vehicles_begin;
327
328 /* Check if any vehicle in the group matches; if so, the whole group does. */
329 for (; it != vehgroup->vehicles_end; it++) {
330 if (CargoFilterSingle(*it, cid)) return true;
331 }
332
333 return false;
334 }
335
336 static GUIVehicleGroupList::FilterFunction * const _filter_funcs[] = {
337 &CargoFilter,
338 };
339
344 void BaseVehicleListWindow::SetCargoFilter(CargoID cid)
345 {
346 if (this->cargo_filter_criteria != cid) {
347 this->cargo_filter_criteria = cid;
348 /* Deactivate filter if criteria is 'Show All', activate it otherwise. */
349 this->vehgroups.SetFilterState(this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY);
350 this->vehgroups.SetFilterType(0);
351 this->vehgroups.ForceRebuild();
352 }
353 }
354
358 void BaseVehicleListWindow::SetCargoFilterArray()
359 {
360 this->cargo_filter_criteria = CargoFilterCriteria::CF_ANY;
361 this->vehgroups.SetFilterFuncs(_filter_funcs);
362 this->vehgroups.SetFilterState(this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY);
363 }
364
368 void BaseVehicleListWindow::FilterVehicleList()
369 {
370 this->vehgroups.Filter(this->cargo_filter_criteria);
371 if (this->vehicles.empty()) {
372 /* No vehicle passed through the filter, invalidate the previously selected vehicle */
373 this->vehicle_sel = INVALID_VEHICLE;
374 } else if (this->vehicle_sel != INVALID_VEHICLE && std::find(this->vehicles.begin(), this->vehicles.end(), Vehicle::Get(this->vehicle_sel)) == this->vehicles.end()) { // previously selected engine didn't pass the filter, remove selection
375 this->vehicle_sel = INVALID_VEHICLE;
376 }
377 }
378
386 Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bool show_group, bool show_create)
387 {
388 Dimension d = {0, 0};
389
390 if (show_autoreplace) d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_REPLACE_VEHICLES));
391 d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_SEND_FOR_SERVICING));
392 d = maxdim(d, GetStringBoundingBox(this->vehicle_depot_name[this->vli.vtype]));
393
394 if (show_group) {
395 d = maxdim(d, GetStringBoundingBox(STR_GROUP_ADD_SHARED_VEHICLE));
396 d = maxdim(d, GetStringBoundingBox(STR_GROUP_REMOVE_ALL_VEHICLES));
397 } else if (show_create) {
398 d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_CREATE_GROUP));
399 }
400
401 return d;
402 }
403
404 void BaseVehicleListWindow::OnInit()
405 {
406 this->order_arrow_width = GetStringBoundingBox(STR_JUST_RIGHT_ARROW, FS_SMALL).width;
407 this->SetCargoFilterArray();
408 }
409
410 StringID BaseVehicleListWindow::GetCargoFilterLabel(CargoID cid) const
411 {
412 switch (cid) {
413 case CargoFilterCriteria::CF_ANY: return STR_CARGO_TYPE_FILTER_ALL;
414 case CargoFilterCriteria::CF_FREIGHT: return STR_CARGO_TYPE_FILTER_FREIGHT;
415 case CargoFilterCriteria::CF_NONE: return STR_CARGO_TYPE_FILTER_NONE;
416 default: return CargoSpec::Get(cid)->name;
417 }
418 }
419
425 DropDownList BaseVehicleListWindow::BuildCargoDropDownList(bool full) const
426 {
427 DropDownList list;
428
429 /* Add item for disabling filtering. */
430 list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY, false));
431 /* Add item for freight (i.e. vehicles with cargo capacity and with no passenger capacity). */
432 list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_FREIGHT), CargoFilterCriteria::CF_FREIGHT, false));
433 /* Add item for vehicles not carrying anything, e.g. train engines. */
434 list.push_back(std::make_unique<DropDownListStringItem>(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE, false));
435
436 /* Add cargos */
437 Dimension d = GetLargestCargoIconSize();
438 for (const CargoSpec *cs : _sorted_cargo_specs) {
439 if (!full && !HasBit(this->used_cargoes, cs->Index())) continue;
440 list.push_back(std::make_unique<DropDownListIconItem>(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index(), false, !HasBit(this->used_cargoes, cs->Index())));
441 }
442
443 return list;
444 }
445
453 DropDownList BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplace, bool show_group, bool show_create)
454 {
455 DropDownList list;
456
457 if (show_autoreplace) list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false));
458 list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false));
459 list.push_back(std::make_unique<DropDownListStringItem>(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false));
460
461 if (show_group) {
462 list.push_back(std::make_unique<DropDownListStringItem>(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false));
463 list.push_back(std::make_unique<DropDownListStringItem>(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false));
464 } else if (show_create) {
465 list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_CREATE_GROUP, ADI_CREATE_GROUP, false));
466 }
467
468 return list;
469 }
470
471 /* cached values for VehicleNameSorter to spare many GetString() calls */
472 static const Vehicle *_last_vehicle[2] = { nullptr, nullptr };
473
474 void BaseVehicleListWindow::SortVehicleList()
475 {
476 if (this->vehgroups.Sort()) return;
477
478 /* invalidate cached values for name sorter - vehicle names could change */
479 _last_vehicle[0] = _last_vehicle[1] = nullptr;
480 }
481
482 void DepotSortList(VehicleList *list)
483 {
484 if (list->size() < 2) return;
485 std::sort(list->begin(), list->end(), &VehicleNumberSorter);
486 }
487
489 static void DrawVehicleProfitButton(TimerGameEconomy::Date age, Money display_profit_last_year, uint num_vehicles, int x, int y)
490 {
491 SpriteID spr;
492
493 /* draw profit-based coloured icons */
494 if (age <= VEHICLE_PROFIT_MIN_AGE) {
495 spr = SPR_PROFIT_NA;
496 } else if (display_profit_last_year < 0) {
497 spr = SPR_PROFIT_NEGATIVE;
498 } else if (display_profit_last_year < VEHICLE_PROFIT_THRESHOLD * num_vehicles) {
499 spr = SPR_PROFIT_SOME;
500 } else {
501 spr = SPR_PROFIT_LOT;
502 }
503 DrawSprite(spr, PAL_NONE, x, y);
504 }
505
507 static const uint MAX_REFIT_CYCLE = 256;
508
518 byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
519 {
520 v_from = v_from->GetFirstEnginePart();
521 v_for = v_for->GetFirstEnginePart();
522
523 /* Create a list of subtypes used by the various parts of v_for */
524 static std::vector<StringID> subtypes;
525 subtypes.clear();
526 for (; v_from != nullptr; v_from = v_from->HasArticulatedPart() ? v_from->GetNextArticulatedPart() : nullptr) {
527 const Engine *e_from = v_from->GetEngine();
528 if (!e_from->CanCarryCargo() || !HasBit(e_from->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
529 include(subtypes, GetCargoSubtypeText(v_from));
530 }
531
532 byte ret_refit_cyc = 0;
533 bool success = false;
534 if (!subtypes.empty()) {
535 /* Check whether any articulated part is refittable to 'dest_cargo_type' with a subtype listed in 'subtypes' */
536 for (Vehicle *v = v_for; v != nullptr; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr) {
537 const Engine *e = v->GetEngine();
538 if (!e->CanCarryCargo() || !HasBit(e->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
539 if (!HasBit(e->info.refit_mask, dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
540
541 CargoID old_cargo_type = v->cargo_type;
542 byte old_cargo_subtype = v->cargo_subtype;
543
544 /* Set the 'destination' cargo */
545 v->cargo_type = dest_cargo_type;
546
547 /* Cycle through the refits */
548 for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
549 v->cargo_subtype = refit_cyc;
550
551 /* Make sure we don't pick up anything cached. */
552 v->First()->InvalidateNewGRFCache();
553 v->InvalidateNewGRFCache();
554
555 StringID subtype = GetCargoSubtypeText(v);
556 if (subtype == STR_EMPTY) break;
557
558 if (std::find(subtypes.begin(), subtypes.end(), subtype) == subtypes.end()) continue;
559
560 /* We found something matching. */
561 ret_refit_cyc = refit_cyc;
562 success = true;
563 break;
564 }
565
566 /* Reset the vehicle's cargo type */
567 v->cargo_type = old_cargo_type;
568 v->cargo_subtype = old_cargo_subtype;
569
570 /* Make sure we don't taint the vehicle. */
571 v->First()->InvalidateNewGRFCache();
572 v->InvalidateNewGRFCache();
573
574 if (success) break;
575 }
576 }
577
578 return ret_refit_cyc;
579 }
580
582 struct RefitOption {
583 CargoID cargo;
584 byte subtype;
585 StringID string;
586
592 inline bool operator != (const RefitOption &other) const
593 {
594 return other.cargo != this->cargo || other.string != this->string;
595 }
596
602 inline bool operator == (const RefitOption &other) const
603 {
604 return other.cargo == this->cargo && other.string == this->string;
605 }
606 };
607
608 using RefitOptions = std::map<CargoID, std::vector<RefitOption>, CargoIDComparator>;
609
619 static void DrawVehicleRefitWindow(const RefitOptions &refits, const RefitOption *sel, uint pos, uint rows, uint delta, const Rect &r)
620 {
621 Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
622 uint current = 0;
623
624 bool rtl = _current_text_dir == TD_RTL;
625 uint iconwidth = std::max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width);
626 uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
627 int linecolour = _colour_gradient[COLOUR_ORANGE][4];
628
629 int iconleft = rtl ? ir.right - iconwidth : ir.left;
630 int iconcenter = rtl ? ir.right - iconwidth / 2 : ir.left + iconwidth / 2;
631 int iconinner = rtl ? ir.right - iconwidth : ir.left + iconwidth;
632
633 Rect tr = ir.Indent(iconwidth + WidgetDimensions::scaled.hsep_wide, rtl);
634
635 /* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
636 for (const auto &pair : refits) {
637 bool has_subtypes = pair.second.size() > 1;
638 for (const RefitOption &refit : pair.second) {
639 if (current >= pos + rows) break;
640
641 /* Hide subtypes if selected cargo type does not match */
642 if ((sel == nullptr || sel->cargo != refit.cargo) && refit.subtype != UINT8_MAX) continue;
643
644 /* Refit options with a position smaller than pos don't have to be drawn. */
645 if (current < pos) {
646 current++;
647 continue;
648 }
649
650 if (has_subtypes) {
651 if (refit.subtype != UINT8_MAX) {
652 /* Draw tree lines */
653 int ycenter = tr.top + GetCharacterHeight(FS_NORMAL) / 2;
654 GfxDrawLine(iconcenter, tr.top - WidgetDimensions::scaled.matrix.top, iconcenter, (&refit == &pair.second.back()) ? ycenter : tr.top - WidgetDimensions::scaled.matrix.top + delta - 1, linecolour);
655 GfxDrawLine(iconcenter, ycenter, iconinner, ycenter, linecolour);
656 } else {
657 /* Draw expand/collapse icon */
658 DrawSprite((sel != nullptr && sel->cargo == refit.cargo) ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, tr.top + (GetCharacterHeight(FS_NORMAL) - iconheight) / 2);
659 }
660 }
661
662 TextColour colour = (sel != nullptr && sel->cargo == refit.cargo && sel->subtype == refit.subtype) ? TC_WHITE : TC_BLACK;
663 /* Get the cargo name. */
664 SetDParam(0, CargoSpec::Get(refit.cargo)->name);
665 SetDParam(1, refit.string);
666 DrawString(tr, STR_JUST_STRING_STRING, colour);
667
668 tr.top += delta;
669 current++;
670 }
671 }
672 }
673
675 struct RefitWindow : public Window {
676 const RefitOption *selected_refit;
677 RefitOptions refit_list;
678 VehicleOrderID order;
679 uint information_width;
680 Scrollbar *vscroll;
681 Scrollbar *hscroll;
682 int vehicle_width;
683 int sprite_left;
684 int sprite_right;
685 uint vehicle_margin;
686 int click_x;
687 VehicleID selected_vehicle;
688 uint8_t num_vehicles;
689 bool auto_refit;
690
694 void BuildRefitList()
695 {
696 /* Store the currently selected RefitOption. */
697 std::optional<RefitOption> current_refit_option;
698 if (this->selected_refit != nullptr) current_refit_option = *(this->selected_refit);
699 this->selected_refit = nullptr;
700
701 this->refit_list.clear();
702 Vehicle *v = Vehicle::Get(this->window_number);
703
704 /* Check only the selected vehicles. */
705 VehicleSet vehicles_to_refit;
706 GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
707
708 do {
709 if (v->type == VEH_TRAIN && std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), v->index) == vehicles_to_refit.end()) continue;
710 const Engine *e = v->GetEngine();
711 CargoTypes cmask = e->info.refit_mask;
712 byte callback_mask = e->info.callback_mask;
713
714 /* Skip this engine if it does not carry anything */
715 if (!e->CanCarryCargo()) continue;
716 /* Skip this engine if we build the list for auto-refitting and engine doesn't allow it. */
717 if (this->auto_refit && !HasBit(e->info.misc_flags, EF_AUTO_REFIT)) continue;
718
719 /* Loop through all cargoes in the refit mask */
720 for (const auto &cs : _sorted_cargo_specs) {
721 CargoID cid = cs->Index();
722 /* Skip cargo type if it's not listed */
723 if (!HasBit(cmask, cid)) continue;
724
725 auto &list = this->refit_list[cid];
726 bool first_vehicle = list.empty();
727 if (first_vehicle) {
728 /* Keeping the current subtype is always an option. It also serves as the option in case of no subtypes */
729 list.push_back({cid, UINT8_MAX, STR_EMPTY});
730 }
731
732 /* Check the vehicle's callback mask for cargo suffixes.
733 * This is not supported for ordered refits, since subtypes only have a meaning
734 * for a specific vehicle at a specific point in time, which conflicts with shared orders,
735 * autoreplace, autorenew, clone, order restoration, ... */
736 if (this->order == INVALID_VEH_ORDER_ID && HasBit(callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
737 /* Make a note of the original cargo type. It has to be
738 * changed to test the cargo & subtype... */
739 CargoID temp_cargo = v->cargo_type;
740 byte temp_subtype = v->cargo_subtype;
741
742 v->cargo_type = cid;
743
744 for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
745 v->cargo_subtype = refit_cyc;
746
747 /* Make sure we don't pick up anything cached. */
748 v->First()->InvalidateNewGRFCache();
749 v->InvalidateNewGRFCache();
750
751 StringID subtype = GetCargoSubtypeText(v);
752
753 if (first_vehicle) {
754 /* Append new subtype (don't add duplicates though) */
755 if (subtype == STR_EMPTY) break;
756
757 RefitOption option;
758 option.cargo = cid;
759 option.subtype = refit_cyc;
760 option.string = subtype;
761 include(list, option);
762 } else {
763 /* Intersect the subtypes of earlier vehicles with the subtypes of this vehicle */
764 if (subtype == STR_EMPTY) {
765 /* No more subtypes for this vehicle, delete all subtypes >= refit_cyc */
766 /* UINT8_MAX item is in front, other subtypes are sorted. So just truncate the list in the right spot */
767 for (uint i = 1; i < list.size(); i++) {
768 if (list[i].subtype >= refit_cyc) {
769 list.resize(i);
770 break;
771 }
772 }
773 break;
774 } else {
775 /* Check whether the subtype matches with the subtype of earlier vehicles. */
776 uint pos = 1;
777 while (pos < list.size() && list[pos].subtype != refit_cyc) pos++;
778 if (pos < list.size() && list[pos].string != subtype) {
779 /* String mismatch, remove item keeping the order */
780 list.erase(list.begin() + pos);
781 }
782 }
783 }
784 }
785
786 /* Reset the vehicle's cargo type */
787 v->cargo_type = temp_cargo;
788 v->cargo_subtype = temp_subtype;
789
790 /* And make sure we haven't tainted the cache */
791 v->First()->InvalidateNewGRFCache();
792 v->InvalidateNewGRFCache();
793 }
794 }
795 } while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
796
797 /* Restore the previously selected RefitOption. */
798 if (current_refit_option.has_value()) {
799 for (const auto &pair : this->refit_list) {
800 for (const auto &refit : pair.second) {
801 if (refit.cargo == current_refit_option->cargo && refit.subtype == current_refit_option->subtype) {
802 this->selected_refit = &refit;
803 break;
804 }
805 }
806 if (this->selected_refit != nullptr) break;
807 }
808 }
809
810 this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
811 }
812
816 void RefreshScrollbar()
817 {
818 size_t scroll_row = 0;
819 size_t rows = 0;
820 CargoID cargo = this->selected_refit == nullptr ? INVALID_CARGO : this->selected_refit->cargo;
821
822 for (const auto &pair : this->refit_list) {
823 if (pair.first == cargo) {
824 /* selected_refit points to an element in the vector so no need to search for it. */
825 scroll_row = rows + (this->selected_refit - pair.second.data());
826 rows += pair.second.size();
827 } else {
828 rows++; /* Unselected cargo type is collapsed into one row. */
829 }
830 }
831
832 this->vscroll->SetCount(rows);
833 this->vscroll->ScrollTowards(static_cast<int>(scroll_row));
834 }
835
840 void SetSelection(uint click_row)
841 {
842 uint row = 0;
843
844 for (const auto &pair : refit_list) {
845 for (const RefitOption &refit : pair.second) {
846 if (row == click_row) {
847 this->selected_refit = &refit;
848 return;
849 }
850 row++;
851 /* If this cargo type is not already selected then its subtypes are not visible, so skip the rest. */
852 if (this->selected_refit == nullptr || this->selected_refit->cargo != refit.cargo) break;
853 }
854 }
855
856 /* No selection made */
857 this->selected_refit = nullptr;
858 }
859
860 RefitWindow(WindowDesc *desc, const Vehicle *v, VehicleOrderID order, bool auto_refit) : Window(desc)
861 {
862 this->auto_refit = auto_refit;
863 this->order = order;
864 this->CreateNestedTree();
865
866 this->vscroll = this->GetScrollbar(WID_VR_SCROLLBAR);
867 this->hscroll = (v->IsGroundVehicle() ? this->GetScrollbar(WID_VR_HSCROLLBAR) : nullptr);
868 this->GetWidget<NWidgetCore>(WID_VR_SELECT_HEADER)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
869 this->GetWidget<NWidgetCore>(WID_VR_MATRIX)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
870 NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VR_REFIT);
871 nwi->widget_data = STR_REFIT_TRAIN_REFIT_BUTTON + v->type;
872 nwi->tool_tip = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
873 this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
874 this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
875
876 this->FinishInitNested(v->index);
877 this->owner = v->owner;
878
879 this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
880 }
881
882 void OnInit() override
883 {
884 /* (Re)build the refit list */
885 this->OnInvalidateData(VIWD_CONSIST_CHANGED);
886 }
887
888 void OnPaint() override
889 {
890 /* Determine amount of items for scroller. */
891 if (this->hscroll != nullptr) this->hscroll->SetCount(this->vehicle_width);
892
893 /* Calculate sprite position. */
894 NWidgetCore *vehicle_panel_display = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
895 int sprite_width = std::max(0, ((int)vehicle_panel_display->current_x - this->vehicle_width) / 2);
896 this->sprite_left = vehicle_panel_display->pos_x;
897 this->sprite_right = vehicle_panel_display->pos_x + vehicle_panel_display->current_x - 1;
898 if (_current_text_dir == TD_RTL) {
899 this->sprite_right -= sprite_width;
900 this->vehicle_margin = vehicle_panel_display->current_x - sprite_right;
901 } else {
902 this->sprite_left += sprite_width;
903 this->vehicle_margin = sprite_left;
904 }
905
906 this->DrawWidgets();
907 }
908
909 void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
910 {
911 switch (widget) {
912 case WID_VR_MATRIX:
913 resize->height = GetCharacterHeight(FS_NORMAL) + padding.height;
914 size->height = resize->height * 8;
915 break;
916
917 case WID_VR_VEHICLE_PANEL_DISPLAY:
918 size->height = ScaleGUITrad(GetVehicleHeight(Vehicle::Get(this->window_number)->type));
919 break;
920
921 case WID_VR_INFO:
922 size->width = this->information_width + padding.height;
923 break;
924 }
925 }
926
927 void SetStringParameters(WidgetID widget) const override
928 {
929 if (widget == WID_VR_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
930 }
931
938 StringID GetCapacityString(const RefitOption &option) const
939 {
940 assert(_current_company == _local_company);
941 auto [cost, refit_capacity, mail_capacity, cargo_capacities] = Command<CMD_REFIT_VEHICLE>::Do(DC_QUERY_COST, this->selected_vehicle, option.cargo, option.subtype, this->auto_refit, false, this->num_vehicles);
942
943 if (cost.Failed()) return INVALID_STRING_ID;
944
945 SetDParam(0, option.cargo);
946 SetDParam(1, refit_capacity);
947
948 Money money = cost.GetCost();
949 if (mail_capacity > 0) {
950 SetDParam(2, GetCargoIDByLabel(CT_MAIL));
951 SetDParam(3, mail_capacity);
952 if (this->order != INVALID_VEH_ORDER_ID) {
953 /* No predictable cost */
954 return STR_PURCHASE_INFO_AIRCRAFT_CAPACITY;
955 } else if (money <= 0) {
956 SetDParam(4, -money);
957 return STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT;
958 } else {
959 SetDParam(4, money);
960 return STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT;
961 }
962 } else {
963 if (this->order != INVALID_VEH_ORDER_ID) {
964 /* No predictable cost */
965 SetDParam(2, STR_EMPTY);
966 return STR_PURCHASE_INFO_CAPACITY;
967 } else if (money <= 0) {
968 SetDParam(2, -money);
969 return STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT;
970 } else {
971 SetDParam(2, money);
972 return STR_REFIT_NEW_CAPACITY_COST_OF_REFIT;
973 }
974 }
975 }
976
977 void DrawWidget(const Rect &r, WidgetID widget) const override
978 {
979 switch (widget) {
980 case WID_VR_VEHICLE_PANEL_DISPLAY: {
981 Vehicle *v = Vehicle::Get(this->window_number);
982 DrawVehicleImage(v, {this->sprite_left, r.top, this->sprite_right, r.bottom},
983 INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != nullptr ? this->hscroll->GetPosition() : 0);
984
985 /* Highlight selected vehicles. */
986 if (this->order != INVALID_VEH_ORDER_ID) break;
987 int x = 0;
988 switch (v->type) {
989 case VEH_TRAIN: {
990 VehicleSet vehicles_to_refit;
991 GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
992
993 int left = INT32_MIN;
994 int width = 0;
995
996 /* Determine top & bottom position of the highlight.*/
997 const int height = ScaleSpriteTrad(12);
998 const int highlight_top = CenterBounds(r.top, r.bottom, height);
999 const int highlight_bottom = highlight_top + height - 1;
1000
1001 for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
1002 /* Start checking. */
1003 const bool contained = std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), u->index) != vehicles_to_refit.end();
1004 if (contained && left == INT32_MIN) {
1005 left = x - this->hscroll->GetPosition() + r.left + this->vehicle_margin;
1006 width = 0;
1007 }
1008
1009 /* Draw a selection. */
1010 if ((!contained || u->Next() == nullptr) && left != INT32_MIN) {
1011 if (u->Next() == nullptr && contained) {
1012 int current_width = u->GetDisplayImageWidth();
1013 width += current_width;
1014 x += current_width;
1015 }
1016
1017 int right = Clamp(left + width, 0, r.right);
1018 left = std::max(0, left);
1019
1020 if (_current_text_dir == TD_RTL) {
1021 right = r.Width() - left;
1022 left = right - width;
1023 }
1024
1025 if (left != right) {
1026 Rect hr = {left, highlight_top, right, highlight_bottom};
1027 DrawFrameRect(hr.Expand(WidgetDimensions::scaled.bevel), COLOUR_WHITE, FR_BORDERONLY);
1028 }
1029
1030 left = INT32_MIN;
1031 }
1032
1033 int current_width = u->GetDisplayImageWidth();
1034 width += current_width;
1035 x += current_width;
1036 }
1037 break;
1038 }
1039
1040 default: break;
1041 }
1042 break;
1043 }
1044
1045 case WID_VR_MATRIX:
1046 DrawVehicleRefitWindow(this->refit_list, this->selected_refit, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->resize.step_height, r);
1047 break;
1048
1049 case WID_VR_INFO:
1050 if (this->selected_refit != nullptr) {
1051 StringID string = this->GetCapacityString(*this->selected_refit);
1052 if (string != INVALID_STRING_ID) {
1053 DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), string);
1054 }
1055 }
1056 break;
1057 }
1058 }
1059
1065 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1066 {
1067 switch (data) {
1068 case VIWD_AUTOREPLACE: // Autoreplace replaced the vehicle; selected_vehicle became invalid.
1069 case VIWD_CONSIST_CHANGED: { // The consist has changed; rebuild the entire list.
1070 /* Clear the selection. */
1071 Vehicle *v = Vehicle::Get(this->window_number);
1072 this->selected_vehicle = v->index;
1073 this->num_vehicles = UINT8_MAX;
1074 [[fallthrough]];
1075 }
1076
1077 case 2: { // The vehicle selection has changed; rebuild the entire list.
1078 if (!gui_scope) break;
1079 this->BuildRefitList();
1080
1081 /* The vehicle width has changed too. */
1082 this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
1083 uint max_width = 0;
1084
1085 /* Check the width of all cargo information strings. */
1086 for (const auto &list : this->refit_list) {
1087 for (const RefitOption &refit : list.second) {
1088 StringID string = this->GetCapacityString(refit);
1089 if (string != INVALID_STRING_ID) {
1090 Dimension dim = GetStringBoundingBox(string);
1091 max_width = std::max(dim.width, max_width);
1092 }
1093 }
1094 }
1095
1096 if (this->information_width < max_width) {
1097 this->information_width = max_width;
1098 this->ReInit();
1099 }
1100 [[fallthrough]];
1101 }
1102
1103 case 1: // A new cargo has been selected.
1104 if (!gui_scope) break;
1105 this->RefreshScrollbar();
1106 break;
1107 }
1108 }
1109
1110 int GetClickPosition(int click_x)
1111 {
1112 const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
1113 if (_current_text_dir == TD_RTL) click_x = matrix_widget->current_x - click_x;
1114 click_x -= this->vehicle_margin;
1115 if (this->hscroll != nullptr) click_x += this->hscroll->GetPosition();
1116
1117 return click_x;
1118 }
1119
1120 void SetSelectedVehicles(int drag_x)
1121 {
1122 drag_x = GetClickPosition(drag_x);
1123
1124 int left_x = std::min(this->click_x, drag_x);
1125 int right_x = std::max(this->click_x, drag_x);
1126 this->num_vehicles = 0;
1127
1128 Vehicle *v = Vehicle::Get(this->window_number);
1129 /* Find the vehicle part that was clicked. */
1130 switch (v->type) {
1131 case VEH_TRAIN: {
1132 /* Don't select anything if we are not clicking in the vehicle. */
1133 if (left_x >= 0) {
1134 const Train *u = Train::From(v);
1135 bool start_counting = false;
1136 for (; u != nullptr; u = u->Next()) {
1137 int current_width = u->GetDisplayImageWidth();
1138 left_x -= current_width;
1139 right_x -= current_width;
1140
1141 if (left_x < 0 && !start_counting) {
1142 this->selected_vehicle = u->index;
1143 start_counting = true;
1144
1145 /* Count the first vehicle, even if articulated part */
1146 this->num_vehicles++;
1147 } else if (start_counting && !u->IsArticulatedPart()) {
1148 /* Do not count articulated parts */
1149 this->num_vehicles++;
1150 }
1151
1152 if (right_x < 0) break;
1153 }
1154 }
1155
1156 /* If the selection is not correct, clear it. */
1157 if (this->num_vehicles != 0) {
1158 if (_ctrl_pressed) this->num_vehicles = UINT8_MAX;
1159 break;
1160 }
1161 [[fallthrough]];
1162 }
1163
1164 default:
1165 /* Clear the selection. */
1166 this->selected_vehicle = v->index;
1167 this->num_vehicles = UINT8_MAX;
1168 break;
1169 }
1170 }
1171
1172 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1173 {
1174 switch (widget) {
1175 case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
1176 if (this->order != INVALID_VEH_ORDER_ID) break;
1177 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
1178 this->click_x = GetClickPosition(pt.x - nwi->pos_x);
1179 this->SetSelectedVehicles(pt.x - nwi->pos_x);
1180 this->SetWidgetDirty(WID_VR_VEHICLE_PANEL_DISPLAY);
1181 if (!_ctrl_pressed) {
1182 SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
1183 } else {
1184 /* The vehicle selection has changed. */
1185 this->InvalidateData(2);
1186 }
1187 break;
1188 }
1189
1190 case WID_VR_MATRIX: { // listbox
1191 this->SetSelection(this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VR_MATRIX));
1192 this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
1193 this->InvalidateData(1);
1194
1195 if (click_count == 1) break;
1196 [[fallthrough]];
1197 }
1198
1199 case WID_VR_REFIT: // refit button
1200 if (this->selected_refit != nullptr) {
1201 const Vehicle *v = Vehicle::Get(this->window_number);
1202
1203 if (this->order == INVALID_VEH_ORDER_ID) {
1204 bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
1205 if (Command<CMD_REFIT_VEHICLE>::Post(GetCmdRefitVehMsg(v), v->tile, this->selected_vehicle, this->selected_refit->cargo, this->selected_refit->subtype, false, false, this->num_vehicles) && delete_window) this->Close();
1206 } else {
1207 if (Command<CMD_ORDER_REFIT>::Post(v->tile, v->index, this->order, this->selected_refit->cargo)) this->Close();
1208 }
1209 }
1210 break;
1211 }
1212 }
1213
1214 void OnMouseDrag(Point pt, WidgetID widget) override
1215 {
1216 switch (widget) {
1217 case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
1218 if (this->order != INVALID_VEH_ORDER_ID) break;
1219 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
1220 this->SetSelectedVehicles(pt.x - nwi->pos_x);
1221 this->SetWidgetDirty(WID_VR_VEHICLE_PANEL_DISPLAY);
1222 break;
1223 }
1224 }
1225 }
1226
1227 void OnDragDrop(Point pt, WidgetID widget) override
1228 {
1229 switch (widget) {
1230 case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
1231 if (this->order != INVALID_VEH_ORDER_ID) break;
1232 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
1233 this->SetSelectedVehicles(pt.x - nwi->pos_x);
1234 this->InvalidateData(2);
1235 break;
1236 }
1237 }
1238 }
1239
1240 void OnResize() override
1241 {
1242 this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
1243 this->vscroll->SetCapacityFromWidget(this, WID_VR_MATRIX);
1244 if (this->hscroll != nullptr) this->hscroll->SetCapacityFromWidget(this, WID_VR_VEHICLE_PANEL_DISPLAY);
1245 }
1246 };
1247
1248 static constexpr NWidgetPart _nested_vehicle_refit_widgets[] = {
1249 NWidget(NWID_HORIZONTAL),
1250 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1251 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VR_CAPTION), SetDataTip(STR_REFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1252 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1253 EndContainer(),
1254 /* Vehicle display + scrollbar. */
1255 NWidget(NWID_VERTICAL),
1256 NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_VEHICLE_PANEL_DISPLAY), SetMinimalSize(228, 14), SetResize(1, 0), SetScrollbar(WID_VR_HSCROLLBAR), EndContainer(),
1257 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VR_SHOW_HSCROLLBAR),
1258 NWidget(NWID_HSCROLLBAR, COLOUR_GREY, WID_VR_HSCROLLBAR),
1259 EndContainer(),
1260 EndContainer(),
1261 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VR_SELECT_HEADER), SetDataTip(STR_REFIT_TITLE, STR_NULL), SetResize(1, 0),
1262 /* Matrix + scrollbar. */
1263 NWidget(NWID_HORIZONTAL),
1264 NWidget(WWT_MATRIX, COLOUR_GREY, WID_VR_MATRIX), SetMinimalSize(228, 112), SetResize(1, 14), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VR_SCROLLBAR),
1265 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VR_SCROLLBAR),
1266 EndContainer(),
1267 NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_INFO), SetMinimalTextLines(2, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0), EndContainer(),
1268 NWidget(NWID_HORIZONTAL),
1269 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VR_REFIT), SetFill(1, 0), SetResize(1, 0),
1270 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1271 EndContainer(),
1272 };
1273
1274 static WindowDesc _vehicle_refit_desc(__FILE__, __LINE__,
1275 WDP_AUTO, "view_vehicle_refit", 240, 174,
1276 WC_VEHICLE_REFIT, WC_VEHICLE_VIEW,
1277 WDF_CONSTRUCTION,
1278 std::begin(_nested_vehicle_refit_widgets), std::end(_nested_vehicle_refit_widgets)
1279 );
1280
1288 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
1289 {
1290 CloseWindowById(WC_VEHICLE_REFIT, v->index);
1291 RefitWindow *w = new RefitWindow(&_vehicle_refit_desc, v, order, auto_refit);
1292 w->parent = parent;
1293 }
1294
1296 uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
1297 {
1298 /* List of cargo types of this engine */
1299 CargoTypes cmask = GetUnionOfArticulatedRefitMasks(engine, false);
1300 /* List of cargo types available in this climate */
1301 CargoTypes lmask = _cargo_mask;
1302
1303 /* Draw nothing if the engine is not refittable */
1304 if (HasAtMostOneBit(cmask)) return y;
1305
1306 if (cmask == lmask) {
1307 /* Engine can be refitted to all types in this climate */
1308 SetDParam(0, STR_PURCHASE_INFO_ALL_TYPES);
1309 } else {
1310 /* Check if we are able to refit to more cargo types and unable to. If
1311 * so, invert the cargo types to list those that we can't refit to. */
1312 if (CountBits(cmask ^ lmask) < CountBits(cmask) && CountBits(cmask ^ lmask) <= 7) {
1313 cmask ^= lmask;
1314 SetDParam(0, STR_PURCHASE_INFO_ALL_BUT);
1315 } else {
1316 SetDParam(0, STR_JUST_CARGO_LIST);
1317 }
1318 SetDParam(1, cmask);
1319 }
1320
1321 return DrawStringMultiLine(left, right, y, INT32_MAX, STR_PURCHASE_INFO_REFITTABLE_TO);
1322 }
1323
1325 StringID GetCargoSubtypeText(const Vehicle *v)
1326 {
1327 if (HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
1328 uint16_t cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v);
1329 if (cb != CALLBACK_FAILED) {
1330 if (cb > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb);
1331 if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED;
1332 }
1333 if (cb != CALLBACK_FAILED) {
1334 return GetGRFStringID(v->GetGRFID(), 0xD000 + cb);
1335 }
1336 }
1337 return STR_EMPTY;
1338 }
1339
1341 static bool VehicleGroupLengthSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
1342 {
1343 return a.NumVehicles() < b.NumVehicles();
1344 }
1345
1347 static bool VehicleGroupTotalProfitThisYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
1348 {
1349 return a.GetDisplayProfitThisYear() < b.GetDisplayProfitThisYear();
1350 }
1351
1353 static bool VehicleGroupTotalProfitLastYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
1354 {
1355 return a.GetDisplayProfitLastYear() < b.GetDisplayProfitLastYear();
1356 }
1357
1359 static bool VehicleGroupAverageProfitThisYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
1360 {
1361 return a.GetDisplayProfitThisYear() * static_cast<uint>(b.NumVehicles()) < b.GetDisplayProfitThisYear() * static_cast<uint>(a.NumVehicles());
1362 }
1363
1365 static bool VehicleGroupAverageProfitLastYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
1366 {
1367 return a.GetDisplayProfitLastYear() * static_cast<uint>(b.NumVehicles()) < b.GetDisplayProfitLastYear() * static_cast<uint>(a.NumVehicles());
1368 }
1369
1371 static bool VehicleNumberSorter(const Vehicle * const &a, const Vehicle * const &b)
1372 {
1373 return a->unitnumber < b->unitnumber;
1374 }
1375
1377 static bool VehicleNameSorter(const Vehicle * const &a, const Vehicle * const &b)
1378 {
1379 static std::string last_name[2] = { {}, {} };
1380
1381 if (a != _last_vehicle[0]) {
1382 _last_vehicle[0] = a;
1383 SetDParam(0, a->index);
1384 last_name[0] = GetString(STR_VEHICLE_NAME);
1385 }
1386
1387 if (b != _last_vehicle[1]) {
1388 _last_vehicle[1] = b;
1389 SetDParam(0, b->index);
1390 last_name[1] = GetString(STR_VEHICLE_NAME);
1391 }
1392
1393 int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).
1394 return (r != 0) ? r < 0: VehicleNumberSorter(a, b);
1395 }
1396
1398 static bool VehicleAgeSorter(const Vehicle * const &a, const Vehicle * const &b)
1399 {
1400 auto r = a->age - b->age;
1401 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1402 }
1403
1405 static bool VehicleProfitThisYearSorter(const Vehicle * const &a, const Vehicle * const &b)
1406 {
1407 int r = ClampTo<int32_t>(a->GetDisplayProfitThisYear() - b->GetDisplayProfitThisYear());
1408 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1409 }
1410
1412 static bool VehicleProfitLastYearSorter(const Vehicle * const &a, const Vehicle * const &b)
1413 {
1414 int r = ClampTo<int32_t>(a->GetDisplayProfitLastYear() - b->GetDisplayProfitLastYear());
1415 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1416 }
1417
1419 static bool VehicleCargoSorter(const Vehicle * const &a, const Vehicle * const &b)
1420 {
1421 const Vehicle *v;
1422 CargoArray diff{};
1423
1424 /* Append the cargo of the connected waggons */
1425 for (v = a; v != nullptr; v = v->Next()) diff[v->cargo_type] += v->cargo_cap;
1426 for (v = b; v != nullptr; v = v->Next()) diff[v->cargo_type] -= v->cargo_cap;
1427
1428 int r = 0;
1429 for (uint d : diff) {
1430 r = d;
1431 if (r != 0) break;
1432 }
1433
1434 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1435 }
1436
1438 static bool VehicleReliabilitySorter(const Vehicle * const &a, const Vehicle * const &b)
1439 {
1440 int r = a->reliability - b->reliability;
1441 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1442 }
1443
1445 static bool VehicleMaxSpeedSorter(const Vehicle * const &a, const Vehicle * const &b)
1446 {
1447 int r = a->vcache.cached_max_speed - b->vcache.cached_max_speed;
1448 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1449 }
1450
1452 static bool VehicleModelSorter(const Vehicle * const &a, const Vehicle * const &b)
1453 {
1454 int r = a->engine_type - b->engine_type;
1455 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1456 }
1457
1459 static bool VehicleValueSorter(const Vehicle * const &a, const Vehicle * const &b)
1460 {
1461 const Vehicle *u;
1462 Money diff = 0;
1463
1464 for (u = a; u != nullptr; u = u->Next()) diff += u->value;
1465 for (u = b; u != nullptr; u = u->Next()) diff -= u->value;
1466
1467 int r = ClampTo<int32_t>(diff);
1468 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1469 }
1470
1472 static bool VehicleLengthSorter(const Vehicle * const &a, const Vehicle * const &b)
1473 {
1474 int r = a->GetGroundVehicleCache()->cached_total_length - b->GetGroundVehicleCache()->cached_total_length;
1475 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1476 }
1477
1479 static bool VehicleTimeToLiveSorter(const Vehicle * const &a, const Vehicle * const &b)
1480 {
1481 int r = ClampTo<int32_t>((a->max_age - a->age) - (b->max_age - b->age));
1482 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1483 }
1484
1486 static bool VehicleTimetableDelaySorter(const Vehicle * const &a, const Vehicle * const &b)
1487 {
1488 int r = a->lateness_counter - b->lateness_counter;
1489 return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1490 }
1491
1492 void InitializeGUI()
1493 {
1494 MemSetT(&_grouping, 0);
1495 MemSetT(&_sorting, 0);
1496 }
1497
1504 static inline void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
1505 {
1506 Window *w = FindWindowById(window_class, from_index);
1507 if (w != nullptr) {
1508 /* Update window_number */
1509 w->window_number = to_index;
1510 if (w->viewport != nullptr) w->viewport->follow_vehicle = to_index;
1511
1512 /* Update vehicle drag data */
1513 if (_thd.window_class == window_class && _thd.window_number == (WindowNumber)from_index) {
1514 _thd.window_number = to_index;
1515 }
1516
1517 /* Notify the window. */
1518 w->InvalidateData(VIWD_AUTOREPLACE, false);
1519 }
1520 }
1521
1527 void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
1528 {
1529 ChangeVehicleWindow(WC_VEHICLE_VIEW, from_index, to_index);
1530 ChangeVehicleWindow(WC_VEHICLE_ORDERS, from_index, to_index);
1531 ChangeVehicleWindow(WC_VEHICLE_REFIT, from_index, to_index);
1532 ChangeVehicleWindow(WC_VEHICLE_DETAILS, from_index, to_index);
1533 ChangeVehicleWindow(WC_VEHICLE_TIMETABLE, from_index, to_index);
1534 }
1535
1536 static constexpr NWidgetPart _nested_vehicle_list[] = {
1537 NWidget(NWID_HORIZONTAL),
1538 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1539 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_CAPTION_SELECTION),
1540 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VL_CAPTION),
1541 NWidget(NWID_HORIZONTAL),
1542 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VL_CAPTION_SHARED_ORDERS),
1543 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_ORDER_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_GOTO_ORDER_VIEW, STR_GOTO_ORDER_VIEW_TOOLTIP),
1544 EndContainer(),
1545 EndContainer(),
1546 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1547 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1548 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1549 EndContainer(),
1550
1551 NWidget(NWID_HORIZONTAL),
1552 NWidget(NWID_VERTICAL),
1553 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VL_GROUP_ORDER), SetMinimalSize(0, 12), SetFill(1, 1), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER),
1554 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(0, 12), SetFill(1, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
1555 EndContainer(),
1556 NWidget(NWID_VERTICAL),
1557 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_GROUP_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
1558 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
1559 EndContainer(),
1560 NWidget(NWID_VERTICAL),
1561 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1562 NWidget(NWID_HORIZONTAL),
1563 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_FILTER_BY_CARGO_SEL),
1564 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_FILTER_BY_CARGO), SetMinimalSize(0, 12), SetFill(0, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA),
1565 EndContainer(),
1566 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1567 EndContainer(),
1568 EndContainer(),
1569 EndContainer(),
1570
1571 NWidget(NWID_HORIZONTAL),
1572 NWidget(WWT_MATRIX, COLOUR_GREY, WID_VL_LIST), SetMinimalSize(248, 0), SetFill(1, 0), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VL_SCROLLBAR),
1573 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VL_SCROLLBAR),
1574 EndContainer(),
1575
1576 NWidget(NWID_HORIZONTAL),
1577 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_HIDE_BUTTONS),
1578 NWidget(NWID_HORIZONTAL),
1579 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_AVAILABLE_VEHICLES), SetMinimalSize(106, 12), SetFill(0, 1),
1580 SetDataTip(STR_JUST_STRING, STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP),
1581 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), SetFill(1, 1), EndContainer(),
1582 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_MANAGE_VEHICLES_DROPDOWN), SetMinimalSize(118, 12), SetFill(0, 1),
1583 SetDataTip(STR_VEHICLE_LIST_MANAGE_LIST, STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP),
1584 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_STOP_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1585 SetDataTip(SPR_FLAG_VEH_STOPPED, STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP),
1586 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_START_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1587 SetDataTip(SPR_FLAG_VEH_RUNNING, STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP),
1588 EndContainer(),
1589 /* Widget to be shown for other companies hiding the previous 5 widgets. */
1590 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1591 EndContainer(),
1592 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1593 EndContainer(),
1594 };
1595
1596 static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, uint order_arrow_width, VehicleOrderID start)
1597 {
1598 const Order *order = v->GetOrder(start);
1599 if (order == nullptr) return;
1600
1601 bool rtl = _current_text_dir == TD_RTL;
1602 int l_offset = rtl ? 0 : order_arrow_width;
1603 int r_offset = rtl ? order_arrow_width : 0;
1604 int i = 0;
1605 VehicleOrderID oid = start;
1606
1607 do {
1608 if (oid == v->cur_real_order_index) DrawString(left, right, y, STR_JUST_RIGHT_ARROW, TC_BLACK, SA_LEFT, false, FS_SMALL);
1609
1610 if (order->IsType(OT_GOTO_STATION)) {
1611 SetDParam(0, order->GetDestination());
1612 DrawString(left + l_offset, right - r_offset, y, STR_STATION_NAME, TC_BLACK, SA_LEFT, false, FS_SMALL);
1613
1614 y += GetCharacterHeight(FS_SMALL);
1615 if (++i == 4) break;
1616 }
1617
1618 oid++;
1619 order = order->next;
1620 if (order == nullptr) {
1621 order = v->orders->GetFirstOrder();
1622 oid = 0;
1623 }
1624 } while (oid != start);
1625 }
1626
1628 static void DrawSmallOrderList(const Order *order, int left, int right, int y, uint order_arrow_width)
1629 {
1630 bool rtl = _current_text_dir == TD_RTL;
1631 int l_offset = rtl ? 0 : order_arrow_width;
1632 int r_offset = rtl ? order_arrow_width : 0;
1633 int i = 0;
1634 while (order != nullptr) {
1635 if (order->IsType(OT_GOTO_STATION)) {
1636 SetDParam(0, order->GetDestination());
1637 DrawString(left + l_offset, right - r_offset, y, STR_STATION_NAME, TC_BLACK, SA_LEFT, false, FS_SMALL);
1638
1639 y += GetCharacterHeight(FS_SMALL);
1640 if (++i == 4) break;
1641 }
1642 order = order->next;
1643 }
1644 }
1645
1653 void DrawVehicleImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
1654 {
1655 switch (v->type) {
1656 case VEH_TRAIN: DrawTrainImage(Train::From(v), r, selection, image_type, skip); break;
1657 case VEH_ROAD: DrawRoadVehImage(v, r, selection, image_type, skip); break;
1658 case VEH_SHIP: DrawShipImage(v, r, selection, image_type); break;
1659 case VEH_AIRCRAFT: DrawAircraftImage(v, r, selection, image_type); break;
1660 default: NOT_REACHED();
1661 }
1662 }
1663
1670 uint GetVehicleListHeight(VehicleType type, uint divisor)
1671 {
1672 /* Name + vehicle + profit */
1673 uint base = ScaleGUITrad(GetVehicleHeight(type)) + 2 * GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.matrix.Vertical();
1674 /* Drawing of the 4 small orders + profit*/
1675 if (type >= VEH_SHIP) base = std::max(base, 5U * GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.matrix.Vertical());
1676
1677 if (divisor == 1) return base;
1678
1679 /* Make sure the height is dividable by divisor */
1680 uint rem = base % divisor;
1681 return base + (rem == 0 ? 0 : divisor - rem);
1682 }
1683
1690 void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
1691 {
1692 Rect ir = r.WithHeight(line_height).Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
1693 bool rtl = _current_text_dir == TD_RTL;
1694
1695 Dimension profit = GetSpriteSize(SPR_PROFIT_LOT);
1696 int text_offset = std::max<int>(profit.width, GetDigitWidth() * this->unitnumber_digits) + WidgetDimensions::scaled.hsep_normal;
1697 Rect tr = ir.Indent(text_offset, rtl);
1698
1699 bool show_orderlist = this->vli.vtype >= VEH_SHIP;
1700 Rect olr = ir.Indent(std::max(ScaleGUITrad(100) + text_offset, ir.Width() / 2), rtl);
1701
1702 int image_left = (rtl && show_orderlist) ? olr.right : tr.left;
1703 int image_right = (!rtl && show_orderlist) ? olr.left : tr.right;
1704
1705 int vehicle_button_x = rtl ? ir.right - profit.width : ir.left;
1706
1707 uint max = static_cast<uint>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehgroups.size()));
1708 for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
1709
1710 const GUIVehicleGroup &vehgroup = this->vehgroups[i];
1711
1712 SetDParam(0, vehgroup.GetDisplayProfitThisYear());
1713 SetDParam(1, vehgroup.GetDisplayProfitLastYear());
1714 DrawString(tr.left, tr.right, ir.bottom - GetCharacterHeight(FS_SMALL) - WidgetDimensions::scaled.framerect.bottom,
1715 TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_LIST_PROFIT_THIS_PERIOD_LAST_PERIOD : STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
1716
1717 DrawVehicleProfitButton(vehgroup.GetOldestVehicleAge(), vehgroup.GetDisplayProfitLastYear(), vehgroup.NumVehicles(), vehicle_button_x, ir.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal);
1718
1719 switch (this->grouping) {
1720 case GB_NONE: {
1721 const Vehicle *v = vehgroup.GetSingleVehicle();
1722
1723 if (HasBit(v->vehicle_flags, VF_PATHFINDER_LOST)) {
1724 DrawSprite(SPR_WARNING_SIGN, PAL_NONE, vehicle_button_x, ir.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal + profit.height);
1725 }
1726
1727 DrawVehicleImage(v, {image_left, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0);
1728
1729 if (_settings_client.gui.show_cargo_in_vehicle_lists) {
1730 /* Get the cargoes the vehicle can carry */
1731 CargoTypes vehicle_cargoes = 0;
1732
1733 for (auto u = v; u != nullptr; u = u->Next()) {
1734 if (u->cargo_cap == 0) continue;
1735
1736 SetBit(vehicle_cargoes, u->cargo_type);
1737 }
1738
1739 if (!v->name.empty()) {
1740 /* The vehicle got a name so we will print it and the cargoes */
1741 SetDParam(0, STR_VEHICLE_NAME);
1742 SetDParam(1, v->index);
1743 SetDParam(2, STR_VEHICLE_LIST_CARGO);
1744 SetDParam(3, vehicle_cargoes);
1745 DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_NAME_AND_CARGO, TC_BLACK, SA_LEFT, false, FS_SMALL);
1746 } else if (v->group_id != DEFAULT_GROUP) {
1747 /* The vehicle has no name, but is member of a group, so print group name and the cargoes */
1748 SetDParam(0, STR_GROUP_NAME);
1749 SetDParam(1, v->group_id);
1750 SetDParam(2, STR_VEHICLE_LIST_CARGO);
1751 SetDParam(3, vehicle_cargoes);
1752 DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_NAME_AND_CARGO, TC_BLACK, SA_LEFT, false, FS_SMALL);
1753 } else {
1754 /* The vehicle has no name, and is not a member of a group, so just print the cargoes */
1755 SetDParam(0, vehicle_cargoes);
1756 DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_CARGO, TC_BLACK, SA_LEFT, false, FS_SMALL);
1757 }
1758 } else if (!v->name.empty()) {
1759 /* The vehicle got a name so we will print it */
1760 SetDParam(0, v->index);
1761 DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_NAME, TC_BLACK, SA_LEFT, false, FS_SMALL);
1762 } else if (v->group_id != DEFAULT_GROUP) {
1763 /* The vehicle has no name, but is member of a group, so print group name */
1764 SetDParam(0, v->group_id);
1765 DrawString(tr.left, tr.right, ir.top, STR_GROUP_NAME, TC_BLACK, SA_LEFT, false, FS_SMALL);
1766 }
1767
1768 if (show_orderlist) DrawSmallOrderList(v, olr.left, olr.right, ir.top, this->order_arrow_width, v->cur_real_order_index);
1769
1770 TextColour tc;
1771 if (v->IsChainInDepot()) {
1772 tc = TC_BLUE;
1773 } else {
1774 tc = (v->age > v->max_age - CalendarTime::DAYS_IN_LEAP_YEAR) ? TC_RED : TC_BLACK;
1775 }
1776
1777 SetDParam(0, v->unitnumber);
1778 DrawString(ir.left, ir.right, ir.top + WidgetDimensions::scaled.framerect.top, STR_JUST_COMMA, tc);
1779 break;
1780 }
1781
1782 case GB_SHARED_ORDERS:
1783 assert(vehgroup.NumVehicles() > 0);
1784
1785 for (int i = 0; i < static_cast<int>(vehgroup.NumVehicles()); ++i) {
1786 if (image_left + WidgetDimensions::scaled.hsep_wide * i >= image_right) break; // Break if there is no more space to draw any more vehicles anyway.
1787 DrawVehicleImage(vehgroup.vehicles_begin[i], {image_left + WidgetDimensions::scaled.hsep_wide * i, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0);
1788 }
1789
1790 if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), olr.left, olr.right, ir.top, this->order_arrow_width);
1791
1792 SetDParam(0, vehgroup.NumVehicles());
1793 DrawString(ir.left, ir.right, ir.top + WidgetDimensions::scaled.framerect.top, STR_JUST_COMMA, TC_BLACK);
1794 break;
1795
1796 default:
1797 NOT_REACHED();
1798 }
1799
1800 ir = ir.Translate(0, line_height);
1801 }
1802 }
1803
1804 void BaseVehicleListWindow::UpdateSortingFromGrouping()
1805 {
1806 /* Set up sorting. Make the window-specific _sorting variable
1807 * point to the correct global _sorting struct so we are freed
1808 * from having conditionals during window operation */
1809 switch (this->vli.vtype) {
1810 case VEH_TRAIN: this->sorting = &_sorting[this->grouping].train; break;
1811 case VEH_ROAD: this->sorting = &_sorting[this->grouping].roadveh; break;
1812 case VEH_SHIP: this->sorting = &_sorting[this->grouping].ship; break;
1813 case VEH_AIRCRAFT: this->sorting = &_sorting[this->grouping].aircraft; break;
1814 default: NOT_REACHED();
1815 }
1816 this->vehgroups.SetSortFuncs(this->GetVehicleSorterFuncs());
1817 this->vehgroups.SetListing(*this->sorting);
1818 this->vehgroups.ForceRebuild();
1819 this->vehgroups.NeedResort();
1820 }
1821
1822 void BaseVehicleListWindow::UpdateVehicleGroupBy(GroupBy group_by)
1823 {
1824 if (this->grouping != group_by) {
1825 /* Save the old sorting option, so that if we change the grouping option back later on,
1826 * UpdateSortingFromGrouping() will automatically restore the saved sorting option. */
1827 *this->sorting = this->vehgroups.GetListing();
1828
1829 this->grouping = group_by;
1830 _grouping[this->vli.type][this->vli.vtype] = group_by;
1831 this->UpdateSortingFromGrouping();
1832 }
1833 }
1834
1844 struct VehicleListWindow : public BaseVehicleListWindow {
1845 private:
1847 enum ButtonPlanes {
1848 BP_SHOW_BUTTONS,
1849 BP_HIDE_BUTTONS,
1850 };
1851
1853 enum CaptionPlanes {
1854 BP_NORMAL,
1855 BP_SHARED_ORDERS,
1856 };
1857
1858 public:
1859 VehicleListWindow(WindowDesc *desc, WindowNumber window_number) : BaseVehicleListWindow(desc, window_number)
1860 {
1861 this->CreateNestedTree();
1862
1863 this->GetWidget<NWidgetStacked>(WID_VL_FILTER_BY_CARGO_SEL)->SetDisplayedPlane((this->vli.type == VL_SHARED_ORDERS) ? SZSP_NONE : 0);
1864
1865 this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR);
1866
1867 /* Set up the window widgets */
1868 this->GetWidget<NWidgetCore>(WID_VL_LIST)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
1869
1870 NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VL_CAPTION_SELECTION);
1871 if (this->vli.type == VL_SHARED_ORDERS) {
1872 this->GetWidget<NWidgetCore>(WID_VL_CAPTION_SHARED_ORDERS)->widget_data = STR_VEHICLE_LIST_SHARED_ORDERS_LIST_CAPTION;
1873 /* If we are in the shared orders window, then disable the group-by dropdown menu.
1874 * Remove this when the group-by dropdown menu has another option apart from grouping by shared orders. */
1875 this->SetWidgetDisabledState(WID_VL_GROUP_ORDER, true);
1876 this->SetWidgetDisabledState(WID_VL_GROUP_BY_PULLDOWN, true);
1877 nwi->SetDisplayedPlane(BP_SHARED_ORDERS);
1878 } else {
1879 this->GetWidget<NWidgetCore>(WID_VL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
1880 nwi->SetDisplayedPlane(BP_NORMAL);
1881 }
1882
1883 this->FinishInitNested(window_number);
1884 if (this->vli.company != OWNER_NONE) this->owner = this->vli.company;
1885
1886 this->BuildVehicleList();
1887 this->SortVehicleList();
1888 }
1889
1890 ~VehicleListWindow()
1891 {
1892 *this->sorting = this->vehgroups.GetListing();
1893 }
1894
1895 void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
1896 {
1897 switch (widget) {
1898 case WID_VL_LIST:
1899 resize->height = GetVehicleListHeight(this->vli.vtype, 1);
1900
1901 switch (this->vli.vtype) {
1902 case VEH_TRAIN:
1903 case VEH_ROAD:
1904 size->height = 6 * resize->height;
1905 break;
1906 case VEH_SHIP:
1907 case VEH_AIRCRAFT:
1908 size->height = 4 * resize->height;
1909 break;
1910 default: NOT_REACHED();
1911 }
1912 break;
1913
1914 case WID_VL_SORT_ORDER: {
1915 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
1916 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
1917 d.height += padding.height;
1918 *size = maxdim(*size, d);
1919 break;
1920 }
1921
1922 case WID_VL_GROUP_BY_PULLDOWN:
1923 size->width = GetStringListWidth(this->vehicle_group_by_names) + padding.width;
1924 break;
1925
1926 case WID_VL_SORT_BY_PULLDOWN:
1927 size->width = GetStringListWidth(this->vehicle_group_none_sorter_names_calendar);
1928 size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_none_sorter_names_wallclock));
1929 size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names_calendar));
1930 size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names_wallclock));
1931 size->width += padding.width;
1932 break;
1933
1934 case WID_VL_FILTER_BY_CARGO:
1935 size->width = std::max(size->width, GetDropDownListDimension(this->BuildCargoDropDownList(true)).width + padding.width);
1936 break;
1937
1938 case WID_VL_MANAGE_VEHICLES_DROPDOWN: {
1939 Dimension d = this->GetActionDropdownSize(this->vli.type == VL_STANDARD, false, true);
1940 d.height += padding.height;
1941 d.width += padding.width;
1942 *size = maxdim(*size, d);
1943 break;
1944 }
1945 }
1946 }
1947
1948 void SetStringParameters(WidgetID widget) const override
1949 {
1950 switch (widget) {
1951 case WID_VL_AVAILABLE_VEHICLES:
1952 SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
1953 break;
1954
1955 case WID_VL_FILTER_BY_CARGO:
1956 SetDParam(0, this->GetCargoFilterLabel(this->cargo_filter_criteria));
1957 break;
1958
1959 case WID_VL_CAPTION:
1960 case WID_VL_CAPTION_SHARED_ORDERS: {
1961 switch (this->vli.type) {
1962 case VL_SHARED_ORDERS: // Shared Orders
1963 SetDParam(0, this->vehicles.size());
1964 break;
1965
1966 case VL_STANDARD: // Company Name
1967 SetDParam(0, STR_COMPANY_NAME);
1968 SetDParam(1, this->vli.index);
1969 SetDParam(3, this->vehicles.size());
1970 break;
1971
1972 case VL_STATION_LIST: // Station/Waypoint Name
1973 SetDParam(0, Station::IsExpected(BaseStation::Get(this->vli.index)) ? STR_STATION_NAME : STR_WAYPOINT_NAME);
1974 SetDParam(1, this->vli.index);
1975 SetDParam(3, this->vehicles.size());
1976 break;
1977
1978 case VL_DEPOT_LIST:
1979 SetDParam(0, STR_DEPOT_CAPTION);
1980 SetDParam(1, this->vli.vtype);
1981 SetDParam(2, this->vli.index);
1982 SetDParam(3, this->vehicles.size());
1983 break;
1984 default: NOT_REACHED();
1985 }
1986 break;
1987 }
1988 }
1989 }
1990
1991 void DrawWidget(const Rect &r, WidgetID widget) const override
1992 {
1993 switch (widget) {
1994 case WID_VL_SORT_ORDER:
1995 /* draw arrow pointing up/down for ascending/descending sorting */
1996 this->DrawSortButtonState(widget, this->vehgroups.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
1997 break;
1998
1999 case WID_VL_LIST:
2000 this->DrawVehicleListItems(INVALID_VEHICLE, this->resize.step_height, r);
2001 break;
2002 }
2003 }
2004
2005 void OnPaint() override
2006 {
2007 this->BuildVehicleList();
2008 this->SortVehicleList();
2009
2010 if (this->vehicles.empty() && this->IsWidgetLowered(WID_VL_MANAGE_VEHICLES_DROPDOWN)) {
2011 this->CloseChildWindows(WC_DROPDOWN_MENU);
2012 }
2013
2014 /* Hide the widgets that we will not use in this window
2015 * Some windows contains actions only fit for the owner */
2016 int plane_to_show = (this->owner == _local_company) ? BP_SHOW_BUTTONS : BP_HIDE_BUTTONS;
2017 NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VL_HIDE_BUTTONS);
2018 if (plane_to_show != nwi->shown_plane) {
2019 nwi->SetDisplayedPlane(plane_to_show);
2020 nwi->SetDirty(this);
2021 }
2022 if (this->owner == _local_company) {
2023 this->SetWidgetDisabledState(WID_VL_AVAILABLE_VEHICLES, this->vli.type != VL_STANDARD);
2024 this->SetWidgetsDisabledState(this->vehicles.empty(),
2025 WID_VL_MANAGE_VEHICLES_DROPDOWN,
2026 WID_VL_STOP_ALL,
2027 WID_VL_START_ALL);
2028 }
2029
2030 /* Set text of group by dropdown widget. */
2031 this->GetWidget<NWidgetCore>(WID_VL_GROUP_BY_PULLDOWN)->widget_data = this->vehicle_group_by_names[this->grouping];
2032
2033 /* Set text of sort by dropdown widget. */
2034 this->GetWidget<NWidgetCore>(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->GetVehicleSorterNames()[this->vehgroups.SortType()];
2035
2036 this->GetWidget<NWidgetCore>(WID_VL_FILTER_BY_CARGO)->widget_data = this->GetCargoFilterLabel(this->cargo_filter_criteria);
2037
2038 this->DrawWidgets();
2039 }
2040
2041 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2042 {
2043 switch (widget) {
2044 case WID_VL_ORDER_VIEW: // Open the shared orders window
2045 assert(this->vli.type == VL_SHARED_ORDERS);
2046 assert(!this->vehicles.empty());
2047 ShowOrdersWindow(this->vehicles[0]);
2048 break;
2049
2050 case WID_VL_SORT_ORDER: // Flip sorting method ascending/descending
2051 this->vehgroups.ToggleSortOrder();
2052 this->SetDirty();
2053 break;
2054
2055 case WID_VL_GROUP_BY_PULLDOWN: // Select sorting criteria dropdown menu
2056 ShowDropDownMenu(this, this->vehicle_group_by_names, this->grouping, WID_VL_GROUP_BY_PULLDOWN, 0, 0);
2057 return;
2058
2059 case WID_VL_SORT_BY_PULLDOWN: // Select sorting criteria dropdown menu
2060 ShowDropDownMenu(this, this->GetVehicleSorterNames(), this->vehgroups.SortType(), WID_VL_SORT_BY_PULLDOWN, 0,
2061 (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
2062 return;
2063
2064 case WID_VL_FILTER_BY_CARGO: // Cargo filter dropdown
2065 ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria, widget);
2066 break;
2067
2068 case WID_VL_LIST: { // Matrix to show vehicles
2069 auto it = this->vscroll->GetScrolledItemFromWidget(this->vehgroups, pt.y, this, WID_VL_LIST);
2070 if (it == this->vehgroups.end()) return; // click out of list bound
2071
2072 const GUIVehicleGroup &vehgroup = *it;
2073 switch (this->grouping) {
2074 case GB_NONE: {
2075 const Vehicle *v = vehgroup.GetSingleVehicle();
2076 if (!VehicleClicked(v)) {
2077 if (_ctrl_pressed) {
2078 ShowCompanyGroupForVehicle(v);
2079 } else {
2080 ShowVehicleViewWindow(v);
2081 }
2082 }
2083 break;
2084 }
2085
2086 case GB_SHARED_ORDERS: {
2087 assert(vehgroup.NumVehicles() > 0);
2088 if (!VehicleClicked(vehgroup)) {
2089 const Vehicle *v = vehgroup.vehicles_begin[0];
2090 if (_ctrl_pressed) {
2091 ShowOrdersWindow(v);
2092 } else {
2093 if (vehgroup.NumVehicles() == 1) {
2094 ShowVehicleViewWindow(v);
2095 } else {
2096 ShowVehicleListWindow(v);
2097 }
2098 }
2099 }
2100 break;
2101 }
2102
2103 default: NOT_REACHED();
2104 }
2105
2106 break;
2107 }
2108
2109 case WID_VL_AVAILABLE_VEHICLES:
2110 ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype);
2111 break;
2112
2113 case WID_VL_MANAGE_VEHICLES_DROPDOWN: {
2114 ShowDropDownList(this, this->BuildActionDropdownList(VehicleListIdentifier::UnPack(this->window_number).type == VL_STANDARD, false, true), 0, WID_VL_MANAGE_VEHICLES_DROPDOWN);
2115 break;
2116 }
2117
2118 case WID_VL_STOP_ALL:
2119 case WID_VL_START_ALL:
2120 Command<CMD_MASS_START_STOP>::Post(0, widget == WID_VL_START_ALL, true, this->vli);
2121 break;
2122 }
2123 }
2124
2125 void OnDropdownSelect(WidgetID widget, int index) override
2126 {
2127 switch (widget) {
2128 case WID_VL_GROUP_BY_PULLDOWN:
2129 this->UpdateVehicleGroupBy(static_cast<GroupBy>(index));
2130 break;
2131
2132 case WID_VL_SORT_BY_PULLDOWN:
2133 this->vehgroups.SetSortType(index);
2134 break;
2135
2136 case WID_VL_FILTER_BY_CARGO:
2137 this->SetCargoFilter(index);
2138 break;
2139
2140 case WID_VL_MANAGE_VEHICLES_DROPDOWN:
2141 assert(!this->vehicles.empty());
2142
2143 switch (index) {
2144 case ADI_REPLACE: // Replace window
2145 ShowReplaceGroupVehicleWindow(ALL_GROUP, this->vli.vtype);
2146 break;
2147 case ADI_SERVICE: // Send for servicing
2148 case ADI_DEPOT: // Send to Depots
2149 Command<CMD_SEND_VEHICLE_TO_DEPOT>::Post(GetCmdSendToDepotMsg(this->vli.vtype), 0, DepotCommand::MassSend | (index == ADI_SERVICE ? DepotCommand::Service : DepotCommand::None), this->vli);
2150 break;
2151
2152 case ADI_CREATE_GROUP: // Create group
2153 Command<CMD_ADD_VEHICLE_GROUP>::Post(CcAddVehicleNewGroup, NEW_GROUP, INVALID_VEHICLE, false, this->vli);
2154 break;
2155
2156 default: NOT_REACHED();
2157 }
2158 break;
2159
2160 default: NOT_REACHED();
2161 }
2162 this->SetDirty();
2163 }
2164
2165 void OnGameTick() override
2166 {
2167 if (this->vehgroups.NeedResort()) {
2168 StationID station = (this->vli.type == VL_STATION_LIST) ? this->vli.index : INVALID_STATION;
2169
2170 Debug(misc, 3, "Periodic resort {} list company {} at station {}", this->vli.vtype, this->owner, station);
2171 this->SetDirty();
2172 }
2173 }
2174
2175 void OnResize() override
2176 {
2177 this->vscroll->SetCapacityFromWidget(this, WID_VL_LIST);
2178 }
2179
2185 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2186 {
2187 if (!gui_scope && HasBit(data, 31) && this->vli.type == VL_SHARED_ORDERS) {
2188 /* Needs to be done in command-scope, so everything stays valid */
2189 this->vli.index = GB(data, 0, 20);
2190 this->window_number = this->vli.Pack();
2191 this->vehgroups.ForceRebuild();
2192 return;
2193 }
2194
2195 if (data == 0) {
2196 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
2197 this->vehgroups.ForceRebuild();
2198 } else {
2199 this->vehgroups.ForceResort();
2200 }
2201 }
2202 };
2203
2204 static WindowDesc _vehicle_list_other_desc(__FILE__, __LINE__,
2205 WDP_AUTO, "list_vehicles", 260, 246,
2206 WC_INVALID, WC_NONE,
2207 0,
2208 std::begin(_nested_vehicle_list), std::end(_nested_vehicle_list)
2209 );
2210
2211 static WindowDesc _vehicle_list_train_desc(__FILE__, __LINE__,
2212 WDP_AUTO, "list_vehicles_train", 325, 246,
2213 WC_TRAINS_LIST, WC_NONE,
2214 0,
2215 std::begin(_nested_vehicle_list), std::end(_nested_vehicle_list)
2216 );
2217
2218 static void ShowVehicleListWindowLocal(CompanyID company, VehicleListType vlt, VehicleType vehicle_type, uint32_t unique_number)
2219 {
2220 if (!Company::IsValidID(company) && company != OWNER_NONE) return;
2221
2222 WindowNumber num = VehicleListIdentifier(vlt, vehicle_type, company, unique_number).Pack();
2223 if (vehicle_type == VEH_TRAIN) {
2224 AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_train_desc, num);
2225 } else {
2226 _vehicle_list_other_desc.cls = GetWindowClassForVehicleType(vehicle_type);
2227 AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_other_desc, num);
2228 }
2229 }
2230
2231 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type)
2232 {
2233 /* If _settings_client.gui.advanced_vehicle_list > 1, display the Advanced list
2234 * if _settings_client.gui.advanced_vehicle_list == 1, display Advanced list only for local company
2235 * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
2236 */
2237
2238 if ((_settings_client.gui.advanced_vehicle_list > (uint)(company != _local_company)) != _ctrl_pressed) {
2239 ShowCompanyGroup(company, vehicle_type);
2240 } else {
2241 ShowVehicleListWindowLocal(company, VL_STANDARD, vehicle_type, company);
2242 }
2243 }
2244
2245 void ShowVehicleListWindow(const Vehicle *v)
2246 {
2247 ShowVehicleListWindowLocal(v->owner, VL_SHARED_ORDERS, v->type, v->FirstShared()->index);
2248 }
2249
2250 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station)
2251 {
2252 ShowVehicleListWindowLocal(company, VL_STATION_LIST, vehicle_type, station);
2253 }
2254
2255 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile)
2256 {
2257 uint16_t depot_airport_index;
2258
2259 if (vehicle_type == VEH_AIRCRAFT) {
2260 depot_airport_index = GetStationIndex(depot_tile);
2261 } else {
2262 depot_airport_index = GetDepotIndex(depot_tile);
2263 }
2264 ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_airport_index);
2265 }
2266
2267
2268 /* Unified vehicle GUI - Vehicle Details Window */
2269
2270 static_assert(WID_VD_DETAILS_CARGO_CARRIED == WID_VD_DETAILS_CARGO_CARRIED + TDW_TAB_CARGO );
2271 static_assert(WID_VD_DETAILS_TRAIN_VEHICLES == WID_VD_DETAILS_CARGO_CARRIED + TDW_TAB_INFO );
2272 static_assert(WID_VD_DETAILS_CAPACITY_OF_EACH == WID_VD_DETAILS_CARGO_CARRIED + TDW_TAB_CAPACITY);
2273 static_assert(WID_VD_DETAILS_TOTAL_CARGO == WID_VD_DETAILS_CARGO_CARRIED + TDW_TAB_TOTALS );
2274
2276 static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[] = {
2277 NWidget(NWID_HORIZONTAL),
2278 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2279 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2280 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2281 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
2282 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2283 EndContainer(),
2284 NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetMinimalSize(405, 42), SetResize(1, 0), EndContainer(),
2285 NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_MIDDLE_DETAILS), SetMinimalSize(405, 45), SetResize(1, 0), EndContainer(),
2286 NWidget(NWID_HORIZONTAL),
2287 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_DECREASE_SERVICING_INTERVAL), SetFill(0, 1),
2288 SetDataTip(AWV_DECREASE, STR_NULL),
2289 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_INCREASE_SERVICING_INTERVAL), SetFill(0, 1),
2290 SetDataTip(AWV_INCREASE, STR_NULL),
2291 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VD_SERVICE_INTERVAL_DROPDOWN), SetFill(0, 1),
2292 SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
2293 NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
2294 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
2295 EndContainer(),
2296 };
2297
2299 static constexpr NWidgetPart _nested_train_vehicle_details_widgets[] = {
2300 NWidget(NWID_HORIZONTAL),
2301 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2302 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2303 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2304 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
2305 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2306 EndContainer(),
2307 NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetResize(1, 0), SetMinimalSize(405, 42), EndContainer(),
2308 NWidget(NWID_HORIZONTAL),
2309 NWidget(WWT_MATRIX, COLOUR_GREY, WID_VD_MATRIX), SetResize(1, 1), SetMinimalSize(393, 45), SetMatrixDataTip(1, 0, STR_NULL), SetFill(1, 0), SetScrollbar(WID_VD_SCROLLBAR),
2310 NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VD_SCROLLBAR),
2311 EndContainer(),
2312 NWidget(NWID_HORIZONTAL),
2313 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_DECREASE_SERVICING_INTERVAL), SetFill(0, 1),
2314 SetDataTip(AWV_DECREASE, STR_NULL),
2315 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_VD_INCREASE_SERVICING_INTERVAL), SetFill(0, 1),
2316 SetDataTip(AWV_INCREASE, STR_NULL),
2317 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VD_SERVICE_INTERVAL_DROPDOWN), SetFill(0, 1),
2318 SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
2319 NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
2320 EndContainer(),
2321 NWidget(NWID_HORIZONTAL),
2322 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_CARGO_CARRIED), SetMinimalSize(96, 12),
2323 SetDataTip(STR_VEHICLE_DETAIL_TAB_CARGO, STR_VEHICLE_DETAILS_TRAIN_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2324 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_TRAIN_VEHICLES), SetMinimalSize(99, 12),
2325 SetDataTip(STR_VEHICLE_DETAIL_TAB_INFORMATION, STR_VEHICLE_DETAILS_TRAIN_INFORMATION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2326 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_CAPACITY_OF_EACH), SetMinimalSize(99, 12),
2327 SetDataTip(STR_VEHICLE_DETAIL_TAB_CAPACITIES, STR_VEHICLE_DETAILS_TRAIN_CAPACITIES_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2328 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_DETAILS_TOTAL_CARGO), SetMinimalSize(99, 12),
2329 SetDataTip(STR_VEHICLE_DETAIL_TAB_TOTAL_CARGO, STR_VEHICLE_DETAILS_TRAIN_TOTAL_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2330 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
2331 EndContainer(),
2332 };
2333
2334
2335 extern int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab);
2336 extern void DrawTrainDetails(const Train *v, const Rect &r, int vscroll_pos, uint16_t vscroll_cap, TrainDetailsWindowTabs det_tab);
2337 extern void DrawRoadVehDetails(const Vehicle *v, const Rect &r);
2338 extern void DrawShipDetails(const Vehicle *v, const Rect &r);
2339 extern void DrawAircraftDetails(const Aircraft *v, const Rect &r);
2340
2341 static StringID _service_interval_dropdown_calendar[] = {
2342 STR_VEHICLE_DETAILS_DEFAULT,
2343 STR_VEHICLE_DETAILS_DAYS,
2344 STR_VEHICLE_DETAILS_PERCENT,
2345 INVALID_STRING_ID,
2346 };
2347
2348 static StringID _service_interval_dropdown_wallclock[] = {
2349 STR_VEHICLE_DETAILS_DEFAULT,
2350 STR_VEHICLE_DETAILS_MINUTES,
2351 STR_VEHICLE_DETAILS_PERCENT,
2352 INVALID_STRING_ID,
2353 };
2354
2356 struct VehicleDetailsWindow : Window {
2357 TrainDetailsWindowTabs tab;
2358 Scrollbar *vscroll;
2359
2361 VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2362 {
2363 const Vehicle *v = Vehicle::Get(window_number);
2364
2365 this->CreateNestedTree();
2366 this->vscroll = (v->type == VEH_TRAIN ? this->GetScrollbar(WID_VD_SCROLLBAR) : nullptr);
2367 this->FinishInitNested(window_number);
2368
2369 this->owner = v->owner;
2370 this->tab = TDW_TAB_CARGO;
2371 }
2372
2378 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2379 {
2380 if (data == VIWD_AUTOREPLACE) {
2381 /* Autoreplace replaced the vehicle.
2382 * Nothing to do for this window. */
2383 return;
2384 }
2385 if (!gui_scope) return;
2386 const Vehicle *v = Vehicle::Get(this->window_number);
2387 if (v->type == VEH_ROAD) {
2388 const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_VD_MIDDLE_DETAILS);
2389 uint aimed_height = this->GetRoadVehDetailsHeight(v);
2390 /* If the number of articulated parts changes, the size of the window must change too. */
2391 if (aimed_height != nwid_info->current_y) {
2392 this->ReInit();
2393 }
2394 }
2395 }
2396
2402 uint GetRoadVehDetailsHeight(const Vehicle *v)
2403 {
2404 uint desired_height;
2405 if (v->HasArticulatedPart()) {
2406 /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
2407 desired_height = ScaleGUITrad(15) + 3 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal * 2;
2408 /* Add space for the cargo amount for each part. */
2409 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2410 if (u->cargo_cap != 0) desired_height += GetCharacterHeight(FS_NORMAL);
2411 }
2412 } else {
2413 desired_height = 4 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal * 2;
2414 }
2415 return desired_height;
2416 }
2417
2418 void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
2419 {
2420 switch (widget) {
2421 case WID_VD_TOP_DETAILS: {
2422 Dimension dim = { 0, 0 };
2423 size->height = 4 * GetCharacterHeight(FS_NORMAL) + padding.height;
2424
2425 for (uint i = 0; i < 4; i++) SetDParamMaxValue(i, INT16_MAX);
2426 static const StringID info_strings[] = {
2427 STR_VEHICLE_INFO_MAX_SPEED,
2428 STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED,
2429 STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE,
2430 STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE,
2431 STR_VEHICLE_INFO_PROFIT_THIS_PERIOD_LAST_PERIOD_MIN_PERFORMANCE,
2432 STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS
2433 };
2434 for (uint i = 0; i < lengthof(info_strings); i++) {
2435 dim = maxdim(dim, GetStringBoundingBox(info_strings[i]));
2436 }
2437 SetDParam(0, STR_VEHICLE_INFO_AGE);
2438 dim = maxdim(dim, GetStringBoundingBox(TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_INFO_AGE_RUNNING_COST_PERIOD : STR_VEHICLE_INFO_AGE_RUNNING_COST_YR));
2439 size->width = dim.width + padding.width;
2440 break;
2441 }
2442
2443 case WID_VD_MIDDLE_DETAILS: {
2444 const Vehicle *v = Vehicle::Get(this->window_number);
2445 switch (v->type) {
2446 case VEH_ROAD:
2447 size->height = this->GetRoadVehDetailsHeight(v) + padding.height;
2448 break;
2449
2450 case VEH_SHIP:
2451 size->height = 4 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal * 2 + padding.height;
2452 break;
2453
2454 case VEH_AIRCRAFT:
2455 size->height = 5 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal * 2 + padding.height;
2456 break;
2457
2458 default:
2459 NOT_REACHED(); // Train uses WID_VD_MATRIX instead.
2460 }
2461 break;
2462 }
2463
2464 case WID_VD_MATRIX:
2465 resize->height = std::max<uint>(ScaleGUITrad(14), GetCharacterHeight(FS_NORMAL) + padding.height);
2466 size->height = 4 * resize->height;
2467 break;
2468
2469 case WID_VD_SERVICE_INTERVAL_DROPDOWN: {
2470 Dimension d{0, 0};
2471 for (const StringID *strs : {_service_interval_dropdown_calendar, _service_interval_dropdown_wallclock}) {
2472 while (*strs != INVALID_STRING_ID) {
2473 d = maxdim(d, GetStringBoundingBox(*strs++));
2474 }
2475 }
2476 d.width += padding.width;
2477 d.height += padding.height;
2478 *size = maxdim(*size, d);
2479 break;
2480 }
2481
2482 case WID_VD_SERVICING_INTERVAL:
2483 SetDParamMaxValue(0, MAX_SERVINT_DAYS); // Roughly the maximum interval
2484
2485 /* Do we show the last serviced value as a date or minutes since service? */
2486 if (TimerGameEconomy::UsingWallclockUnits()) {
2487 SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_MINUTES_AGO);
2488 /*/ Vehicle was last serviced at year 0, and we're at max year */
2489 SetDParamMaxValue(2, EconomyTime::MONTHS_IN_YEAR * EconomyTime::MAX_YEAR.base());
2490 } else {
2491 SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_DATE);
2492 /*/ Vehicle was last serviced at year 0, and we're at max year */
2493 SetDParamMaxValue(2, TimerGameEconomy::DateAtStartOfYear(EconomyTime::MAX_YEAR));
2494 }
2495 size->width = std::max(
2496 GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width,
2497 GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width
2498 ) + padding.width;
2499 size->height = GetCharacterHeight(FS_NORMAL) + padding.height;
2500 break;
2501 }
2502 }
2503
2505 static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
2506 {
2507 const VehicleDefaultSettings *vds = &Company::Get(company_id)->settings.vehicle;
2508 switch (vehicle_type) {
2509 default: NOT_REACHED();
2510 case VEH_TRAIN: return vds->servint_trains != 0;
2511 case VEH_ROAD: return vds->servint_roadveh != 0;
2512 case VEH_SHIP: return vds->servint_ships != 0;
2513 case VEH_AIRCRAFT: return vds->servint_aircraft != 0;
2514 }
2515 }
2516
2526 static void DrawVehicleDetails(const Vehicle *v, const Rect &r, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
2527 {
2528 switch (v->type) {
2529 case VEH_TRAIN: DrawTrainDetails(Train::From(v), r, vscroll_pos, vscroll_cap, det_tab); break;
2530 case VEH_ROAD: DrawRoadVehDetails(v, r); break;
2531 case VEH_SHIP: DrawShipDetails(v, r); break;
2532 case VEH_AIRCRAFT: DrawAircraftDetails(Aircraft::From(v), r); break;
2533 default: NOT_REACHED();
2534 }
2535 }
2536
2537 void SetStringParameters(WidgetID widget) const override
2538 {
2539 if (widget == WID_VD_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
2540 }
2541
2542 void DrawWidget(const Rect &r, WidgetID widget) const override
2543 {
2544 const Vehicle *v = Vehicle::Get(this->window_number);
2545
2546 switch (widget) {
2547 case WID_VD_TOP_DETAILS: {
2548 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
2549
2550 /* Draw running cost */
2551 SetDParam(1, TimerGameCalendar::DateToYear(v->age));
2552 SetDParam(0, (v->age + CalendarTime::DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_INFO_AGE : STR_VEHICLE_INFO_AGE_RED);
2553 SetDParam(2, TimerGameCalendar::DateToYear(v->max_age));
2554 SetDParam(3, v->GetDisplayRunningCost());
2555 DrawString(tr, TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_INFO_AGE_RUNNING_COST_PERIOD : STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
2556 tr.top += GetCharacterHeight(FS_NORMAL);
2557
2558 /* Draw max speed */
2559 StringID string;
2560 if (v->type == VEH_TRAIN ||
2561 (v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) {
2562 const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
2563 SetDParam(2, PackVelocity(v->GetDisplayMaxSpeed(), v->type));
2564 SetDParam(1, gcache->cached_power);
2565 SetDParam(0, gcache->cached_weight);
2566 SetDParam(3, gcache->cached_max_te);
2567 if (v->type == VEH_TRAIN && (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ||
2568 GetRailTypeInfo(Train::From(v)->railtype)->acceleration_type == 2)) {
2569 string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED;
2570 } else {
2571 string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE;
2572 }
2573 } else {
2574 SetDParam(0, PackVelocity(v->GetDisplayMaxSpeed(), v->type));
2575 if (v->type == VEH_AIRCRAFT) {
2576 SetDParam(1, v->GetEngine()->GetAircraftTypeText());
2577 if (Aircraft::From(v)->GetRange() > 0) {
2578 SetDParam(2, Aircraft::From(v)->GetRange());
2579 string = STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE;
2580 } else {
2581 string = STR_VEHICLE_INFO_MAX_SPEED_TYPE;
2582 }
2583 } else {
2584 string = STR_VEHICLE_INFO_MAX_SPEED;
2585 }
2586 }
2587 DrawString(tr, string);
2588 tr.top += GetCharacterHeight(FS_NORMAL);
2589
2590 /* Draw profit */
2591 SetDParam(0, v->GetDisplayProfitThisYear());
2592 SetDParam(1, v->GetDisplayProfitLastYear());
2593 if (v->IsGroundVehicle()) {
2594 SetDParam(2, v->GetDisplayMinPowerToWeight());
2595 DrawString(tr, TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_INFO_PROFIT_THIS_PERIOD_LAST_PERIOD_MIN_PERFORMANCE : STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE);
2596 } else {
2597 DrawString(tr, TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_INFO_PROFIT_THIS_PERIOD_LAST_PERIOD : STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR);
2598 }
2599 tr.top += GetCharacterHeight(FS_NORMAL);
2600
2601 /* Draw breakdown & reliability */
2602 SetDParam(0, ToPercent16(v->reliability));
2603 SetDParam(1, v->breakdowns_since_last_service);
2604 DrawString(tr, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
2605 break;
2606 }
2607
2608 case WID_VD_MATRIX: {
2609 /* For trains only. */
2610 DrawVehicleDetails(v, r.Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero).WithHeight(this->resize.step_height), this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->tab);
2611 break;
2612 }
2613
2614 case WID_VD_MIDDLE_DETAILS: {
2615 /* For other vehicles, at the place of the matrix. */
2616 bool rtl = _current_text_dir == TD_RTL;
2617 uint sprite_width = GetSingleVehicleWidth(v, EIT_IN_DETAILS) + WidgetDimensions::scaled.framerect.Horizontal();
2618 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
2619
2620 /* Articulated road vehicles use a complete line. */
2621 if (v->type == VEH_ROAD && v->HasArticulatedPart()) {
2622 DrawVehicleImage(v, tr.WithHeight(ScaleGUITrad(GetVehicleHeight(v->type)), false), INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2623 } else {
2624 Rect sr = tr.WithWidth(sprite_width, rtl);
2625 DrawVehicleImage(v, sr.WithHeight(ScaleGUITrad(GetVehicleHeight(v->type)), false), INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2626 }
2627
2628 DrawVehicleDetails(v, tr.Indent(sprite_width, rtl), 0, 0, this->tab);
2629 break;
2630 }
2631
2632 case WID_VD_SERVICING_INTERVAL: {
2633 /* Draw service interval text */
2634 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
2635
2636 SetDParam(0, v->GetServiceInterval());
2637
2638 /* We're using wallclock units. Show minutes since last serviced. */
2639 if (TimerGameEconomy::UsingWallclockUnits()) {
2640 int minutes_since_serviced = (TimerGameEconomy::date - v->date_of_last_service).base() / EconomyTime::DAYS_IN_ECONOMY_MONTH;
2641 SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_MINUTES_AGO);
2642 SetDParam(2, minutes_since_serviced);
2643 DrawString(tr.left, tr.right, CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)),
2644 v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_MINUTES);
2645 break;
2646 }
2647
2648 /* We're using calendar dates. Show the date of last service. */
2649 SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_DATE);
2650 SetDParam(2, v->date_of_last_service);
2651 DrawString(tr.left, tr.right, CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)),
2652 v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS);
2653 break;
2654 }
2655 }
2656 }
2657
2659 void OnPaint() override
2660 {
2661 const Vehicle *v = Vehicle::Get(this->window_number);
2662
2663 if (v->type == VEH_TRAIN) {
2664 this->LowerWidget(WID_VD_DETAILS_CARGO_CARRIED + this->tab);
2665 this->vscroll->SetCount(GetTrainDetailsWndVScroll(v->index, this->tab));
2666 }
2667
2668 /* Disable service-scroller when interval is set to disabled */
2669 this->SetWidgetsDisabledState(!IsVehicleServiceIntervalEnabled(v->type, v->owner),
2670 WID_VD_INCREASE_SERVICING_INTERVAL,
2671 WID_VD_DECREASE_SERVICING_INTERVAL);
2672
2673 StringID str =
2674 !v->ServiceIntervalIsCustom() ? STR_VEHICLE_DETAILS_DEFAULT :
2675 v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT :
2676 TimerGameEconomy::UsingWallclockUnits() ? STR_VEHICLE_DETAILS_MINUTES : STR_VEHICLE_DETAILS_DAYS;
2677 this->GetWidget<NWidgetCore>(WID_VD_SERVICE_INTERVAL_DROPDOWN)->widget_data = str;
2678
2679 this->DrawWidgets();
2680 }
2681
2682 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2683 {
2684 switch (widget) {
2685 case WID_VD_INCREASE_SERVICING_INTERVAL: // increase int
2686 case WID_VD_DECREASE_SERVICING_INTERVAL: { // decrease int
2687 const Vehicle *v = Vehicle::Get(this->window_number);
2688 int mod;
2689 if (!v->ServiceIntervalIsPercent() && TimerGameEconomy::UsingWallclockUnits()) {
2690 mod = _ctrl_pressed ? 1 : 5;
2691 } else {
2692 mod = _ctrl_pressed ? 5 : 10;
2693 }
2694
2695 mod = (widget == WID_VD_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
2696 mod = GetServiceIntervalClamped(mod + v->GetServiceInterval(), v->ServiceIntervalIsPercent());
2697 if (mod == v->GetServiceInterval()) return;
2698
2699 Command<CMD_CHANGE_SERVICE_INT>::Post(STR_ERROR_CAN_T_CHANGE_SERVICING, v->index, mod, true, v->ServiceIntervalIsPercent());
2700 break;
2701 }
2702
2703 case WID_VD_SERVICE_INTERVAL_DROPDOWN: {
2704 const Vehicle *v = Vehicle::Get(this->window_number);
2705 ShowDropDownMenu(this,
2706 TimerGameEconomy::UsingWallclockUnits() ? _service_interval_dropdown_wallclock : _service_interval_dropdown_calendar,
2707 v->ServiceIntervalIsCustom() ? (v->ServiceIntervalIsPercent() ? 2 : 1) : 0, widget, 0, 0);
2708 break;
2709 }
2710
2711 case WID_VD_DETAILS_CARGO_CARRIED:
2712 case WID_VD_DETAILS_TRAIN_VEHICLES:
2713 case WID_VD_DETAILS_CAPACITY_OF_EACH:
2714 case WID_VD_DETAILS_TOTAL_CARGO:
2715 this->SetWidgetsLoweredState(false,
2716 WID_VD_DETAILS_CARGO_CARRIED,
2717 WID_VD_DETAILS_TRAIN_VEHICLES,
2718 WID_VD_DETAILS_CAPACITY_OF_EACH,
2719 WID_VD_DETAILS_TOTAL_CARGO);
2720
2721 this->tab = (TrainDetailsWindowTabs)(widget - WID_VD_DETAILS_CARGO_CARRIED);
2722 this->SetDirty();
2723 break;
2724 }
2725 }
2726
2727 bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override
2728 {
2729 if (widget == WID_VD_INCREASE_SERVICING_INTERVAL || widget == WID_VD_DECREASE_SERVICING_INTERVAL) {
2730 const Vehicle *v = Vehicle::Get(this->window_number);
2731 StringID tool_tip;
2732 if (v->ServiceIntervalIsPercent()) {
2733 tool_tip = widget == WID_VD_INCREASE_SERVICING_INTERVAL ? STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP_PERCENT : STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP_PERCENT;
2734 } else if (TimerGameEconomy::UsingWallclockUnits()) {
2735 tool_tip = widget == WID_VD_INCREASE_SERVICING_INTERVAL ? STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP_MINUTES : STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP_MINUTES;
2736 } else {
2737 tool_tip = widget == WID_VD_INCREASE_SERVICING_INTERVAL ? STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP_DAYS : STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP_DAYS;
2738 }
2739 GuiShowTooltips(this, tool_tip, close_cond);
2740 return true;
2741 }
2742
2743 return false;
2744 }
2745
2746 void OnDropdownSelect(WidgetID widget, int index) override
2747 {
2748 switch (widget) {
2749 case WID_VD_SERVICE_INTERVAL_DROPDOWN: {
2750 const Vehicle *v = Vehicle::Get(this->window_number);
2751 bool iscustom = index != 0;
2752 bool ispercent = iscustom ? (index == 2) : Company::Get(v->owner)->settings.vehicle.servint_ispercent;
2753 uint16_t interval = GetServiceIntervalClamped(v->GetServiceInterval(), ispercent);
2754 Command<CMD_CHANGE_SERVICE_INT>::Post(STR_ERROR_CAN_T_CHANGE_SERVICING, v->index, interval, iscustom, ispercent);
2755 break;
2756 }
2757 }
2758 }
2759
2760 void OnResize() override
2761 {
2762 NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VD_MATRIX);
2763 if (nwi != nullptr) {
2764 this->vscroll->SetCapacityFromWidget(this, WID_VD_MATRIX);
2765 }
2766 }
2767 };
2768
2770 static WindowDesc _train_vehicle_details_desc(__FILE__, __LINE__,
2771 WDP_AUTO, "view_vehicle_details_train", 405, 178,
2772 WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
2773 0,
2774 std::begin(_nested_train_vehicle_details_widgets), std::end(_nested_train_vehicle_details_widgets)
2775 );
2776
2778 static WindowDesc _nontrain_vehicle_details_desc(__FILE__, __LINE__,
2779 WDP_AUTO, "view_vehicle_details", 405, 113,
2780 WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
2781 0,
2782 std::begin(_nested_nontrain_vehicle_details_widgets), std::end(_nested_nontrain_vehicle_details_widgets)
2783 );
2784
2786 static void ShowVehicleDetailsWindow(const Vehicle *v)
2787 {
2788 CloseWindowById(WC_VEHICLE_ORDERS, v->index, false);
2789 CloseWindowById(WC_VEHICLE_TIMETABLE, v->index, false);
2790 AllocateWindowDescFront<VehicleDetailsWindow>((v->type == VEH_TRAIN) ? &_train_vehicle_details_desc : &_nontrain_vehicle_details_desc, v->index);
2791 }
2792
2793
2794 /* Unified vehicle GUI - Vehicle View Window */
2795
2797 static constexpr NWidgetPart _nested_vehicle_view_widgets[] = {
2798 NWidget(NWID_HORIZONTAL),
2799 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2800 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_RENAME), SetMinimalSize(12, 14), SetDataTip(SPR_RENAME, STR_NULL /* filled in later */),
2801 NWidget(WWT_CAPTION, COLOUR_GREY, WID_VV_CAPTION), SetDataTip(STR_VEHICLE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2802 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_LOCATION), SetMinimalSize(12, 14), SetDataTip(SPR_GOTO_LOCATION, STR_NULL /* filled in later */),
2803 NWidget(WWT_DEBUGBOX, COLOUR_GREY),
2804 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2805 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
2806 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2807 EndContainer(),
2808 NWidget(NWID_HORIZONTAL),
2809 NWidget(WWT_PANEL, COLOUR_GREY),
2810 NWidget(WWT_INSET, COLOUR_GREY), SetPadding(2, 2, 2, 2),
2811 NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1),
2812 EndContainer(),
2813 EndContainer(),
2814 NWidget(NWID_VERTICAL),
2815 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VV_SELECT_DEPOT_CLONE),
2816 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_GOTO_DEPOT), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2817 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_CLONE), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2818 EndContainer(),
2819 /* For trains only, 'ignore signal' button. */
2820 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_FORCE_PROCEED), SetMinimalSize(18, 18),
2821 SetDataTip(SPR_IGNORE_SIGNALS, STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP),
2822 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VV_SELECT_REFIT_TURN),
2823 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_REFIT), SetMinimalSize(18, 18), SetDataTip(SPR_REFIT_VEHICLE, 0x0 /* filled later */),
2824 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_TURN_AROUND), SetMinimalSize(18, 18),
2825 SetDataTip(SPR_FORCE_VEHICLE_TURN, STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP),
2826 EndContainer(),
2827 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_ORDERS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_ORDERS, 0x0 /* filled later */),
2828 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_DETAILS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_VEHICLE_DETAILS, 0x0 /* filled later */),
2829 NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(18, 0), SetResize(0, 1), EndContainer(),
2830 EndContainer(),
2831 EndContainer(),
2832 NWidget(NWID_HORIZONTAL),
2833 NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_VV_START_STOP), SetResize(1, 0), SetFill(1, 0),
2834 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_ORDER_LOCATION), SetMinimalSize(12, 14), SetDataTip(SPR_GOTO_LOCATION, STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP),
2835 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
2836 EndContainer(),
2837 };
2838
2839 /* Just to make sure, nobody has changed the vehicle type constants, as we are
2840 using them for array indexing in a number of places here. */
2841 static_assert(VEH_TRAIN == 0);
2842 static_assert(VEH_ROAD == 1);
2843 static_assert(VEH_SHIP == 2);
2844 static_assert(VEH_AIRCRAFT == 3);
2845
2847 static const ZoomLevel _vehicle_view_zoom_levels[] = {
2848 ZOOM_LVL_TRAIN,
2849 ZOOM_LVL_ROADVEH,
2850 ZOOM_LVL_SHIP,
2851 ZOOM_LVL_AIRCRAFT,
2852 };
2853
2854 /* Constants for geometry of vehicle view viewport */
2855 static const int VV_INITIAL_VIEWPORT_WIDTH = 226;
2856 static const int VV_INITIAL_VIEWPORT_HEIGHT = 84;
2857 static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102;
2858
2860 enum VehicleCommandTranslation {
2861 VCT_CMD_START_STOP = 0,
2862 VCT_CMD_CLONE_VEH,
2863 VCT_CMD_TURN_AROUND,
2864 };
2865
2867 static const StringID _vehicle_msg_translation_table[][4] = {
2868 { // VCT_CMD_START_STOP
2869 STR_ERROR_CAN_T_STOP_START_TRAIN,
2870 STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE,
2871 STR_ERROR_CAN_T_STOP_START_SHIP,
2872 STR_ERROR_CAN_T_STOP_START_AIRCRAFT
2873 },
2874 { // VCT_CMD_CLONE_VEH
2875 STR_ERROR_CAN_T_BUY_TRAIN,
2876 STR_ERROR_CAN_T_BUY_ROAD_VEHICLE,
2877 STR_ERROR_CAN_T_BUY_SHIP,
2878 STR_ERROR_CAN_T_BUY_AIRCRAFT
2879 },
2880 { // VCT_CMD_TURN_AROUND
2881 STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN,
2882 STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN,
2883 INVALID_STRING_ID, // invalid for ships
2884 INVALID_STRING_ID // invalid for aircraft
2885 },
2886 };
2887
2893 void CcStartStopVehicle(Commands, const CommandCost &result, VehicleID veh_id, bool)
2894 {
2895 if (result.Failed()) return;
2896
2897 const Vehicle *v = Vehicle::GetIfValid(veh_id);
2898 if (v == nullptr || !v->IsPrimaryVehicle() || v->owner != _local_company) return;
2899
2900 StringID msg = (v->vehstatus & VS_STOPPED) ? STR_VEHICLE_COMMAND_STOPPED : STR_VEHICLE_COMMAND_STARTED;
2901 Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos);
2902 AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
2903 }
2904
2910 void StartStopVehicle(const Vehicle *v, bool texteffect)
2911 {
2912 assert(v->IsPrimaryVehicle());
2913 Command<CMD_START_STOP_VEHICLE>::Post(_vehicle_msg_translation_table[VCT_CMD_START_STOP][v->type], texteffect ? CcStartStopVehicle : nullptr, v->tile, v->index, false);
2914 }
2915
2917 static bool IsVehicleRefitable(const Vehicle *v)
2918 {
2919 if (!v->IsStoppedInDepot()) return false;
2920
2921 do {
2922 if (IsEngineRefittable(v->engine_type)) return true;
2923 } while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
2924
2925 return false;
2926 }
2927
2929 struct VehicleViewWindow : Window {
2930 private:
2932 enum PlaneSelections {
2933 SEL_DC_GOTO_DEPOT,
2934 SEL_DC_CLONE,
2935
2936 SEL_RT_REFIT,
2937 SEL_RT_TURN_AROUND,
2938
2939 SEL_DC_BASEPLANE = SEL_DC_GOTO_DEPOT,
2940 SEL_RT_BASEPLANE = SEL_RT_REFIT,
2941 };
2942 bool mouse_over_start_stop = false;
2943
2948 void SelectPlane(PlaneSelections plane)
2949 {
2950 switch (plane) {
2951 case SEL_DC_GOTO_DEPOT:
2952 case SEL_DC_CLONE:
2953 this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE)->SetDisplayedPlane(plane - SEL_DC_BASEPLANE);
2954 break;
2955
2956 case SEL_RT_REFIT:
2957 case SEL_RT_TURN_AROUND:
2958 this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN)->SetDisplayedPlane(plane - SEL_RT_BASEPLANE);
2959 break;
2960
2961 default:
2962 NOT_REACHED();
2963 }
2964 }
2965
2966 public:
2967 VehicleViewWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2968 {
2969 this->flags |= WF_DISABLE_VP_SCROLL;
2970 this->CreateNestedTree();
2971
2972 /* Sprites for the 'send to depot' button indexed by vehicle type. */
2973 static const SpriteID vehicle_view_goto_depot_sprites[] = {
2974 SPR_SEND_TRAIN_TODEPOT,
2975 SPR_SEND_ROADVEH_TODEPOT,
2976 SPR_SEND_SHIP_TODEPOT,
2977 SPR_SEND_AIRCRAFT_TODEPOT,
2978 };
2979 const Vehicle *v = Vehicle::Get(window_number);
2980 this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->widget_data = vehicle_view_goto_depot_sprites[v->type];
2981
2982 /* Sprites for the 'clone vehicle' button indexed by vehicle type. */
2983 static const SpriteID vehicle_view_clone_sprites[] = {
2984 SPR_CLONE_TRAIN,
2985 SPR_CLONE_ROADVEH,
2986 SPR_CLONE_SHIP,
2987 SPR_CLONE_AIRCRAFT,
2988 };
2989 this->GetWidget<NWidgetCore>(WID_VV_CLONE)->widget_data = vehicle_view_clone_sprites[v->type];
2990
2991 switch (v->type) {
2992 case VEH_TRAIN:
2993 this->GetWidget<NWidgetCore>(WID_VV_TURN_AROUND)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP;
2994 break;
2995
2996 case VEH_ROAD:
2997 break;
2998
2999 case VEH_SHIP:
3000 case VEH_AIRCRAFT:
3001 this->SelectPlane(SEL_RT_REFIT);
3002 break;
3003
3004 default: NOT_REACHED();
3005 }
3006 this->FinishInitNested(window_number);
3007 this->owner = v->owner;
3008 this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT)->InitializeViewport(this, static_cast<VehicleID>(this->window_number), ScaleZoomGUI(_vehicle_view_zoom_levels[v->type]));
3009
3010 this->GetWidget<NWidgetCore>(WID_VV_START_STOP)->tool_tip = STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP + v->type;
3011 this->GetWidget<NWidgetCore>(WID_VV_RENAME)->tool_tip = STR_VEHICLE_DETAILS_TRAIN_RENAME + v->type;
3012 this->GetWidget<NWidgetCore>(WID_VV_LOCATION)->tool_tip = STR_VEHICLE_VIEW_TRAIN_CENTER_TOOLTIP + v->type;
3013 this->GetWidget<NWidgetCore>(WID_VV_REFIT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP + v->type;
3014 this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + v->type;
3015 this->GetWidget<NWidgetCore>(WID_VV_SHOW_ORDERS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP + v->type;
3016 this->GetWidget<NWidgetCore>(WID_VV_SHOW_DETAILS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP + v->type;
3017 this->GetWidget<NWidgetCore>(WID_VV_CLONE)->tool_tip = STR_VEHICLE_VIEW_CLONE_TRAIN_INFO + v->type;
3018
3019 this->UpdateButtonStatus();
3020 }
3021
3022 void Close([[maybe_unused]] int data = 0) override
3023 {
3024 CloseWindowById(WC_VEHICLE_ORDERS, this->window_number, false);
3025 CloseWindowById(WC_VEHICLE_REFIT, this->window_number, false);
3026 CloseWindowById(WC_VEHICLE_DETAILS, this->window_number, false);
3027 CloseWindowById(WC_VEHICLE_TIMETABLE, this->window_number, false);
3028 this->Window::Close();
3029 }
3030
3031 void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
3032 {
3033 const Vehicle *v = Vehicle::Get(this->window_number);
3034 switch (widget) {
3035 case WID_VV_START_STOP:
3036 size->height = std::max<uint>({size->height, (uint)GetCharacterHeight(FS_NORMAL), GetScaledSpriteSize(SPR_WARNING_SIGN).height, GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED).height, GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING).height}) + padding.height;
3037 break;
3038
3039 case WID_VV_FORCE_PROCEED:
3040 if (v->type != VEH_TRAIN) {
3041 size->height = 0;
3042 size->width = 0;
3043 }
3044 break;
3045
3046 case WID_VV_VIEWPORT:
3047 size->width = VV_INITIAL_VIEWPORT_WIDTH;
3048 size->height = (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT;
3049 break;
3050 }
3051 }
3052
3053 void OnPaint() override
3054 {
3055 const Vehicle *v = Vehicle::Get(this->window_number);
3056 bool is_localcompany = v->owner == _local_company;
3057 bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
3058
3059 this->SetWidgetDisabledState(WID_VV_RENAME, !is_localcompany);
3060 this->SetWidgetDisabledState(WID_VV_GOTO_DEPOT, !is_localcompany);
3061 this->SetWidgetDisabledState(WID_VV_REFIT, !refitable_and_stopped_in_depot || !is_localcompany);
3062 this->SetWidgetDisabledState(WID_VV_CLONE, !is_localcompany);
3063
3064 if (v->type == VEH_TRAIN) {
3065 this->SetWidgetLoweredState(WID_VV_FORCE_PROCEED, Train::From(v)->force_proceed == TFP_SIGNAL);
3066 this->SetWidgetDisabledState(WID_VV_FORCE_PROCEED, !is_localcompany);
3067 }
3068
3069 if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
3070 this->SetWidgetDisabledState(WID_VV_TURN_AROUND, !is_localcompany);
3071 }
3072
3073 this->SetWidgetDisabledState(WID_VV_ORDER_LOCATION, v->current_order.GetLocation(v) == INVALID_TILE);
3074
3075 this->DrawWidgets();
3076 }
3077
3078 void SetStringParameters(WidgetID widget) const override
3079 {
3080 if (widget != WID_VV_CAPTION) return;
3081
3082 const Vehicle *v = Vehicle::Get(this->window_number);
3083 SetDParam(0, v->index);
3084 }
3085
3086 void DrawWidget(const Rect &r, WidgetID widget) const override
3087 {
3088 if (widget != WID_VV_START_STOP) return;
3089
3090 Vehicle *v = Vehicle::Get(this->window_number);
3091 StringID str;
3092 TextColour text_colour = TC_FROMSTRING;
3093 if (v->vehstatus & VS_CRASHED) {
3094 str = STR_VEHICLE_STATUS_CRASHED;
3095 } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
3096 str = STR_VEHICLE_STATUS_BROKEN_DOWN;
3097 } else if (v->vehstatus & VS_STOPPED && (!mouse_over_start_stop || v->IsStoppedInDepot())) {
3098 if (v->type == VEH_TRAIN) {
3099 if (v->cur_speed == 0) {
3100 if (Train::From(v)->gcache.cached_power == 0) {
3101 str = STR_VEHICLE_STATUS_TRAIN_NO_POWER;
3102 } else {
3103 str = STR_VEHICLE_STATUS_STOPPED;
3104 }
3105 } else {
3106 SetDParam(0, PackVelocity(v->GetDisplaySpeed(), v->type));
3107 str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL;
3108 }
3109 } else { // no train
3110 str = STR_VEHICLE_STATUS_STOPPED;
3111 }
3112 } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {
3113 str = STR_VEHICLE_STATUS_TRAIN_STUCK;
3114 } else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) {
3115 str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
3116 } else if (v->IsInDepot() && v->IsWaitingForUnbunching()) {
3117 str = STR_VEHICLE_STATUS_WAITING_UNBUNCHING;
3118 } else { // vehicle is in a "normal" state, show current order
3119 if (mouse_over_start_stop) {
3120 if (v->vehstatus & VS_STOPPED) {
3121 text_colour = TC_RED | TC_FORCED;
3122 } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {
3123 text_colour = TC_ORANGE | TC_FORCED;
3124 }
3125 }
3126 switch (v->current_order.GetType()) {
3127 case OT_GOTO_STATION: {
3128 SetDParam(0, v->current_order.GetDestination());
3129 SetDParam(1, PackVelocity(v->GetDisplaySpeed(), v->type));
3130 str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_STATION_VEL : STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL;
3131 break;
3132 }
3133
3134 case OT_GOTO_DEPOT: {
3135 SetDParam(0, v->type);
3136 SetDParam(1, v->current_order.GetDestination());
3137 SetDParam(2, PackVelocity(v->GetDisplaySpeed(), v->type));
3138 if (v->current_order.GetDestination() == INVALID_DEPOT) {
3139 /* This case *only* happens when multiple nearest depot orders
3140 * follow each other (including an order list only one order: a
3141 * nearest depot order) and there are no reachable depots.
3142 * It is primarily to guard for the case that there is no
3143 * depot with index 0, which would be used as fallback for
3144 * evaluating the string in the status bar. */
3145 str = STR_EMPTY;
3146 } else if (v->current_order.GetDepotActionType() & ODATFB_HALT) {
3147 str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_DEPOT_VEL : STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL;
3148 } else if (v->current_order.GetDepotActionType() & ODATFB_UNBUNCH) {
3149 str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_DEPOT_SERVICE_VEL : STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_UNBUNCH_VEL;
3150 } else {
3151 str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_DEPOT_SERVICE_VEL : STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL;
3152 }
3153 break;
3154 }
3155
3156 case OT_LOADING:
3157 str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
3158 break;
3159
3160 case OT_GOTO_WAYPOINT: {
3161 assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
3162 SetDParam(0, v->current_order.GetDestination());
3163 str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_WAYPOINT_VEL : STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL;
3164 SetDParam(1, PackVelocity(v->GetDisplaySpeed(), v->type));
3165 break;
3166 }
3167
3168 case OT_LEAVESTATION:
3169 if (v->type != VEH_AIRCRAFT) {
3170 str = STR_VEHICLE_STATUS_LEAVING;
3171 break;
3172 }
3173 [[fallthrough]];
3174 default:
3175 if (v->GetNumManualOrders() == 0) {
3176 str = STR_VEHICLE_STATUS_NO_ORDERS_VEL;
3177 SetDParam(0, PackVelocity(v->GetDisplaySpeed(), v->type));
3178 } else {
3179 str = STR_EMPTY;
3180 }
3181 break;
3182 }
3183 }
3184
3185 /* Draw the flag plus orders. */
3186 bool rtl = (_current_text_dir == TD_RTL);
3187 uint icon_width = std::max({GetScaledSpriteSize(SPR_WARNING_SIGN).width, GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING).width});
3188 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
3189 SpriteID image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : (HasBit(v->vehicle_flags, VF_PATHFINDER_LOST)) ? SPR_WARNING_SIGN : SPR_FLAG_VEH_RUNNING;
3190 DrawSpriteIgnorePadding(image, PAL_NONE, tr.WithWidth(icon_width, rtl), SA_CENTER);
3191 tr = tr.Indent(icon_width + WidgetDimensions::scaled.imgbtn.Horizontal(), rtl);
3192 DrawString(tr.left, tr.right, CenterBounds(tr.top, tr.bottom, GetCharacterHeight(FS_NORMAL)), str, text_colour, SA_HOR_CENTER);
3193 }
3194
3195 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
3196 {
3197 const Vehicle *v = Vehicle::Get(this->window_number);
3198
3199 switch (widget) {
3200 case WID_VV_RENAME: { // rename
3201 SetDParam(0, v->index);
3202 ShowQueryString(STR_VEHICLE_NAME, STR_QUERY_RENAME_TRAIN_CAPTION + v->type,
3203 MAX_LENGTH_VEHICLE_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
3204 break;
3205 }
3206
3207 case WID_VV_START_STOP: // start stop
3208 StartStopVehicle(v, false);
3209 break;
3210
3211 case WID_VV_ORDER_LOCATION: {
3212 /* Scroll to current order destination */
3213 TileIndex tile = v->current_order.GetLocation(v);
3214 if (tile == INVALID_TILE) break;
3215
3216 if (_ctrl_pressed) {
3217 ShowExtraViewportWindow(tile);
3218 } else {
3219 ScrollMainWindowToTile(tile);
3220 }
3221 break;
3222 }
3223
3224 case WID_VV_LOCATION: // center main view
3225 if (_ctrl_pressed) {
3226 ShowExtraViewportWindow(TileVirtXY(v->x_pos, v->y_pos));
3227 } else {
3228 const Window *mainwindow = GetMainWindow();
3229 if (click_count > 1 && mainwindow->viewport->zoom <= ZOOM_LVL_OUT_4X) {
3230 /* main window 'follows' vehicle */
3231 mainwindow->viewport->follow_vehicle = v->index;
3232 } else {
3233 ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos);
3234 }
3235 }
3236 break;
3237
3238 case WID_VV_GOTO_DEPOT: // goto hangar
3239 Command<CMD_SEND_VEHICLE_TO_DEPOT>::Post(GetCmdSendToDepotMsg(v), v->index, _ctrl_pressed ? DepotCommand::Service : DepotCommand::None, {});
3240 break;
3241 case WID_VV_REFIT: // refit
3242 ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID, this);
3243 break;
3244 case WID_VV_SHOW_ORDERS: // show orders
3245 if (_ctrl_pressed) {
3246 ShowTimetableWindow(v);
3247 } else {
3248 ShowOrdersWindow(v);
3249 }
3250 break;
3251 case WID_VV_SHOW_DETAILS: // show details
3252 if (_ctrl_pressed) {
3253 ShowCompanyGroupForVehicle(v);
3254 } else {
3255 ShowVehicleDetailsWindow(v);
3256 }
3257 break;
3258 case WID_VV_CLONE: // clone vehicle
3259 /* Suppress the vehicle GUI when share-cloning.
3260 * There is no point to it except for starting the vehicle.
3261 * For starting the vehicle the player has to open the depot GUI, which is
3262 * most likely already open, but is also visible in the vehicle viewport. */
3263 Command<CMD_CLONE_VEHICLE>::Post(_vehicle_msg_translation_table[VCT_CMD_CLONE_VEH][v->type],
3264 _ctrl_pressed ? nullptr : CcCloneVehicle,
3265 v->tile, v->index, _ctrl_pressed);
3266 break;
3267 case WID_VV_TURN_AROUND: // turn around
3268 assert(v->IsGroundVehicle());
3269 if (v->type == VEH_ROAD) {
3270 Command<CMD_TURN_ROADVEH>::Post(_vehicle_msg_translation_table[VCT_CMD_TURN_AROUND][v->type], v->tile, v->index);
3271 } else {
3272 Command<CMD_REVERSE_TRAIN_DIRECTION>::Post(_vehicle_msg_translation_table[VCT_CMD_TURN_AROUND][v->type], v->tile, v->index, false);
3273 }
3274 break;
3275 case WID_VV_FORCE_PROCEED: // force proceed
3276 assert(v->type == VEH_TRAIN);
3277 Command<CMD_FORCE_TRAIN_PROCEED>::Post(STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL, v->tile, v->index);
3278 break;
3279 }
3280 }
3281
3282 EventState OnHotkey(int hotkey) override
3283 {
3284 /* If the hotkey is not for any widget in the UI (i.e. for honking) */
3285 if (hotkey == WID_VV_HONK_HORN) {
3286 const Window *mainwindow = GetMainWindow();
3287 const Vehicle *v = Vehicle::Get(window_number);
3288 /* Only play the sound if we're following this vehicle */
3289 if (mainwindow->viewport->follow_vehicle == v->index) {
3290 v->PlayLeaveStationSound(true);
3291 }
3292 }
3293 return Window::OnHotkey(hotkey);
3294 }
3295
3296 void OnQueryTextFinished(char *str) override
3297 {
3298 if (str == nullptr) return;
3299
3300 Command<CMD_RENAME_VEHICLE>::Post(STR_ERROR_CAN_T_RENAME_TRAIN + Vehicle::Get(this->window_number)->type, this->window_number, str);
3301 }
3302
3303 void OnMouseOver([[maybe_unused]] Point pt, WidgetID widget) override
3304 {
3305 bool start_stop = widget == WID_VV_START_STOP;
3306 if (start_stop != mouse_over_start_stop) {
3307 mouse_over_start_stop = start_stop;
3308 this->SetWidgetDirty(WID_VV_START_STOP);
3309 }
3310 }
3311
3312 void OnResize() override
3313 {
3314 if (this->viewport != nullptr) {
3315 NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT);
3316 nvp->UpdateViewportCoordinates(this);
3317 }
3318 }
3319
3320 void UpdateButtonStatus()
3321 {
3322 const Vehicle *v = Vehicle::Get(this->window_number);
3323 bool veh_stopped = v->IsStoppedInDepot();
3324
3325 /* Widget WID_VV_GOTO_DEPOT must be hidden if the vehicle is already stopped in depot.
3326 * Widget WID_VV_CLONE_VEH should then be shown, since cloning is allowed only while in depot and stopped.
3327 */
3328 PlaneSelections plane = veh_stopped ? SEL_DC_CLONE : SEL_DC_GOTO_DEPOT;
3329 NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE); // Selection widget 'send to depot' / 'clone'.
3330 if (nwi->shown_plane + SEL_DC_BASEPLANE != plane) {
3331 this->SelectPlane(plane);
3332 this->SetWidgetDirty(WID_VV_SELECT_DEPOT_CLONE);
3333 }
3334 /* The same system applies to widget WID_VV_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
3335 if (v->IsGroundVehicle()) {
3336 plane = veh_stopped ? SEL_RT_REFIT : SEL_RT_TURN_AROUND;
3337 nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN);
3338 if (nwi->shown_plane + SEL_RT_BASEPLANE != plane) {
3339 this->SelectPlane(plane);
3340 this->SetWidgetDirty(WID_VV_SELECT_REFIT_TURN);
3341 }
3342 }
3343 }
3344
3350 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
3351 {
3352 if (data == VIWD_AUTOREPLACE) {
3353 /* Autoreplace replaced the vehicle.
3354 * Nothing to do for this window. */
3355 return;
3356 }
3357
3358 this->UpdateButtonStatus();
3359 }
3360
3361 bool IsNewGRFInspectable() const override
3362 {
3363 return ::IsNewGRFInspectable(GetGrfSpecFeature(Vehicle::Get(this->window_number)->type), this->window_number);
3364 }
3365
3366 void ShowNewGRFInspectWindow() const override
3367 {
3368 ::ShowNewGRFInspectWindow(GetGrfSpecFeature(Vehicle::Get(this->window_number)->type), this->window_number);
3369 }
3370
3371 static inline HotkeyList hotkeys{"vehicleview", {
3372 Hotkey('H', "honk", WID_VV_HONK_HORN),
3373 }};
3374 };
3375
3377 static WindowDesc _vehicle_view_desc(__FILE__, __LINE__,
3378 WDP_AUTO, "view_vehicle", 250, 116,
3379 WC_VEHICLE_VIEW, WC_NONE,
3380 0,
3381 std::begin(_nested_vehicle_view_widgets), std::end(_nested_vehicle_view_widgets),
3382 &VehicleViewWindow::hotkeys
3383 );
3384
3389 static WindowDesc _train_view_desc(__FILE__, __LINE__,
3390 WDP_AUTO, "view_vehicle_train", 250, 134,
3391 WC_VEHICLE_VIEW, WC_NONE,
3392 0,
3393 std::begin(_nested_vehicle_view_widgets), std::end(_nested_vehicle_view_widgets),
3394 &VehicleViewWindow::hotkeys
3395 );
3396
3398 void ShowVehicleViewWindow(const Vehicle *v)
3399 {
3400 AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
3401 }
3402
3408 bool VehicleClicked(const Vehicle *v)
3409 {
3410 assert(v != nullptr);
3411 if (!(_thd.place_mode & HT_VEHICLE)) return false;
3412
3413 v = v->First();
3414 if (!v->IsPrimaryVehicle()) return false;
3415
3416 return _thd.GetCallbackWnd()->OnVehicleSelect(v);
3417 }
3418
3425 bool VehicleClicked(VehicleList::const_iterator begin, VehicleList::const_iterator end)
3426 {
3427 assert(begin != end);
3428 if (!(_thd.place_mode & HT_VEHICLE)) return false;
3429
3430 /* If there is only one vehicle in the group, act as if we clicked a single vehicle */
3431 if (begin + 1 == end) return _thd.GetCallbackWnd()->OnVehicleSelect(*begin);
3432
3433 return _thd.GetCallbackWnd()->OnVehicleSelect(begin, end);
3434 }
3435
3441 bool VehicleClicked(const GUIVehicleGroup &vehgroup)
3442 {
3443 return VehicleClicked(vehgroup.vehicles_begin, vehgroup.vehicles_end);
3444 }
3445
3446 void StopGlobalFollowVehicle(const Vehicle *v)
3447 {
3448 Window *w = GetMainWindow();
3449 if (w->viewport->follow_vehicle == v->index) {
3450 ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos, true); // lock the main view on the vehicle's last position
3451 w->viewport->follow_vehicle = INVALID_VEHICLE;
3452 }
3453 }
3454
3455
3461 void CcBuildPrimaryVehicle(Commands, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray)
3462 {
3463 if (result.Failed()) return;
3464
3465 const Vehicle *v = Vehicle::Get(new_veh_id);
3466 ShowVehicleViewWindow(v);
3467 }
3468
3474 int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
3475 {
3476 switch (v->type) {
3477 case VEH_TRAIN:
3478 return Train::From(v)->GetDisplayImageWidth();
3479
3480 case VEH_ROAD:
3481 return RoadVehicle::From(v)->GetDisplayImageWidth();
3482
3483 default:
3484 bool rtl = _current_text_dir == TD_RTL;
3485 VehicleSpriteSeq seq;
3486 v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
3487 Rect rec;
3488 seq.GetBounds(&rec);
3489 return UnScaleGUI(rec.Width());
3490 }
3491 }
3492
3498 int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
3499 {
3500 if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
3501 int vehicle_width = 0;
3502 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
3503 vehicle_width += GetSingleVehicleWidth(u, image_type);
3504 }
3505 return vehicle_width;
3506 } else {
3507 return GetSingleVehicleWidth(v, image_type);
3508 }
3509 }
3510
3516 void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
3517 {
3518 bool rtl = _current_text_dir == TD_RTL;
3519
3520 _cursor.sprite_count = 0;
3521 int total_width = 0;
3522 int y_offset = 0;
3523 bool rotor_seq = false; // Whether to draw the rotor of the vehicle in this step.
3524 bool is_ground_vehicle = v->IsGroundVehicle();
3525
3526 while (v != nullptr) {
3527 if (total_width >= ScaleSpriteTrad(2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH)) break;
3528
3529 PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
3530 VehicleSpriteSeq seq;
3531
3532 if (rotor_seq) {
3533 GetCustomRotorSprite(Aircraft::From(v), image_type, &seq);
3534 if (!seq.IsValid()) seq.Set(SPR_ROTOR_STOPPED);
3535 y_offset = -ScaleSpriteTrad(5);
3536 } else {
3537 v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
3538 }
3539
3540 if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
3541
3542 int x_offs = 0;
3543 if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset();
3544
3545 for (uint i = 0; i < seq.count; ++i) {
3546 PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
3547 _cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
3548 _cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
3549 _cursor.sprite_pos[_cursor.sprite_count].x = rtl ? (-total_width + x_offs) : (total_width + x_offs);
3550 _cursor.sprite_pos[_cursor.sprite_count].y = y_offset;
3551 _cursor.sprite_count++;
3552 }
3553
3554 if (v->type == VEH_AIRCRAFT && v->subtype == AIR_HELICOPTER && !rotor_seq) {
3555 /* Draw rotor part in the next step. */
3556 rotor_seq = true;
3557 } else {
3558 total_width += GetSingleVehicleWidth(v, image_type);
3559 v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr;
3560 }
3561 }
3562
3563 if (is_ground_vehicle) {
3564 /* Center trains and road vehicles on the front vehicle */
3565 int offs = (ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2;
3566 if (rtl) offs = -offs;
3567 for (uint i = 0; i < _cursor.sprite_count; ++i) {
3568 _cursor.sprite_pos[i].x += offs;
3569 }
3570 }
3571
3572 UpdateCursorSize();
3573 }
SZSP_NONE
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:469
VEH_AIRCRAFT
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
Train::GetDisplayImageWidth
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:460
IsVehicleRefitable
static bool IsVehicleRefitable(const Vehicle *v)
Checks whether the vehicle may be refitted at the moment.
Definition: vehicle_gui.cpp:2917
VehicleListType
VehicleListType
Vehicle List type flags.
Definition: vehiclelist.h:18
VehicleDetailsWindow::DrawVehicleDetails
static void DrawVehicleDetails(const Vehicle *v, const Rect &r, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the position of the Details windows.
Definition: vehicle_gui.cpp:2526
Vehicle::GetGroundVehicleCache
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition: vehicle.cpp:3131
Vehicle::IsChainInDepot
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:550
TC_FORCED
@ TC_FORCED
Ignore colour changes from strings.
Definition: gfx_type.h:278
VehicleListWindow::BP_HIDE_BUTTONS
@ BP_HIDE_BUTTONS
Show the empty panel.
Definition: vehicle_gui.cpp:1849
SetFill
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition: widget_type.h:1143
WID_VV_SELECT_DEPOT_CLONE
@ WID_VV_SELECT_DEPOT_CLONE
Selection widget between 'goto depot', and 'clone vehicle' buttons.
Definition: vehicle_widget.h:26
VehicleViewWindow::OnPaint
void OnPaint() override
The window must be repainted.
Definition: vehicle_gui.cpp:3053
VehicleViewWindow::SEL_RT_TURN_AROUND
@ SEL_RT_TURN_AROUND
Display 'turn around' button in WID_VV_SELECT_REFIT_TURN stacked widget.
Definition: vehicle_gui.cpp:2937
VehicleOrderID
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:15
CountDigitsForAllocatingSpace
uint CountDigitsForAllocatingSpace(uint number)
Get the number of digits of space required for the given number.
Definition: vehicle_gui.cpp:193
VehicleGroupLengthSorter
static bool VehicleGroupLengthSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
Sort vehicle groups by the number of vehicles in the group.
Definition: vehicle_gui.cpp:1341
Window::OnVehicleSelect
virtual bool OnVehicleSelect([[maybe_unused]] const struct Vehicle *v)
The user clicked on a vehicle while HT_VEHICLE has been set.
Definition: window_gui.h:796
WC_INVALID
@ WC_INVALID
Invalid window.
Definition: window_type.h:719
BaseVehicleListWindow::SetCargoFilter
void SetCargoFilter(byte index)
Set cargo filter for the vehicle group list.
Definition: vehicle_gui.cpp:344
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition: bitmath_func.hpp:121
Order::IsType
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:71
order_cmd.h
VehicleList
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition: vehiclelist.h:54
Pool::PoolItem<&_vehicle_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
VehicleViewWindow::PlaneSelections
PlaneSelections
Display planes available in the vehicle view window.
Definition: vehicle_gui.cpp:2932
ScrollMainWindowToTile
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2509
VehicleListWindow::BP_SHOW_BUTTONS
@ BP_SHOW_BUTTONS
Show the buttons.
Definition: vehicle_gui.cpp:1848
VehicleDetailsWindow::GetRoadVehDetailsHeight
uint GetRoadVehDetailsHeight(const Vehicle *v)
Gets the desired height for the road vehicle details panel.
Definition: vehicle_gui.cpp:2402
TDW_TAB_CAPACITY
@ TDW_TAB_CAPACITY
Tab with cargo capacity of the vehicles.
Definition: vehicle_gui.h:28
ShowExtraViewportWindow
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
Definition: viewport_gui.cpp:156
HotkeyList
List of hotkeys for a window.
Definition: hotkeys.h:37
GUISettings::show_cargo_in_vehicle_lists
bool show_cargo_in_vehicle_lists
Show the cargoes the vehicles can carry in the list windows.
Definition: settings_type.h:199
WID_VD_DETAILS_TOTAL_CARGO
@ WID_VD_DETAILS_TOTAL_CARGO
Show the capacity and carried cargo amounts aggregated per cargo of the train.
Definition: vehicle_widget.h:60
VehicleListIdentifier::company
CompanyID company
The company associated with this list.
Definition: vehiclelist.h:31
Vehicle::GetNumManualOrders
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:740
WID_VD_CAPTION
@ WID_VD_CAPTION
Caption of window.
Definition: vehicle_widget.h:48
Vehicle::value
Money value
Value of the vehicle.
Definition: vehicle_base.h:271
train.h
DrawVehicleRefitWindow
static void DrawVehicleRefitWindow(const RefitOptions &refits, const RefitOption *sel, uint pos, uint rows, uint delta, const Rect &r)
Draw the list of available refit options for a consist and highlight the selected refit option (if an...
Definition: vehicle_gui.cpp:619
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition: geometry_type.hpp:30
command_func.h
VehicleViewWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition: vehicle_gui.cpp:3312
WidgetDimensions::scaled
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition: window_gui.h:68
RefitWindow::OnInvalidateData
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: vehicle_gui.cpp:1065
WWT_STICKYBOX
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:68
CursorVars::sprite_count
uint sprite_count
number of sprites to draw
Definition: gfx_type.h:130
BaseVehicleListWindow::BuildActionDropdownList
DropDownList BuildActionDropdownList(bool show_autoreplace, bool show_group, bool show_create)
Display the Action dropdown window.
Definition: vehicle_gui.cpp:453
Pool::PoolItem<&_vehicle_pool >::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
WDF_CONSTRUCTION
@ WDF_CONSTRUCTION
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:197
RefitWindow::click_x
int click_x
Position of the first click while dragging.
Definition: vehicle_gui.cpp:686
dropdown_func.h
GetRailTypeInfo
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:307
GUIList::SetFilterState
void SetFilterState(bool state)
Enable or disable the filter.
Definition: sortlist_type.h:327
Rect::Shrink
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Definition: geometry_type.hpp:98
BaseVehicleListWindow::grouping
GroupBy grouping
How we want to group the list.
Definition: vehicle_gui_base.h:76
VehicleGroupTotalProfitThisYearSorter
static bool VehicleGroupTotalProfitThisYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
Sort vehicle groups by the total profit this year.
Definition: vehicle_gui.cpp:1347
VehicleListIdentifier
The information about a vehicle list.
Definition: vehiclelist.h:28
Vehicle::cargo_cap
uint16_t cargo_cap
total capacity
Definition: vehicle_base.h:339
CBID_VEHICLE_CARGO_SUFFIX
@ CBID_VEHICLE_CARGO_SUFFIX
Determine the cargo "suffixes" for each refit possibility of a cargo.
Definition: newgrf_callbacks.h:60
_sorted_cargo_specs
std::vector< const CargoSpec * > _sorted_cargo_specs
Cargo specifications sorted alphabetically by name.
Definition: cargotype.cpp:168
VehicleViewWindow::OnInvalidateData
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: vehicle_gui.cpp:3350
company_base.h
Vehicle::Next
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:628
SpecializedVehicle::Next
T * Next() const
Get next vehicle in the chain.
Definition: vehicle_base.h:1121
NWID_HSCROLLBAR
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition: widget_type.h:85
RefitWindow::information_width
uint information_width
Width required for correctly displaying all cargoes in the information panel.
Definition: vehicle_gui.cpp:679
Vehicle::GetDisplayMaxSpeed
virtual int GetDisplayMaxSpeed() const
Gets the maximum speed in km-ish/h that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:526
NWidgetViewport
Nested widget to display a viewport in a window.
Definition: widget_type.h:666
WWT_CAPTION
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:63
Scrollbar::ScrollTowards
void ScrollTowards(int position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition: widget_type.h:823
Order::GetDestination
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:104
Window::SetWidgetDirty
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:552
RefitWindow::selected_vehicle
VehicleID selected_vehicle
First vehicle in the current selection.
Definition: vehicle_gui.cpp:687
BaseVehicleListWindow::order_arrow_width
uint order_arrow_width
Width of the arrow in the small order list.
Definition: vehicle_gui_base.h:85
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
DrawTrainDetails
void DrawTrainDetails(const Train *v, const Rect &r, int vscroll_pos, uint16_t vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the given position.
Definition: train_gui.cpp:352
VehicleDetailsWindow::VehicleDetailsWindow
VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number)
Initialize a newly created vehicle details window.
Definition: vehicle_gui.cpp:2361
VehicleSpriteSeq::Set
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition: vehicle_base.h:164
WF_DISABLE_VP_SCROLL
@ WF_DISABLE_VP_SCROLL
Window does not do autoscroll,.
Definition: window_gui.h:229
GroundVehicleCache::cached_weight
uint32_t cached_weight
Total weight of the consist (valid only for the first engine).
Definition: ground_vehicle.hpp:31
Window::viewport
ViewportData * viewport
Pointer to viewport data, if present.
Definition: window_gui.h:312
depot_cmd.h
WID_VR_INFO
@ WID_VR_INFO
Information about the currently selected refit option.
Definition: vehicle_widget.h:42
WID_VD_TOP_DETAILS
@ WID_VD_TOP_DETAILS
Panel with generic details.
Definition: vehicle_widget.h:49
CloseWindowById
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:1141
CargoFilterSingle
static bool CargoFilterSingle(const Vehicle *v, const CargoID cid)
Check whether a single vehicle should pass the filter.
Definition: vehicle_gui.cpp:284
DropDownList
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Definition: dropdown_type.h:210
VehicleListWindow::OnInvalidateData
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: vehicle_gui.cpp:2185
NWidgetCore::widget_data
uint32_t widget_data
Data of the widget.
Definition: widget_type.h:379
Vehicle::vehstatus
byte vehstatus
Status.
Definition: vehicle_base.h:349
BaseConsist::name
std::string name
Name of vehicle.
Definition: base_consist.h:18
WWT_DEFSIZEBOX
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition: widget_type.h:67
RefitWindow::OnPaint
void OnPaint() override
The window must be repainted.
Definition: vehicle_gui.cpp:888
group_gui.h
GB
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
GUISettings::advanced_vehicle_list
uint8_t advanced_vehicle_list
use the "advanced" vehicle list
Definition: settings_type.h:150
DrawShipDetails
void DrawShipDetails(const Vehicle *v, const Rect &r)
Draw the details for the given vehicle at the given position.
Definition: ship_gui.cpp:62
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
CargoSpec::Get
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:131
NWID_HORIZONTAL
@ NWID_HORIZONTAL
Horizontal container.
Definition: widget_type.h:77
Vehicle::GetGRFID
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:767
DrawRoadVehDetails
void DrawRoadVehDetails(const Vehicle *v, const Rect &r)
Draw the details for the given vehicle at the given position.
Definition: roadveh_gui.cpp:29
WID_VD_DETAILS_TRAIN_VEHICLES
@ WID_VD_DETAILS_TRAIN_VEHICLES
Show all parts of the train with their description.
Definition: vehicle_widget.h:58
CargoArray
Class for storing amounts of cargo.
Definition: cargo_type.h:114
PalSpriteID::sprite
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:23
Vehicle::group_id
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:358
maxdim
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Definition: geometry_func.cpp:22
Window::Close
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition: window.cpp:1048
RefitWindow::selected_refit
const RefitOption * selected_refit
Selected refit option.
Definition: vehicle_gui.cpp:676
WWT_MATRIX
@ WWT_MATRIX
Grid of rows and columns.
Definition: widget_type.h:61
FindWindowById
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1099
BaseVehicleListWindow::sorting
Listing * sorting
Pointer to the vehicle type related sorting.
Definition: vehicle_gui_base.h:79
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
RefitOption::subtype
byte subtype
Subcargo to use.
Definition: vehicle_gui.cpp:584
ShowCompanyGroup
void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type, GroupID group=INVALID_GROUP, bool need_existing_window=false)
Show the group window for the given company and vehicle type.
Definition: group_gui.cpp:1124
EndContainer
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition: widget_type.h:1153
BaseConsist::vehicle_flags
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:34
_vehicle_view_zoom_levels
static const ZoomLevel _vehicle_view_zoom_levels[]
Zoom levels for vehicle views indexed by vehicle type.
Definition: vehicle_gui.cpp:2847
VehicleViewWindow::SEL_DC_BASEPLANE
@ SEL_DC_BASEPLANE
First plane of the WID_VV_SELECT_DEPOT_CLONE stacked widget.
Definition: vehicle_gui.cpp:2939
SetMatrixDataTip
constexpr NWidgetPart SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1176
_ctrl_pressed
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:37
Vehicle::GetGRF
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:757
GetStringListWidth
uint GetStringListWidth(const StringID *list, FontSize fontsize)
Get maximum width of a list of strings.
Definition: gfx.cpp:871
BaseConsist::lateness_counter
TimerGameTick::Ticks lateness_counter
How many ticks late (or early if negative) this vehicle is.
Definition: base_consist.h:22
VehicleViewWindow::SelectPlane
void SelectPlane(PlaneSelections plane)
Display a plane in the window.
Definition: vehicle_gui.cpp:2948
VehicleCommandTranslation
VehicleCommandTranslation
Command indices for the _vehicle_command_translation_table.
Definition: vehicle_gui.cpp:2860
TextColour
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:253
GUIList::SetSortType
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
Definition: sortlist_type.h:124
zoom_func.h
WID_VV_START_STOP
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
Definition: vehicle_widget.h:17
autoreplace_gui.h
aircraft.h
Scrollbar::SetCapacityFromWidget
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:2341
GetUnitNumberDigits
uint GetUnitNumberDigits(VehicleList &vehicles)
Get the number of digits the biggest unit number of a set of vehicles has.
Definition: vehicle_gui.cpp:212
StrNaturalCompare
int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:585
GUIVehicleGroup::vehicles_begin
VehicleList::const_iterator vehicles_begin
Pointer to beginning element of this vehicle group.
Definition: vehicle_gui_base.h:25
ZoomLevel
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:19
VehicleDetailsWindow::tab
TrainDetailsWindowTabs tab
For train vehicles: which tab is displayed.
Definition: vehicle_gui.cpp:2357
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:54
ChangeVehicleViewWindow
void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
Report a change in vehicle IDs (due to autoreplace) to affected vehicle windows.
Definition: vehicle_gui.cpp:1527
EIT_IN_DETAILS
@ EIT_IN_DETAILS
Vehicle drawn in vehicle details, refit window, ...
Definition: vehicle_type.h:88
WindowDesc::cls
WindowClass cls
Class of the window,.
Definition: window_gui.h:164
WID_VL_CAPTION_SELECTION
@ WID_VL_CAPTION_SELECTION
Selection for caption.
Definition: vehicle_widget.h:67
CargoSpec
Specification of a cargo type.
Definition: cargotype.h:68
SZSP_HORIZONTAL
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:468
WC_VEHICLE_TIMETABLE
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers:
Definition: window_type.h:224
TimerGameEconomy::UsingWallclockUnits
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
Definition: timer_game_economy.cpp:97
newgrf_debug.h
RectPadding::Vertical
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Definition: geometry_type.hpp:69
Window::owner
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition: window_gui.h:310
WWT_PUSHARROWBTN
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:112
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
DIR_W
@ DIR_W
West.
Definition: direction_type.h:32
WID_VD_DETAILS_CAPACITY_OF_EACH
@ WID_VD_DETAILS_CAPACITY_OF_EACH
Show the capacity of all train parts.
Definition: vehicle_widget.h:59
Vehicle::GetNextArticulatedPart
Vehicle * GetNextArticulatedPart() const
Get the next part of an articulated engine.
Definition: vehicle_base.h:964
NWidgetCore::tool_tip
StringID tool_tip
Tooltip of the widget.
Definition: widget_type.h:380
Rect::Expand
Rect Expand(int s) const
Copy and expand Rect by s pixels.
Definition: geometry_type.hpp:153
EngineImageType
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:85
ScaleZoomGUI
ZoomLevel ScaleZoomGUI(ZoomLevel value)
Scale zoom level relative to GUI zoom.
Definition: zoom_func.h:87
CBM_VEHICLE_CARGO_SUFFIX
@ CBM_VEHICLE_CARGO_SUFFIX
Show suffix after cargo name.
Definition: newgrf_callbacks.h:300
TDW_TAB_INFO
@ TDW_TAB_INFO
Tab with name and value of the vehicles.
Definition: vehicle_gui.h:27
Engine
Definition: engine_base.h:37
WID_VR_HSCROLLBAR
@ WID_VR_HSCROLLBAR
Horizontal scrollbar or the vehicle display.
Definition: vehicle_widget.h:38
VEH_ROAD
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
CC_PASSENGERS
@ CC_PASSENGERS
Passengers.
Definition: cargotype.h:50
Vehicle
Vehicle data structure.
Definition: vehicle_base.h:240
Vehicle::IsPrimaryVehicle
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:473
WID_VD_SCROLLBAR
@ WID_VD_SCROLLBAR
Scrollbar for train details.
Definition: vehicle_widget.h:56
Vehicle::owner
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:305
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
VehicleGroupTotalProfitLastYearSorter
static bool VehicleGroupTotalProfitLastYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
Sort vehicle groups by the total profit last year.
Definition: vehicle_gui.cpp:1353
GetVehicleSet
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:3194
Scrollbar
Scrollbar data structure.
Definition: widget_type.h:680
Window::GetScrollbar
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:315
WID_VV_SHOW_ORDERS
@ WID_VV_SHOW_ORDERS
Show the orders of this vehicle.
Definition: vehicle_widget.h:23
Vehicle::IsInDepot
virtual bool IsInDepot() const
Check whether the vehicle is in the depot.
Definition: vehicle_base.h:544
PaletteID
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:18
WID_VL_SORT_BY_PULLDOWN
@ WID_VL_SORT_BY_PULLDOWN
Sort by dropdown list.
Definition: vehicle_widget.h:72
Window::OnHotkey
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition: window.cpp:566
ShowTimetableWindow
void ShowTimetableWindow(const Vehicle *v)
Show the timetable for a given vehicle.
Definition: timetable_gui.cpp:866
NEW_GROUP
static const GroupID NEW_GROUP
Sentinel for a to-be-created group.
Definition: group_type.h:15
Vehicle::IsGroundVehicle
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:511
VehicleAgeSorter
static bool VehicleAgeSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their age.
Definition: vehicle_gui.cpp:1398
Rect::WithHeight
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Definition: geometry_type.hpp:211
CursorVars::sprite_pos
Point sprite_pos[16]
relative position of individual sprites
Definition: gfx_type.h:129
VehicleListWindow
Window for the (old) vehicle listing.
Definition: vehicle_gui.cpp:1844
NWidgetPart
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:1040
_nontrain_vehicle_details_desc
static WindowDesc _nontrain_vehicle_details_desc(__FILE__, __LINE__, WDP_AUTO, "view_vehicle_details", 405, 113, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, std::begin(_nested_nontrain_vehicle_details_widgets), std::end(_nested_nontrain_vehicle_details_widgets))
Vehicle details window descriptor for other vehicles than a train.
GUIList::NeedRebuild
bool NeedRebuild() const
Check if a rebuild is needed.
Definition: sortlist_type.h:387
Scrollbar::GetPosition
uint16_t GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:722
GetVehicleHeight
uint GetVehicleHeight(VehicleType type)
Get the height of a single vehicle in the GUIs.
Definition: vehicle_gui.h:74
Vehicle::breakdowns_since_last_service
byte breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:297
ODATFB_UNBUNCH
@ ODATFB_UNBUNCH
Service the vehicle and then unbunch it.
Definition: order_type.h:106
VehicleDetailsWindow::OnInvalidateData
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: vehicle_gui.cpp:2378
RefitWindow::sprite_left
int sprite_left
Left position of the vehicle sprite.
Definition: vehicle_gui.cpp:683
WID_VL_ORDER_VIEW
@ WID_VL_ORDER_VIEW
Button to open order window (for shared orders windows).
Definition: vehicle_widget.h:68
VehicleDetailsWindow::IsVehicleServiceIntervalEnabled
static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
Checks whether service interval is enabled for the vehicle.
Definition: vehicle_gui.cpp:2505
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
_colour_gradient
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: palette.cpp:26
WID_VD_SERVICE_INTERVAL_DROPDOWN
@ WID_VD_SERVICE_INTERVAL_DROPDOWN
Dropdown to select default/days/percent service interval.
Definition: vehicle_widget.h:52
textbuf_gui.h
Vehicle::x_pos
int32_t x_pos
x coordinate.
Definition: vehicle_base.h:300
train_cmd.h
RefitWindow::auto_refit
bool auto_refit
Select cargo for auto-refitting.
Definition: vehicle_gui.cpp:689
QSF_LEN_IN_CHARS
@ QSF_LEN_IN_CHARS
the length of the string is counted in characters
Definition: textbuf_gui.h:22
Vehicle::IsArticulatedPart
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:945
VehicleListWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition: vehicle_gui.cpp:2175
BaseVehicleListWindow::SetCargoFilterArray
void SetCargoFilterArray()
Populate the filter list and set the cargo filter criteria.
Definition: vehicle_gui.cpp:358
Order::GetType
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:77
BaseVehicleListWindow::OnInit
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: vehicle_gui.cpp:404
DepotCommand::Service
@ Service
The vehicle will leave the depot right after arrival (service only)
Aircraft
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
WID_VR_REFIT
@ WID_VR_REFIT
Perform the refit.
Definition: vehicle_widget.h:43
UpdateCursorSize
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1617
ALL_GROUP
static const GroupID ALL_GROUP
All vehicles are in this group.
Definition: group_type.h:16
WID_VL_GROUP_BY_PULLDOWN
@ WID_VL_GROUP_BY_PULLDOWN
Group by dropdown list.
Definition: vehicle_widget.h:70
WID_VV_VIEWPORT
@ WID_VV_VIEWPORT
Viewport widget.
Definition: vehicle_widget.h:16
WindowDesc
High level window description.
Definition: window_gui.h:153
WidgetID
int WidgetID
Widget ID.
Definition: window_type.h:18
WID_VV_LOCATION
@ WID_VV_LOCATION
Center the main view on this vehicle.
Definition: vehicle_widget.h:19
GetGrfSpecFeature
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
Definition: newgrf_debug_gui.cpp:773
RectPadding::Horizontal
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
Definition: geometry_type.hpp:63
Vehicle::date_of_last_service
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
Definition: vehicle_base.h:291
WID_VR_SHOW_HSCROLLBAR
@ WID_VR_SHOW_HSCROLLBAR
Selection widget for the horizontal scrollbar.
Definition: vehicle_widget.h:37
Vehicle::GetImage
virtual void GetImage([[maybe_unused]] Direction direction, [[maybe_unused]] EngineImageType image_type, [[maybe_unused]] VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Definition: vehicle_base.h:482
BaseVehicleListWindow::FilterVehicleList
void FilterVehicleList()
Filter the engine list against the currently selected cargo filter.
Definition: vehicle_gui.cpp:368
include
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
Definition: container_func.hpp:24
ScaleGUITrad
int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:117
Vehicle::GetDisplayRunningCost
Money GetDisplayRunningCost() const
Gets the running cost of a vehicle that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:607
VehicleSettings::train_acceleration_model
uint8_t train_acceleration_model
realistic acceleration for trains
Definition: settings_type.h:517
VehicleCache::cached_max_speed
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:124
GetServiceIntervalClamped
uint16_t GetServiceIntervalClamped(int interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1909
WID_VD_MATRIX
@ WID_VD_MATRIX
List of details for trains.
Definition: vehicle_widget.h:55
SetPadding
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1190
ShowVehicleDetailsWindow
static void ShowVehicleDetailsWindow(const Vehicle *v)
Shows the vehicle details window of the given vehicle.
Definition: vehicle_gui.cpp:2786
Vehicle::breakdown_ctr
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:295
BaseVehicleListWindow::vli
VehicleListIdentifier vli
Identifier of the vehicle list we want to currently show.
Definition: vehicle_gui_base.h:82
VehicleSpriteSeq::IsValid
bool IsValid() const
Check whether the sequence contains any sprites.
Definition: vehicle_base.h:148
SetResize
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition: widget_type.h:1088
EF_AUTO_REFIT
@ EF_AUTO_REFIT
Automatic refitting is allowed.
Definition: engine_type.h:173
Vehicle::GetDisplayProfitThisYear
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition: vehicle_base.h:613
GUIList::NeedResort
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0.
Definition: sortlist_type.h:220
EngineInfo::callback_mask
uint16_t callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:156
WDP_AUTO
@ WDP_AUTO
Find a place automatically.
Definition: window_gui.h:141
Vehicle::GetDisplaySpeed
virtual int GetDisplaySpeed() const
Gets the speed in km-ish/h that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:520
GroundVehicleCache
Cached, frequently calculated values.
Definition: ground_vehicle.hpp:29
timetable.h
WID_VL_MANAGE_VEHICLES_DROPDOWN
@ WID_VL_MANAGE_VEHICLES_DROPDOWN
Manage vehicles dropdown list.
Definition: vehicle_widget.h:79
TimerGameConst< struct Calendar >::DAYS_IN_LEAP_YEAR
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: timer_game_common.h:150
WWT_PUSHBTN
@ WWT_PUSHBTN
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:109
Window::resize
ResizeInfo resize
Resize information.
Definition: window_gui.h:308
CommandCost
Common return value for all commands.
Definition: command_type.h:23
WID_VD_MIDDLE_DETAILS
@ WID_VD_MIDDLE_DETAILS
Details for non-trains.
Definition: vehicle_widget.h:54
VehicleListWindow::OnPaint
void OnPaint() override
The window must be repainted.
Definition: vehicle_gui.cpp:2005
CcStartStopVehicle
void CcStartStopVehicle(Commands, const CommandCost &result, VehicleID veh_id, bool)
This is the Callback method after attempting to start/stop a vehicle.
Definition: vehicle_gui.cpp:2893
VRF_TRAIN_STUCK
@ VRF_TRAIN_STUCK
Train can't get a path reservation.
Definition: train.h:32
VehicleViewWindow::SEL_DC_GOTO_DEPOT
@ SEL_DC_GOTO_DEPOT
Display 'goto depot' button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
Definition: vehicle_gui.cpp:2933
WidgetDimensions::matrix
RectPadding matrix
Padding of WWT_MATRIX items.
Definition: window_gui.h:44
WC_VEHICLE_VIEW
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:339
NWidgetViewport::UpdateViewportCoordinates
void UpdateViewportCoordinates(Window *w)
Update the position and size of the viewport (after eg a resize).
Definition: widget.cpp:2244
tilehighlight_func.h
WindowNumber
int32_t WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:732
GetUnionOfArticulatedRefitMasks
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
Definition: articulated_vehicles.cpp:251
FS_NORMAL
@ FS_NORMAL
Index of the normal font in the font tables.
Definition: gfx_type.h:203
Vehicle::IsWaitingForUnbunching
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition: vehicle.cpp:2537
StartStopVehicle
void StartStopVehicle(const Vehicle *v, bool texteffect)
Executes CMD_START_STOP_VEHICLE for given vehicle.
Definition: vehicle_gui.cpp:2910
Rect::Translate
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
Definition: geometry_type.hpp:174
INVALID_VEH_ORDER_ID
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:21
NWID_VIEWPORT
@ NWID_VIEWPORT
Nested widget containing a viewport.
Definition: widget_type.h:83
SetScrollbar
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1246
ShowCompanyGroupForVehicle
void ShowCompanyGroupForVehicle(const Vehicle *v)
Show the group window for the given vehicle.
Definition: group_gui.cpp:1143
CargoFilter
static bool CargoFilter(const GUIVehicleGroup *vehgroup, const CargoID cid)
Check whether a vehicle can carry a specific cargo.
Definition: vehicle_gui.cpp:324
GUIList::Filter
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
Definition: sortlist_type.h:343
VEH_COMPANY_END
@ VEH_COMPANY_END
Last company-ownable type.
Definition: vehicle_type.h:29
DIR_E
@ DIR_E
East.
Definition: direction_type.h:28
TileHighlightData::window_number
WindowNumber window_number
The WindowNumber of the window that is responsible for the selection mode.
Definition: tilehighlight_type.h:69
Window::height
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:306
RefitWindow::num_vehicles
uint8_t num_vehicles
Number of selected vehicles.
Definition: vehicle_gui.cpp:688
VehicleClicked
bool VehicleClicked(const Vehicle *v)
Dispatch a "vehicle selected" event if any window waits for it.
Definition: vehicle_gui.cpp:3408
VehicleModelSorter
static bool VehicleModelSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by model.
Definition: vehicle_gui.cpp:1452
Vehicle::tile
TileIndex tile
Current tile index.
Definition: vehicle_base.h:260
VehicleGroupAverageProfitLastYearSorter
static bool VehicleGroupAverageProfitLastYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
Sort vehicle groups by the average profit last year.
Definition: vehicle_gui.cpp:1365
BaseVehicleListWindow
Definition: vehicle_gui_base.h:67
VehicleProfitThisYearSorter
static bool VehicleProfitThisYearSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by this year profit.
Definition: vehicle_gui.cpp:1405
INVALID_VEHICLE
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
ZOOM_LVL_ROADVEH
@ ZOOM_LVL_ROADVEH
Default zoom level for the road vehicle view.
Definition: zoom_type.h:38
Window::SetDirty
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:941
WID_VL_FILTER_BY_CARGO
@ WID_VL_FILTER_BY_CARGO
Cargo filter dropdown list.
Definition: vehicle_widget.h:73
DepotCommand::MassSend
@ MassSend
Tells that it's a mass send to depot command (type in VLW flag)
Vehicle::engine_type
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:319
RefitOption::operator!=
bool operator!=(const RefitOption &other) const
Inequality operator for RefitOption.
Definition: vehicle_gui.cpp:592
VehicleListWindow::BP_NORMAL
@ BP_NORMAL
Show shared orders caption and buttons.
Definition: vehicle_gui.cpp:1854
WID_VD_DECREASE_SERVICING_INTERVAL
@ WID_VD_DECREASE_SERVICING_INTERVAL
Decrease the servicing interval.
Definition: vehicle_widget.h:51
GUIList::ForceResort
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Definition: sortlist_type.h:234
VS_CRASHED
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
FS_SMALL
@ FS_SMALL
Index of the small font in the font tables.
Definition: gfx_type.h:204
VehicleListIdentifier::index
uint32_t index
A vehicle list type specific index.
Definition: vehiclelist.h:32
VehicleSpriteSeq
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:131
SpecializedStation< Station, false >::IsExpected
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
Definition: base_station_base.h:240
VehicleMaxSpeedSorter
static bool VehicleMaxSpeedSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their max speed.
Definition: vehicle_gui.cpp:1445
CommandCost::Failed
bool Failed() const
Did this command fail?
Definition: command_type.h:171
WWT_PUSHTXTBTN
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:110
WID_VV_FORCE_PROCEED
@ WID_VV_FORCE_PROCEED
Force this vehicle to pass a signal at danger.
Definition: vehicle_widget.h:29
vehicle_gui_base.h
CargoFilterCriteria::CF_NONE
static constexpr CargoID CF_NONE
Show only items which do not carry cargo (e.g. train engines)
Definition: cargo_type.h:95
NWidgetBase
Baseclass for nested widgets.
Definition: widget_type.h:135
Vehicle::current_order
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:350
GUIList::ToggleSortOrder
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
Definition: sortlist_type.h:254
_cargo_mask
CargoTypes _cargo_mask
Bitmask of cargo types available.
Definition: cargotype.cpp:31
CcAddVehicleNewGroup
void CcAddVehicleNewGroup(Commands cmd, const CommandCost &result, GroupID new_group, GroupID, VehicleID veh_id, bool, const VehicleListIdentifier &)
Open rename window after adding a vehicle to a new group via drag and drop.
Definition: group_gui.cpp:1189
CcBuildPrimaryVehicle
void CcBuildPrimaryVehicle(Commands, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray)
This is the Callback method after the construction attempt of a primary vehicle.
Definition: vehicle_gui.cpp:3461
RefitWindow::vscroll
Scrollbar * vscroll
The main scrollbar.
Definition: vehicle_gui.cpp:680
SPR_CLONE_TRAIN
static const SpriteID SPR_CLONE_TRAIN
Clone vehicles stuff.
Definition: sprites.h:100
GetVehicleListHeight
uint GetVehicleListHeight(VehicleType type, uint divisor)
Get the height of a vehicle in the vehicle list GUIs.
Definition: vehicle_gui.cpp:1670
TimerGame< struct Calendar >::DateToYear
static constexpr Year DateToYear(Date date)
Calculate the year of a given date.
Definition: timer_game_common.h:77
VehicleListWindow::BP_SHARED_ORDERS
@ BP_SHARED_ORDERS
Show the normal caption.
Definition: vehicle_gui.cpp:1855
Vehicle::cur_speed
uint16_t cur_speed
current speed
Definition: vehicle_base.h:324
VehicleTimetableDelaySorter
static bool VehicleTimetableDelaySorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by the timetable delay.
Definition: vehicle_gui.cpp:1486
_vehicle_view_desc
static WindowDesc _vehicle_view_desc(__FILE__, __LINE__, WDP_AUTO, "view_vehicle", 250, 116, WC_VEHICLE_VIEW, WC_NONE, 0, std::begin(_nested_vehicle_view_widgets), std::end(_nested_vehicle_view_widgets), &VehicleViewWindow::hotkeys)
Vehicle view window descriptor for all vehicles but trains.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:55
RefitWindow::hscroll
Scrollbar * hscroll
Only used for long vehicles.
Definition: vehicle_gui.cpp:681
Window::ReInit
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:953
VehicleViewWindow::SEL_DC_CLONE
@ SEL_DC_CLONE
Display 'clone vehicle' button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
Definition: vehicle_gui.cpp:2934
VehicleListWindow::ButtonPlanes
ButtonPlanes
Enumeration of planes of the button row at the bottom.
Definition: vehicle_gui.cpp:1847
WC_VEHICLE_DETAILS
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition: window_type.h:200
VehicleViewWindow::ShowNewGRFInspectWindow
void ShowNewGRFInspectWindow() const override
Show the NewGRF inspection window.
Definition: vehicle_gui.cpp:3366
ZOOM_LVL_AIRCRAFT
@ ZOOM_LVL_AIRCRAFT
Default zoom level for the aircraft view.
Definition: zoom_type.h:35
VehicleListIdentifier::Pack
uint32_t Pack() const
Pack a VehicleListIdentifier in a single uint32.
Definition: vehiclelist.cpp:22
VS_STOPPED
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
Window::parent
Window * parent
Parent window.
Definition: window_gui.h:322
NWidget
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
Definition: widget_type.h:1260
GUIList::IsDescSortOrder
bool IsDescSortOrder() const
Check if the sort order is descending.
Definition: sortlist_type.h:244
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:50
Vehicle::GetEngine
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:747
BaseVehicleListWindow::BuildCargoDropDownList
DropDownList BuildCargoDropDownList(bool full) const
Build drop down list for cargo filter selection.
Definition: vehicle_gui.cpp:425
GenerateVehicleSortList
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
Definition: vehiclelist.cpp:114
safeguards.h
WID_VR_SCROLLBAR
@ WID_VR_SCROLLBAR
Scrollbar for the refit options.
Definition: vehicle_widget.h:41
ShowQueryString
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1087
Window::LowerWidget
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition: window_gui.h:460
Window::left
int left
x position of left edge of the window
Definition: window_gui.h:303
VehicleGroupAverageProfitThisYearSorter
static bool VehicleGroupAverageProfitThisYearSorter(const GUIVehicleGroup &a, const GUIVehicleGroup &b)
Sort vehicle groups by the average profit this year.
Definition: vehicle_gui.cpp:1359
Window::flags
WindowFlags flags
Window flags.
Definition: window_gui.h:294
Train
'Train' is either a loco or a wagon.
Definition: train.h:89
vehicle_cmd.h
DrawSmallOrderList
static void DrawSmallOrderList(const Order *order, int left, int right, int y, uint order_arrow_width)
Draw small order list in the vehicle GUI, but without the little black arrow.
Definition: vehicle_gui.cpp:1628
Rect::Indent
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
Definition: geometry_type.hpp:198
DEFAULT_GROUP
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:17
Vehicle::PlayLeaveStationSound
virtual void PlayLeaveStationSound([[maybe_unused]] bool force=false) const
Play the sound associated with leaving the station.
Definition: vehicle_base.h:468
WindowClass
WindowClass
Window classes.
Definition: window_type.h:44
SetMouseCursorVehicle
void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
Set the mouse cursor to look like a vehicle.
Definition: vehicle_gui.cpp:3516
VehicleDefaultSettings::servint_aircraft
uint16_t servint_aircraft
service interval for aircraft
Definition: settings_type.h:602
Rect::WithWidth
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Definition: geometry_type.hpp:185
WID_VV_CLONE
@ WID_VV_CLONE
Clone this vehicle.
Definition: vehicle_widget.h:25
VehicleListWindow::CaptionPlanes
CaptionPlanes
Enumeration of planes of the title row at the top.
Definition: vehicle_gui.cpp:1853
VehicleID
uint32_t VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
DrawSprite
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:1003
DrawAircraftDetails
void DrawAircraftDetails(const Aircraft *v, const Rect &r)
Draw the details for the given vehicle at the given position.
Definition: aircraft_gui.cpp:30
newgrf_text.h
ZOOM_LVL_SHIP
@ ZOOM_LVL_SHIP
Default zoom level for the ship view.
Definition: zoom_type.h:36
VehicleDefaultSettings
Default settings for vehicles.
Definition: settings_type.h:598
RefitWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition: vehicle_gui.cpp:1240
_nested_train_vehicle_details_widgets
static constexpr NWidgetPart _nested_train_vehicle_details_widgets[]
Train details widgets.
Definition: vehicle_gui.cpp:2299
CargoID
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
Point
Coordinates of a point in 2D.
Definition: geometry_type.hpp:21
ScrollMainWindowTo
bool ScrollMainWindowTo(int x, int y, int z, bool instant)
Scrolls the main window to given coordinates.
Definition: smallmap_gui.cpp:2007
VehicleViewWindow::SEL_RT_BASEPLANE
@ SEL_RT_BASEPLANE
First plane of the WID_VV_SELECT_REFIT_TURN stacked widget.
Definition: vehicle_gui.cpp:2940
WC_TRAINS_LIST
@ WC_TRAINS_LIST
Trains list; Window numbers:
Definition: window_type.h:308
TimerGameConst< struct Economy >::MAX_YEAR
static constexpr TimerGame< struct Economy >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
Definition: timer_game_common.h:173
GetSingleVehicleWidth
int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (part) in pixels.
Definition: vehicle_gui.cpp:3474
BaseVehicleListWindow::GetActionDropdownSize
Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group, bool show_create)
Compute the size for the Action dropdown.
Definition: vehicle_gui.cpp:386
CenterBounds
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition: gfx_func.h:166
Scrollbar::GetScrolledItemFromWidget
Tcontainer::iterator GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
Definition: widget_type.h:847
RefitWindow::sprite_right
int sprite_right
Right position of the vehicle sprite.
Definition: vehicle_gui.cpp:684
DrawRoadVehImage
void DrawRoadVehImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a road vehicle chain.
Definition: roadveh_gui.cpp:122
ShowDropDownMenu
void ShowDropDownMenu(Window *w, 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:406
WID_VD_INCREASE_SERVICING_INTERVAL
@ WID_VD_INCREASE_SERVICING_INTERVAL
Increase the servicing interval.
Definition: vehicle_widget.h:50
GetGRFStringID
StringID GetGRFStringID(uint32_t grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Definition: newgrf_text.cpp:587
stdafx.h
RefitWindow::refit_list
RefitOptions refit_list
List of refit subtypes available for each sorted cargo.
Definition: vehicle_gui.cpp:677
Window::window_number
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:296
VehicleType
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
WID_VL_SORT_ORDER
@ WID_VL_SORT_ORDER
Sort order.
Definition: vehicle_widget.h:71
ChangeVehicleWindow
static void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
Assign a vehicle window a new vehicle.
Definition: vehicle_gui.cpp:1504
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition: bitmath_func.hpp:243
GetDepotIndex
DepotID GetDepotIndex(Tile t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:52
VehicleValueSorter
static bool VehicleValueSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their value.
Definition: vehicle_gui.cpp:1459
RefitWindow::order
VehicleOrderID order
If not INVALID_VEH_ORDER_ID, selection is part of a refit order (rather than execute directly).
Definition: vehicle_gui.cpp:678
Window::InvalidateData
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition: window.cpp:3144
EngineInfo::misc_flags
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:155
CS_ALPHANUMERAL
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:25
viewport_func.h
WID_VD_SERVICING_INTERVAL
@ WID_VD_SERVICING_INTERVAL
Information about the servicing interval.
Definition: vehicle_widget.h:53
NWidgetBase::current_y
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:234
NWidgetStacked
Stacked widgets, widgets all occupying the same space in the window.
Definition: widget_type.h:484
WC_NONE
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:45
_nested_vehicle_view_widgets
static constexpr NWidgetPart _nested_vehicle_view_widgets[]
Vehicle view widgets.
Definition: vehicle_gui.cpp:2797
SA_HOR_CENTER
@ SA_HOR_CENTER
Horizontally center the text.
Definition: gfx_type.h:339
Window::SetWidgetLoweredState
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:441
RefitOption::string
StringID string
GRF-local String to display for the cargo.
Definition: vehicle_gui.cpp:585
VehicleViewWindow::SEL_RT_REFIT
@ SEL_RT_REFIT
Display 'refit' button in WID_VV_SELECT_REFIT_TURN stacked widget.
Definition: vehicle_gui.cpp:2936
WID_VV_SELECT_REFIT_TURN
@ WID_VV_SELECT_REFIT_TURN
Selection widget between 'refit' and 'turn around' buttons.
Definition: vehicle_widget.h:27
GetDigitWidth
byte GetDigitWidth(FontSize size)
Return the maximum width of single digit.
Definition: gfx.cpp:1259
ODATFB_HALT
@ ODATFB_HALT
Service the vehicle and then halt it.
Definition: order_type.h:104
WC_VEHICLE_REFIT
@ WC_VEHICLE_REFIT
Vehicle refit; Window numbers:
Definition: window_type.h:206
NWID_VERTICAL
@ NWID_VERTICAL
Vertical container.
Definition: widget_type.h:79
Vehicle::z_pos
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:302
BaseVehicleListWindow::cargo_filter_criteria
CargoID cargo_filter_criteria
Selected cargo filter index.
Definition: vehicle_gui_base.h:84
HT_VEHICLE
@ HT_VEHICLE
vehicle is accepted as target as well (bitmask)
Definition: tilehighlight_type.h:27
GetCargoSubtypeText
StringID GetCargoSubtypeText(const Vehicle *v)
Get the cargo subtype text from NewGRF for the vehicle details window.
Definition: vehicle_gui.cpp:1325
HT_DRAG
@ HT_DRAG
dragging items in the depot windows
Definition: tilehighlight_type.h:24
VIWD_CONSIST_CHANGED
@ VIWD_CONSIST_CHANGED
Vehicle composition was changed.
Definition: vehicle_gui.h:37
VehicleLengthSorter
static bool VehicleLengthSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their length.
Definition: vehicle_gui.cpp:1472
Scrollbar::GetScrolledRowFromWidget
int 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:2267
WidgetDimensions::unscaled
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition: window_gui.h:67
Window::SetWidgetDisabledState
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:381
group_cmd.h
WID_VL_LIST
@ WID_VL_LIST
List of the vehicles.
Definition: vehicle_widget.h:75
GetSpriteSize
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:937
WWT_CLOSEBOX
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition: widget_type.h:71
WWT_RESIZEBOX
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:70
VehicleSettings::roadveh_acceleration_model
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
Definition: settings_type.h:518
BaseConsist::cur_real_order_index
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:31
TileHighlightData::place_mode
HighLightStyle place_mode
Method which is used to place the selection.
Definition: tilehighlight_type.h:67
BaseVehicleListWindow::DrawVehicleListItems
void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
Draw all the vehicle list items.
Definition: vehicle_gui.cpp:1690
RefitOption::operator==
bool operator==(const RefitOption &other) const
Equality operator for RefitOption.
Definition: vehicle_gui.cpp:602
GUIList::ForceRebuild
void ForceRebuild()
Force that a rebuild is needed.
Definition: sortlist_type.h:395
WID_VR_CAPTION
@ WID_VR_CAPTION
Caption of window.
Definition: vehicle_widget.h:35
string_func.h
VAF_DEST_TOO_FAR
@ VAF_DEST_TOO_FAR
Next destination is too far away.
Definition: aircraft.h:39
spritecache.h
Vehicle::FirstShared
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:722
ToPercent16
constexpr uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:306
CALLBACK_FAILED
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
Definition: newgrf_callbacks.h:420
WWT_PUSHIMGBTN
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:111
SBS_DOWN
@ SBS_DOWN
Sort ascending.
Definition: window_gui.h:214
Vehicle::vcache
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:362
DrawStringMultiLine
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:771
EIT_IN_LIST
@ EIT_IN_LIST
Vehicle drawn in vehicle list, group list, ...
Definition: vehicle_type.h:89
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:51
Window::DrawSortButtonState
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition: widget.cpp:763
GuiShowTooltips
void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount)
Shows a tooltip.
Definition: misc_gui.cpp:758
vehicle_func.h
RefitWindow::RefreshScrollbar
void RefreshScrollbar()
Refresh scrollbar after selection changed.
Definition: vehicle_gui.cpp:816
VehicleDetailsWindow
Class for managing the vehicle details window.
Definition: vehicle_gui.cpp:2356
station_base.h
PALETTE_CRASH
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1602
GetVehicleWidth
int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (including all parts of the consist) in pixels.
Definition: vehicle_gui.cpp:3498
Window::CreateNestedTree
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1724
strings_func.h
NWID_VSCROLLBAR
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition: widget_type.h:86
Vehicle::First
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:641
Sorting
Definition: vehicle_gui_base.h:144
Vehicle::max_age
TimerGameCalendar::Date max_age
Maximum age.
Definition: vehicle_base.h:290
TimerGame< struct Economy >::DateAtStartOfYear
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
Definition: timer_game_common.h:88
RefitWindow::vehicle_margin
uint vehicle_margin
Margin to use while selecting vehicles when the vehicle image is centered.
Definition: vehicle_gui.cpp:685
Engine::CanCarryCargo
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition: engine.cpp:168
VehicleDetailsWindow::OnPaint
void OnPaint() override
Repaint vehicle details window.
Definition: vehicle_gui.cpp:2659
GUIVehicleGroup
Definition: vehicle_gui_base.h:24
MAX_LENGTH_VEHICLE_NAME_CHARS
static const uint MAX_LENGTH_VEHICLE_NAME_CHARS
The maximum length of a vehicle name in characters including '\0'.
Definition: vehicle_type.h:73
RoadVehicle::GetDisplayImageWidth
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a road vehicle image in the GUI.
Definition: roadveh_cmd.cpp:94
NWidgetBase::pos_x
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:236
GUIList::GetListing
Listing GetListing() const
Export current sort conditions.
Definition: sortlist_type.h:137
WID_VL_FILTER_BY_CARGO_SEL
@ WID_VL_FILTER_BY_CARGO_SEL
Cargo filter dropdown list panel selector.
Definition: vehicle_widget.h:74
TimerGameConst< struct Economy >::MONTHS_IN_YEAR
static constexpr int MONTHS_IN_YEAR
months per year
Definition: timer_game_common.h:151
BaseVehicleListWindow::vehgroups
GUIVehicleGroupList vehgroups
List of (groups of) vehicles. This stores iterators of vehicles, and should be rebuilt if vehicles is...
Definition: vehicle_gui_base.h:78
ShowReplaceGroupVehicleWindow
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
Definition: autoreplace_gui.cpp:916
Window::CloseChildWindows
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition: window.cpp:1036
SetDParamMaxValue
void SetDParamMaxValue(size_t n, uint64_t max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:127
SpecializedVehicle< Train, Type >::From
static Train * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Definition: vehicle_base.h:1206
GetVehiclePalette
PaletteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition: vehicle.cpp:2138
WID_VV_HONK_HORN
@ WID_VV_HONK_HORN
Honk the vehicles horn (not drawn on UI, only used for hotkey).
Definition: vehicle_widget.h:30
_train_view_desc
static WindowDesc _train_view_desc(__FILE__, __LINE__, WDP_AUTO, "view_vehicle_train", 250, 134, WC_VEHICLE_VIEW, WC_NONE, 0, std::begin(_nested_vehicle_view_widgets), std::end(_nested_vehicle_view_widgets), &VehicleViewWindow::hotkeys)
Vehicle view window descriptor for trains.
VehicleListIdentifier::vtype
VehicleType vtype
The vehicle type associated with this list.
Definition: vehiclelist.h:30
Vehicle::GetFirstEnginePart
Vehicle * GetFirstEnginePart()
Get the first part of an articulated engine.
Definition: vehicle_base.h:974
VIWD_AUTOREPLACE
@ VIWD_AUTOREPLACE
Autoreplace replaced the vehicle.
Definition: vehicle_gui.h:38
WID_VR_MATRIX
@ WID_VR_MATRIX
Options to refit to.
Definition: vehicle_widget.h:40
SetDParam
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
GetMainWindow
Window * GetMainWindow()
Get the main window, i.e.
Definition: window.cpp:1128
GetStationIndex
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
geometry_func.hpp
AIR_HELICOPTER
@ AIR_HELICOPTER
an helicopter
Definition: aircraft.h:31
HasAtMostOneBit
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
Definition: bitmath_func.hpp:271
BaseVehicleListWindow::vehicle_sel
VehicleID vehicle_sel
Selected vehicle.
Definition: vehicle_gui_base.h:83
WWT_PANEL
@ WWT_PANEL
Simple depressed panel.
Definition: widget_type.h:52
GetBestFittingSubType
byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
Get the best fitting subtype when 'cloning'/'replacing' v_from with v_for.
Definition: vehicle_gui.cpp:518
Vehicle::reliability
uint16_t reliability
Reliability.
Definition: vehicle_base.h:293
VehicleViewWindow::OnHotkey
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
Definition: vehicle_gui.cpp:3282
OWNER_NONE
@ OWNER_NONE
The tile has no ownership.
Definition: company_type.h:25
WidgetDimensions::vsep_normal
int vsep_normal
Normal vertical spacing.
Definition: window_gui.h:60
VehicleListIdentifier::type
VehicleListType type
The type of vehicle list.
Definition: vehiclelist.h:29
RefitWindow::GetCapacityString
StringID GetCapacityString(const RefitOption &option) const
Gets the StringID to use for displaying capacity.
Definition: vehicle_gui.cpp:938
NWidgetStacked::SetDisplayedPlane
bool SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition: widget.cpp:1304
ScaleSpriteTrad
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition: zoom_func.h:107
RefitWindow
Refit cargo window.
Definition: vehicle_gui.cpp:675
CcCloneVehicle
void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id)
This is the Callback method after the cloning attempt of a vehicle.
Definition: depot_gui.cpp:123
Scrollbar::SetCount
void SetCount(size_t num)
Sets the number of elements in the list.
Definition: widget_type.h:762
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:327
Vehicle::age
TimerGameCalendar::Date age
Age in calendar days.
Definition: vehicle_base.h:288
_train_vehicle_details_desc
static WindowDesc _train_vehicle_details_desc(__FILE__, __LINE__, WDP_AUTO, "view_vehicle_details_train", 405, 178, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, std::begin(_nested_train_vehicle_details_widgets), std::end(_nested_train_vehicle_details_widgets))
Vehicle details window descriptor.
Vehicle::HasArticulatedPart
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:954
EventState
EventState
State of handling an event.
Definition: window_type.h:738
VehicleNumberSorter
static bool VehicleNumberSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their number.
Definition: vehicle_gui.cpp:1371
WID_VL_SCROLLBAR
@ WID_VL_SCROLLBAR
Scrollbar for the list.
Definition: vehicle_widget.h:76
TrainDetailsWindowTabs
TrainDetailsWindowTabs
The tabs in the train details window.
Definition: vehicle_gui.h:25
VehicleCargoSorter
static bool VehicleCargoSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their cargo.
Definition: vehicle_gui.cpp:1419
VehicleViewWindow::IsNewGRFInspectable
bool IsNewGRFInspectable() const override
Is the data related to this window NewGRF inspectable?
Definition: vehicle_gui.cpp:3361
CargoSpec::name
StringID name
Name of this type of cargo.
Definition: cargotype.h:85
_nested_nontrain_vehicle_details_widgets
static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[]
Vehicle details widgets (other than train).
Definition: vehicle_gui.cpp:2276
TE_RISING
@ TE_RISING
Make the text effect slowly go upwards.
Definition: texteff.hpp:21
WID_VV_CAPTION
@ WID_VV_CAPTION
Caption of window.
Definition: vehicle_widget.h:15
PackVelocity
int64_t PackVelocity(uint speed, VehicleType type)
Pack velocity and vehicle type for use with SCC_VELOCITY string parameter.
Definition: strings_func.h:74
Window::FinishInitNested
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1734
Vehicle::unitnumber
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:322
ShowDropDownList
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:369
depot_map.h
container_func.hpp
VehicleTimeToLiveSorter
static bool VehicleTimeToLiveSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by the time they can still live.
Definition: vehicle_gui.cpp:1479
VehicleDefaultSettings::servint_trains
uint16_t servint_trains
service interval for trains
Definition: settings_type.h:600
company_func.h
WWT_INSET
@ WWT_INSET
Pressed (inset) panel, most commonly used as combo box text area.
Definition: widget_type.h:53
WID_VV_ORDER_LOCATION
@ WID_VV_ORDER_LOCATION
Center the main view on the order's target location.
Definition: vehicle_widget.h:20
ShowRefitOptionsList
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
Display list of cargo types of the engine, for the purchase information window.
Definition: vehicle_gui.cpp:1296
WID_VV_RENAME
@ WID_VV_RENAME
Rename vehicle.
Definition: vehicle_widget.h:18
Vehicle::y_pos
int32_t y_pos
y coordinate.
Definition: vehicle_base.h:301
ZOOM_LVL_TRAIN
@ ZOOM_LVL_TRAIN
Default zoom level for the train view.
Definition: zoom_type.h:37
ErrorUnknownCallbackResult
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Definition: newgrf_commons.cpp:499
Window::SetWidgetsLoweredState
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition: window_gui.h:526
VehicleViewWindow
Window manager class for viewing a vehicle.
Definition: vehicle_gui.cpp:2929
GroundVehicleCache::cached_power
uint32_t cached_power
Total power of the consist (valid only for the first engine).
Definition: ground_vehicle.hpp:38
SA_LEFT
@ SA_LEFT
Left align the text.
Definition: gfx_type.h:338
DrawFrameRect
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:281
Vehicle::InvalidateNewGRFCache
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
Definition: vehicle_base.h:491
NWidgetBase::SetDirty
virtual void SetDirty(const Window *w) const
Mark the widget as 'dirty' (in need of repaint).
Definition: widget.cpp:903
Vehicle::subtype
byte subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:359
WID_VL_STOP_ALL
@ WID_VL_STOP_ALL
Stop all button.
Definition: vehicle_widget.h:80
VehicleDefaultSettings::servint_ships
uint16_t servint_ships
service interval for ships
Definition: settings_type.h:603
OrderList::GetFirstOrder
Order * GetFirstOrder() const
Get the first order of the order chain.
Definition: order_base.h:298
CommandHelper
Definition: command_func.h:93
GUIList::SetFilterFuncs
void SetFilterFuncs(FilterFunction *const *n_funcs)
Hand the array of filter function pointers to the sort list.
Definition: sortlist_type.h:366
UnScaleGUI
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:77
ViewportData::follow_vehicle
VehicleID follow_vehicle
VehicleID to follow if following a vehicle, INVALID_VEHICLE otherwise.
Definition: window_gui.h:247
RefitOptions
std::map< CargoID, std::vector< RefitOption >, CargoIDComparator > RefitOptions
Available refit options (subtype and string) associated with each cargo type.
Definition: vehicle_gui.cpp:608
GUIList::SortType
uint8_t SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:114
ShowVehicleViewWindow
void ShowVehicleViewWindow(const Vehicle *v)
Shows the vehicle view window of the given vehicle.
Definition: vehicle_gui.cpp:3398
WID_VV_TURN_AROUND
@ WID_VV_TURN_AROUND
Turn this vehicle around.
Definition: vehicle_widget.h:28
BaseVehicleListWindow::vehicles
VehicleList vehicles
List of vehicles. This is the buffer for vehgroups to point into; if this is structurally modified,...
Definition: vehicle_gui_base.h:77
SA_CENTER
@ SA_CENTER
Center both horizontally and vertically.
Definition: gfx_type.h:348
CursorVars::sprite_seq
PalSpriteID sprite_seq[16]
current image of cursor
Definition: gfx_type.h:128
DrawShipImage
void DrawShipImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type)
Draws an image of a ship.
Definition: ship_gui.cpp:30
GetCharacterHeight
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition: fontcache.cpp:78
lengthof
#define lengthof(x)
Return the length of an fixed size array.
Definition: stdafx.h:300
Window::width
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:305
Viewport::zoom
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:33
SetMinimalSize
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition: widget_type.h:1099
CargoIDComparator
Comparator to sort CargoID by according to desired order.
Definition: cargotype.h:238
MemSetT
void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49
Window::SortButtonWidth
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:780
GUIList::SetSortFuncs
void SetSortFuncs(SortFunction *const *n_funcs)
Hand the array of sort function pointers to the sort list.
Definition: sortlist_type.h:295
GUIList::RebuildDone
void RebuildDone()
Notify the sortlist that the rebuild is done.
Definition: sortlist_type.h:405
VF_PATHFINDER_LOST
@ VF_PATHFINDER_LOST
Vehicle's pathfinder is lost.
Definition: vehicle_base.h:52
TileHighlightData::window_class
WindowClass window_class
The WindowClass of the window that is responsible for the selection mode.
Definition: tilehighlight_type.h:68
GUIList< GUIVehicleGroup, std::nullptr_t, CargoID >::FilterFunction
bool CDECL FilterFunction(const GUIVehicleGroup *, CargoID)
Signature of filter function.
Definition: sortlist_type.h:50
RefitOption::cargo
CargoID cargo
Cargo to refit to.
Definition: vehicle_gui.cpp:583
OverflowSafeInt< int64_t >
VehicleNameSorter
static bool VehicleNameSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their name.
Definition: vehicle_gui.cpp:1377
Vehicle::IsStoppedInDepot
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:556
WID_VL_CAPTION_SHARED_ORDERS
@ WID_VL_CAPTION_SHARED_ORDERS
Caption of window (for shared orders windows).
Definition: vehicle_widget.h:66
TFP_SIGNAL
@ TFP_SIGNAL
Ignore next signal, after the signal ignore being stuck.
Definition: train.h:40
DrawString
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:654
SetObjectToPlaceWnd
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...
Definition: viewport.cpp:3420
DrawVehicleImage
void DrawVehicleImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a vehicle chain.
Definition: vehicle_gui.cpp:1653
WID_VL_CAPTION
@ WID_VL_CAPTION
Caption of window (for non shared orders windows).
Definition: vehicle_widget.h:65
RefitWindow::vehicle_width
int vehicle_width
Width of the vehicle being drawn.
Definition: vehicle_gui.cpp:682
WID_VV_SHOW_DETAILS
@ WID_VV_SHOW_DETAILS
Show details of this vehicle.
Definition: vehicle_widget.h:24
Vehicle::cargo_type
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:337
TileVirtXY
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:416
IsNewGRFInspectable
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
Can we inspect the data given a certain feature and index.
Definition: newgrf_debug_gui.cpp:761
WID_VL_GROUP_ORDER
@ WID_VL_GROUP_ORDER
Group order.
Definition: vehicle_widget.h:69
WID_VV_REFIT
@ WID_VV_REFIT
Open the refit window.
Definition: vehicle_widget.h:22
TDW_TAB_TOTALS
@ TDW_TAB_TOTALS
Tab with sum of total cargo transported.
Definition: vehicle_gui.h:29
MAX_REFIT_CYCLE
static const uint MAX_REFIT_CYCLE
Maximum number of refit cycles we try, to prevent infinite loops.
Definition: vehicle_gui.cpp:507
Order::GetLocation
TileIndex GetLocation(const Vehicle *v, bool airport=false) const
Returns a tile somewhat representing the order destination (not suitable for pathfinding).
Definition: order_cmd.cpp:658
WidgetDimensions::bevel
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition: window_gui.h:40
gui.h
VehicleIndividualToGroupSorterWrapper
static bool VehicleIndividualToGroupSorterWrapper(GUIVehicleGroup const &a, GUIVehicleGroup const &b)
Wrapper to convert a VehicleIndividualSortFunction to a VehicleGroupSortFunction.
Definition: vehicle_gui.cpp:75
SPR_CURSOR_MOUSE
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition: sprites.h:1382
PalSpriteID::pal
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:24
BaseVehicleListWindow::unitnumber_digits
byte unitnumber_digits
The number of digits of the highest unit number.
Definition: vehicle_gui_base.h:80
articulated_vehicles.h
GameSettings::vehicle
VehicleSettings vehicle
options for vehicles
Definition: settings_type.h:626
EngineID
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
WID_VR_SELECT_HEADER
@ WID_VR_SELECT_HEADER
Header with question about the cargo to carry.
Definition: vehicle_widget.h:39
Vehicle::cargo_subtype
byte cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:338
IsEngineRefittable
bool IsEngineRefittable(EngineID engine)
Check if an engine is refittable.
Definition: engine.cpp:1259
Window
Data structure for an opened window.
Definition: window_gui.h:267
Commands
Commands
List of commands.
Definition: command_type.h:187
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition: timer_game_tick.h:48
VEH_TRAIN
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
DrawAircraftImage
void DrawAircraftImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type)
Draws an image of an aircraft.
Definition: aircraft_gui.cpp:79
Vehicle::GetOrder
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
Definition: vehicle_base.h:913
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Window::DrawWidgets
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:731
RefitWindow::BuildRefitList
void BuildRefitList()
Collects all (cargo, subcargo) refit options of a vehicle chain.
Definition: vehicle_gui.cpp:694
WID_VL_HIDE_BUTTONS
@ WID_VL_HIDE_BUTTONS
Selection to hide the buttons.
Definition: vehicle_widget.h:77
WID_VV_GOTO_DEPOT
@ WID_VV_GOTO_DEPOT
Order this vehicle to go to the depot.
Definition: vehicle_widget.h:21
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
ZOOM_LVL_OUT_4X
@ ZOOM_LVL_OUT_4X
Zoomed 4 times out.
Definition: zoom_type.h:24
DC_QUERY_COST
@ DC_QUERY_COST
query cost only, don't build.
Definition: command_type.h:373
VehicleProfitLastYearSorter
static bool VehicleProfitLastYearSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by last year profit.
Definition: vehicle_gui.cpp:1412
GetDropDownListDimension
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition: dropdown.cpp:328
WID_VR_VEHICLE_PANEL_DISPLAY
@ WID_VR_VEHICLE_PANEL_DISPLAY
Display with a representation of the vehicle to refit.
Definition: vehicle_widget.h:36
EconomyTime::DAYS_IN_ECONOMY_MONTH
static constexpr int DAYS_IN_ECONOMY_MONTH
Days in an economy month, when in wallclock timekeeping mode.
Definition: timer_game_economy.h:52
VehicleListIdentifier::UnPack
static VehicleListIdentifier UnPack(uint32_t data)
Decode a packed vehicle list identifier into a new one.
Definition: vehiclelist.cpp:54
SetDataTip
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1164
SBS_UP
@ SBS_UP
Sort descending.
Definition: window_gui.h:215
SetMinimalTextLines
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:1111
Rect::Width
int Width() const
Get width of Rect.
Definition: geometry_type.hpp:85
NWID_SELECTION
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:82
GetVehicleCallback
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
Definition: newgrf_engine.cpp:1149
GetScaledSpriteSize
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition: widget.cpp:54
NWidgetCore
Base class for a 'real' widget.
Definition: widget_type.h:356
WWT_DEBUGBOX
@ WWT_DEBUGBOX
NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
Definition: widget_type.h:65
VEH_SHIP
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
CargoFilterCriteria::CF_FREIGHT
static constexpr CargoID CF_FREIGHT
Show only vehicles which carry any freight (non-passenger) cargo.
Definition: cargo_type.h:97
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition: geometry_type.hpp:75
IsCargoInClass
bool IsCargoInClass(CargoID c, CargoClass cc)
Does cargo c have cargo class cc?
Definition: cargotype.h:230
WC_DROPDOWN_MENU
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
Definition: window_type.h:156
DepotCommand::None
@ None
No special flags.
GUIList::Sort
bool Sort(Comp compare)
Sort the list.
Definition: sortlist_type.h:268
Vehicle::orders
OrderList * orders
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:353
AWV_INCREASE
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:34
VehicleSpriteSeq::GetBounds
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:103
Order::GetDepotActionType
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:147
Window::SetWidgetsDisabledState
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition: window_gui.h:515
ShowVehicleRefitWindow
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
Show the refit window for a vehicle.
Definition: vehicle_gui.cpp:1288
QSF_ENABLE_DEFAULT
@ QSF_ENABLE_DEFAULT
enable the 'Default' button ("\0" is returned)
Definition: textbuf_gui.h:21
RefitWindow::OnInit
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: vehicle_gui.cpp:882
NWidgetBase::current_x
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:233
GroundVehicleCache::cached_total_length
uint16_t cached_total_length
Length of the whole vehicle (valid only for the first engine).
Definition: ground_vehicle.hpp:42
NWidgetStacked::shown_plane
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:498
WidgetDimensions::framerect
RectPadding framerect
Standard padding inside many panels.
Definition: window_gui.h:42
Order::next
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:59
WidgetDimensions::hsep_normal
int hsep_normal
Normal horizontal spacing.
Definition: window_gui.h:63
WID_VL_START_ALL
@ WID_VL_START_ALL
Start all button.
Definition: vehicle_widget.h:81
Order
Definition: order_base.h:36
RefitWindow::SetSelection
void SetSelection(uint click_row)
Select a row.
Definition: vehicle_gui.cpp:840
VehicleDefaultSettings::servint_roadveh
uint16_t servint_roadveh
service interval for road vehicles
Definition: settings_type.h:601
roadveh_cmd.h
VEHICLE_PROFIT_MIN_AGE
static const TimerGameEconomy::Date VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition: vehicle_func.h:28
Engine::GetAircraftTypeText
StringID GetAircraftTypeText() const
Get the name of the aircraft type for display purposes.
Definition: engine.cpp:467
TD_RTL
@ TD_RTL
Text is written right-to-left by default.
Definition: strings_type.h:24
_current_text_dir
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:56
Vehicle::GetDisplayProfitLastYear
Money GetDisplayProfitLastYear() const
Gets the profit vehicle had last year.
Definition: vehicle_base.h:619
VehicleListWindow::OnGameTick
void OnGameTick() override
Called once per (game) tick.
Definition: vehicle_gui.cpp:2165
RefitOption
Option to refit a vehicle chain.
Definition: vehicle_gui.cpp:582
GetLargestCargoIconSize
Dimension GetLargestCargoIconSize()
Get dimensions of largest cargo icon.
Definition: cargotype.cpp:124
VehicleReliabilitySorter
static bool VehicleReliabilitySorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their reliability.
Definition: vehicle_gui.cpp:1438
GUIList::SetFilterType
void SetFilterType(uint8_t n_type)
Set the filtertype of the list.
Definition: sortlist_type.h:176
WID_VL_AVAILABLE_VEHICLES
@ WID_VL_AVAILABLE_VEHICLES
Available vehicles.
Definition: vehicle_widget.h:78
GetStringBoundingBox
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:848
_vehicle_msg_translation_table
static const StringID _vehicle_msg_translation_table[][4]
Command codes for the shared buttons indexed by VehicleCommandTranslation and vehicle type.
Definition: vehicle_gui.cpp:2867
CargoFilterCriteria::CF_ANY
static constexpr CargoID CF_ANY
Show all items independent of carried cargo (i.e. no filtering)
Definition: cargo_type.h:94
GUIVehicleGroup::vehicles_end
VehicleList::const_iterator vehicles_end
Pointer to past-the-end element of this vehicle group.
Definition: vehicle_gui_base.h:26
GetTrainDetailsWndVScroll
int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab)
Determines the number of lines in the train details window.
Definition: train_gui.cpp:318
WWT_TEXTBTN
@ WWT_TEXTBTN
(Toggle) Button with text
Definition: widget_type.h:57
DrawVehicleProfitButton
static void DrawVehicleProfitButton(TimerGameEconomy::Date age, Money display_profit_last_year, uint num_vehicles, int x, int y)
draw the vehicle profit button in the vehicle list window.
Definition: vehicle_gui.cpp:489
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
TDW_TAB_CARGO
@ TDW_TAB_CARGO
Tab with cargo carried by the vehicles.
Definition: vehicle_gui.h:26
WC_VEHICLE_ORDERS
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
Definition: window_type.h:212
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition: settings_type.h:635
RemapCoords
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition: landscape.h:82
debug.h
GetWindowClassForVehicleType
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:97
FR_BORDERONLY
@ FR_BORDERONLY
Draw border only, no background.
Definition: window_gui.h:27
AWV_DECREASE
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:33
WWT_DROPDOWN
@ WWT_DROPDOWN
Drop down list.
Definition: widget_type.h:72
TileHighlightData::GetCallbackWnd
Window * GetCallbackWnd()
Get the window that started the current highlighting.
Definition: viewport.cpp:2582
GUIList::SetListing
void SetListing(Listing l)
Import sort conditions.
Definition: sortlist_type.h:151
GroundVehicleCache::cached_max_te
uint32_t cached_max_te
Maximum tractive effort of consist (valid only for the first engine).
Definition: ground_vehicle.hpp:33
VEHICLE_PROFIT_THRESHOLD
static const Money VEHICLE_PROFIT_THRESHOLD
Threshold for a vehicle to be considered making good profit.
Definition: vehicle_func.h:29
engine_func.h
Hotkey
All data for a single hotkey.
Definition: hotkeys.h:21
DrawTrainImage
void DrawTrainImage(const Train *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip, VehicleID drag_dest)
Draws an image of a whole train.
Definition: train_gui.cpp:93
VehicleDetailsWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition: vehicle_gui.cpp:2760
hotkeys.h
roadveh.h
WID_VD_DETAILS_CARGO_CARRIED
@ WID_VD_DETAILS_CARGO_CARRIED
Show carried cargo per part of the train.
Definition: vehicle_widget.h:57
WWT_SHADEBOX
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:66
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition: timer_game_economy.h:37
Vehicle::GetDisplayMinPowerToWeight
uint32_t GetDisplayMinPowerToWeight() const
Calculates the minimum power-to-weight ratio using the maximum weight of the ground vehicle.
Definition: vehicle.cpp:3235
HasBit
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103