OpenTTD Source 20250328-master-gc3457cd4c0
depot_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 "train.h"
12#include "roadveh.h"
13#include "ship.h"
14#include "aircraft.h"
15#include "gui.h"
16#include "textbuf_gui.h"
17#include "viewport_func.h"
18#include "command_func.h"
19#include "depot_base.h"
20#include "spritecache.h"
21#include "strings_func.h"
22#include "vehicle_func.h"
23#include "company_func.h"
24#include "tilehighlight_func.h"
25#include "window_gui.h"
26#include "vehiclelist.h"
27#include "vehicle_func.h"
28#include "order_backup.h"
29#include "zoom_func.h"
30#include "error.h"
31#include "depot_cmd.h"
32#include "train_cmd.h"
33#include "vehicle_cmd.h"
35
37
38#include "table/strings.h"
39
40#include "safeguards.h"
41
42/*
43 * Since all depot window sizes aren't the same, we need to modify sizes a little.
44 * It's done with the following arrays of widget indexes. Each of them tells if a widget side should be moved and in what direction.
45 * How long they should be moved and for what window types are controlled in ShowDepotWindow()
46 */
47
51 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
52 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_D_SHOW_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), // rename button
53 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_DEPOT_RENAME_TOOLTIP),
55 NWidget(WWT_CAPTION, COLOUR_GREY, WID_D_CAPTION),
56 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_LOCATION), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION),
57 NWidget(WWT_SHADEBOX, COLOUR_GREY),
58 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
59 NWidget(WWT_STICKYBOX, COLOUR_GREY),
69 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_D_SELL), SetResize(0, 1), SetFill(0, 1),
71 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_D_SELL_CHAIN), SetSpriteTip(SPR_SELL_CHAIN_TRAIN, STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP), SetResize(0, 1), SetFill(0, 1),
79 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_D_BUILD), SetFill(1, 1), SetResize(1, 0),
80 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_D_CLONE), SetFill(1, 1), SetResize(1, 0),
81 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_D_VEHICLE_LIST), SetAspect(WidgetDimensions::ASPECT_VEHICLE_ICON), SetFill(0, 1),
82 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_STOP_ALL), SetSpriteTip(SPR_FLAG_VEH_STOPPED), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1),
83 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_START_ALL), SetSpriteTip(SPR_FLAG_VEH_RUNNING), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1),
84 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
86};
87
88static WindowDesc _train_depot_desc(
89 WDP_AUTO, "depot_train", 362, 123,
91 {},
93);
94
95static WindowDesc _road_depot_desc(
96 WDP_AUTO, "depot_roadveh", 316, 97,
98 {},
100);
101
102static WindowDesc _ship_depot_desc(
103 WDP_AUTO, "depot_ship", 306, 99,
105 {},
107);
108
109static WindowDesc _aircraft_depot_desc(
110 WDP_AUTO, "depot_aircraft", 332, 99,
112 {},
114);
115
116extern void DepotSortList(VehicleList *list);
117
123void CcCloneVehicle(Commands, const CommandCost &result, VehicleID veh_id)
124{
125 if (result.Failed()) return;
126
127 const Vehicle *v = Vehicle::Get(veh_id);
128
130}
131
132static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Vehicle *head)
133{
134 const Vehicle *v = Vehicle::Get(sel);
135
136 if (v == wagon) return;
137
138 if (wagon == nullptr) {
139 if (head != nullptr) wagon = head->Last();
140 } else {
141 wagon = wagon->Previous();
142 if (wagon == nullptr) return;
143 }
144
145 if (wagon == v) return;
146
147 Command<CMD_MOVE_RAIL_VEHICLE>::Post(STR_ERROR_CAN_T_MOVE_VEHICLE, v->tile, v->index, wagon == nullptr ? VehicleID::Invalid() : wagon->index, _ctrl_pressed);
148}
149
153
162{
163 switch (image_type) {
164 case EIT_IN_DEPOT: return _base_block_sizes_depot[type];
165 case EIT_PURCHASE: return _base_block_sizes_purchase[type];
166 default: NOT_REACHED();
167 }
168}
169
170static void InitBlocksizeForVehicles(VehicleType type, EngineImageType image_type)
171{
172 int max_extend_left = 0;
173 int max_extend_right = 0;
174 uint max_height = 0;
175
176 for (const Engine *e : Engine::IterateType(type)) {
177 if (!e->IsEnabled()) continue;
178
179 EngineID eid = e->index;
180 uint x, y;
181 int x_offs, y_offs;
182
183 switch (type) {
184 default: NOT_REACHED();
185 case VEH_TRAIN: GetTrainSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
186 case VEH_ROAD: GetRoadVehSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
187 case VEH_SHIP: GetShipSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
188 case VEH_AIRCRAFT: GetAircraftSpriteSize(eid, x, y, x_offs, y_offs, image_type); break;
189 }
190 if (y > max_height) max_height = y;
191 if (-x_offs > max_extend_left) max_extend_left = -x_offs;
192 if ((int)x + x_offs > max_extend_right) max_extend_right = x + x_offs;
193 }
194
195 int min_extend = ScaleSpriteTrad(16);
196 int max_extend = ScaleSpriteTrad(98);
197
198 switch (image_type) {
199 case EIT_IN_DEPOT:
200 _base_block_sizes_depot[type].height = std::max<uint>(ScaleSpriteTrad(GetVehicleHeight(type)), max_height);
201 _base_block_sizes_depot[type].extend_left = Clamp(max_extend_left, min_extend, max_extend);
202 _base_block_sizes_depot[type].extend_right = Clamp(max_extend_right, min_extend, max_extend);
203 break;
204 case EIT_PURCHASE:
205 _base_block_sizes_purchase[type].height = std::max<uint>(ScaleSpriteTrad(GetVehicleHeight(type)), max_height);
206 _base_block_sizes_purchase[type].extend_left = Clamp(max_extend_left, min_extend, max_extend);
207 _base_block_sizes_purchase[type].extend_right = Clamp(max_extend_right, min_extend, max_extend);
208 break;
209
210 default: NOT_REACHED();
211 }
212}
213
219{
220 for (VehicleType vt = VEH_BEGIN; vt < VEH_COMPANY_END; vt++) {
221 InitBlocksizeForVehicles(vt, EIT_IN_DEPOT);
222 InitBlocksizeForVehicles(vt, EIT_PURCHASE);
223 }
224
225 _consistent_train_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
226 bool first = true;
227 for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
228 if (!e->IsEnabled()) continue;
229
230 uint w = TRAININFO_DEFAULT_VEHICLE_WIDTH;
231 if (e->GetGRF() != nullptr && is_custom_sprite(e->u.rail.image_index)) {
232 w = e->GetGRF()->traininfo_vehicle_width;
233 if (w != VEHICLEINFO_FULL_VEHICLE_WIDTH) {
234 /* Hopeless.
235 * This is a NewGRF vehicle that uses TRAININFO_DEFAULT_VEHICLE_WIDTH.
236 * If the vehicles are shorter than 8/8 we have fractional lengths, which are not consistent after rounding.
237 */
239 break;
240 }
241 }
242
243 if (first) {
245 first = false;
246 } else if (w != _consistent_train_width) {
248 break;
249 }
250 }
251}
252
253static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
254const Sprite *GetAircraftSprite(EngineID engine);
255
257 VehicleID sel = VehicleID::Invalid();
258 VehicleID vehicle_over = VehicleID::Invalid();
260 bool generate_list = true;
261 bool check_unitnumber_digits = true;
263 VehicleList vehicle_list{};
264 VehicleList wagon_list{};
265 uint unitnumber_digits = 2;
266 uint num_columns = 1;
267 Scrollbar *hscroll = nullptr;
268 Scrollbar *vscroll = nullptr;
269 uint count_width = 0;
270 uint header_width = 0;
273 bool last_overlay_state = false;
274
275 DepotWindow(WindowDesc &desc, TileIndex tile, VehicleType type) : Window(desc)
276 {
277 assert(IsCompanyBuildableVehicleType(type)); // ensure that we make the call with a valid type
278
279 this->type = type;
280
281 this->CreateNestedTree();
282 this->hscroll = (this->type == VEH_TRAIN ? this->GetScrollbar(WID_D_H_SCROLL) : nullptr);
283 this->vscroll = this->GetScrollbar(WID_D_V_SCROLL);
284 /* Don't show 'rename button' of aircraft hangar */
285 this->GetWidget<NWidgetStacked>(WID_D_SHOW_RENAME)->SetDisplayedPlane(type == VEH_AIRCRAFT ? SZSP_NONE : 0);
286 /* Only train depots have a horizontal scrollbar and a 'sell chain' button */
287 if (type == VEH_TRAIN) this->GetWidget<NWidgetCore>(WID_D_MATRIX)->SetMatrixDimension(1, 0 /* auto-scale */);
288 this->GetWidget<NWidgetStacked>(WID_D_SHOW_H_SCROLL)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_HORIZONTAL);
289 this->GetWidget<NWidgetStacked>(WID_D_SHOW_SELL_CHAIN)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_NONE);
290 this->SetupWidgetData(type);
291 this->FinishInitNested(tile);
292
293 this->owner = GetTileOwner(tile);
295 }
296
297 void Close([[maybe_unused]] int data = 0) override
298 {
300 CloseWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDestinationIndex()).ToWindowNumber(), false);
302 this->Window::Close();
303 }
304
310 void DrawVehicleInDepot(const Vehicle *v, const Rect &r) const
311 {
312 bool free_wagon = false;
313
314 bool rtl = _current_text_dir == TD_RTL;
315 Rect text = r.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix); /* Ract for text elements, horizontal is already applied. */
316 Rect image = r.Indent(this->header_width, rtl).Indent(this->count_width, !rtl); /* Rect for vehicle images */
317
318 switch (v->type) {
319 case VEH_TRAIN: {
320 const Train *u = Train::From(v);
321 free_wagon = u->IsFreeWagon();
322
323 uint x_space = free_wagon ?
324 ScaleSpriteTrad(_consistent_train_width != 0 ? _consistent_train_width : TRAININFO_DEFAULT_VEHICLE_WIDTH) :
325 0;
326
327 DrawTrainImage(u, image.Indent(x_space, rtl), this->sel, EIT_IN_DEPOT, free_wagon ? 0 : this->hscroll->GetPosition(), this->vehicle_over);
328
329 /* Length of consist in tiles with 1 fractional digit (rounded up) */
330 Rect count = text.WithWidth(this->count_width - WidgetDimensions::scaled.hsep_normal, !rtl);
331 DrawString(count.left, count.right, count.bottom - GetCharacterHeight(FS_SMALL) + 1,
333 TC_BLACK, SA_RIGHT, false, FS_SMALL); // Draw the counter
334 break;
335 }
336
337 case VEH_ROAD: DrawRoadVehImage( v, image, this->sel, EIT_IN_DEPOT); break;
338 case VEH_SHIP: DrawShipImage( v, image, this->sel, EIT_IN_DEPOT); break;
339 case VEH_AIRCRAFT: DrawAircraftImage(v, image, this->sel, EIT_IN_DEPOT); break;
340 default: NOT_REACHED();
341 }
342
343 uint diff_x, diff_y;
344 if (v->IsGroundVehicle()) {
345 /* Arrange unitnumber and flag horizontally */
347 diff_y = WidgetDimensions::scaled.matrix.top;
348 } else {
349 /* Arrange unitnumber and flag vertically */
350 diff_x = 0;
352 }
353
354 text = text.WithWidth(this->header_width - WidgetDimensions::scaled.hsep_normal, rtl).WithHeight(GetCharacterHeight(FS_NORMAL)).Indent(diff_x, rtl);
355 if (free_wagon) {
357 } else {
358 Rect flag = r.WithWidth(this->flag_size.width, rtl).WithHeight(this->flag_size.height).Translate(0, diff_y);
359 DrawSpriteIgnorePadding((v->vehstatus.Test(VehState::Stopped)) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, flag, SA_CENTER);
360
361 DrawString(text, GetString(STR_JUST_COMMA, v->unitnumber), (v->max_age - CalendarTime::DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED);
362 }
363 }
364
365 void DrawWidget(const Rect &r, WidgetID widget) const override
366 {
367 if (widget != WID_D_MATRIX) return;
368
369 bool rtl = _current_text_dir == TD_RTL;
370
371 /* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
373
374 /* Set up rect for each cell */
376 if (this->num_columns != 1) ir = ir.WithWidth(this->resize.step_width, rtl);
377 ir = ir.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero);
378
379 /* Draw vertical separators at whole tiles.
380 * This only works in two cases:
381 * - All vehicles use VEHICLEINFO_FULL_VEHICLE_WIDTH as reference width.
382 * - All vehicles are 8/8. This cannot be checked for NewGRF, so instead we check for "all vehicles are original vehicles".
383 */
384 if (this->type == VEH_TRAIN && _consistent_train_width != 0) {
386 int col = GetColourGradient(wid->colour, SHADE_NORMAL);
387 Rect image = ir.Indent(this->header_width, rtl).Indent(this->count_width, !rtl);
388 int first_line = w + (-this->hscroll->GetPosition()) % w;
389 if (rtl) {
390 for (int x = image.right - first_line; x >= image.left; x -= w) {
391 GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
392 }
393 } else {
394 for (int x = image.left + first_line; x <= image.right; x += w) {
395 GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
396 }
397 }
398 }
399
400 uint16_t rows_in_display = wid->current_y / wid->resize_y;
401
402 uint num = this->vscroll->GetPosition() * this->num_columns;
403 uint maxval = static_cast<uint>(std::min<size_t>(this->vehicle_list.size(), num + (rows_in_display * this->num_columns)));
404 for (; num < maxval; ir = ir.Translate(0, this->resize.step_height)) { // Draw the rows
405 Rect cell = ir; /* Keep track of horizontal cells */
406 for (uint i = 0; i < this->num_columns && num < maxval; i++, num++) {
407 /* Draw all vehicles in the current row */
408 const Vehicle *v = this->vehicle_list[num];
409 this->DrawVehicleInDepot(v, cell);
410 cell = cell.Translate(rtl ? -(int)this->resize.step_width : (int)this->resize.step_width, 0);
411 }
412 }
413
414 maxval = static_cast<uint>(std::min<size_t>(this->vehicle_list.size() + this->wagon_list.size(), (this->vscroll->GetPosition() * this->num_columns) + (rows_in_display * this->num_columns)));
415
416 /* Draw the train wagons without an engine in front. */
417 for (; num < maxval; num++, ir = ir.Translate(0, this->resize.step_height)) {
418 const Vehicle *v = this->wagon_list[num - this->vehicle_list.size()];
419 this->DrawVehicleInDepot(v, ir);
420 }
421 }
422
423 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
424 {
425 if (widget == WID_D_CAPTION) return GetString(STR_DEPOT_CAPTION, this->type, this->GetDestinationIndex());
426
427 return this->Window::GetWidgetString(widget, stringid);
428 }
429
431 const Vehicle *head;
432 const Vehicle *wagon;
433 };
434
435 enum DepotGUIAction : uint8_t {
436 MODE_ERROR,
437 MODE_DRAG_VEHICLE,
438 MODE_SHOW_VEHICLE,
439 MODE_START_STOP,
440 };
441
442 DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d)
443 {
444 this->RefreshVehicleList();
445
447 /* Make X relative to widget. Y is left alone for GetScrolledRowFromWidget(). */
448 x -= matrix_widget->pos_x;
449 /* In case of RTL the widgets are swapped as a whole */
450 if (_current_text_dir == TD_RTL) x = matrix_widget->current_x - x;
451
452 uint xt = 0, xm = 0, ym = 0;
453 if (this->type == VEH_TRAIN) {
454 xm = x;
455 } else {
456 xt = x / this->resize.step_width;
457 xm = x % this->resize.step_width;
458 if (xt >= this->num_columns) return MODE_ERROR;
459 }
460 ym = (y - matrix_widget->pos_y) % this->resize.step_height;
461
462 int32_t row = this->vscroll->GetScrolledRowFromWidget(y, this, WID_D_MATRIX);
463 uint pos = (row * this->num_columns) + xt;
464
465 if (row == INT32_MAX || this->vehicle_list.size() + this->wagon_list.size() <= pos) {
466 /* Clicking on 'line' / 'block' without a vehicle */
467 if (this->type == VEH_TRAIN) {
468 /* End the dragging */
469 d->head = nullptr;
470 d->wagon = nullptr;
471 return MODE_DRAG_VEHICLE;
472 } else {
473 return MODE_ERROR; // empty block, so no vehicle is selected
474 }
475 }
476
477 bool wagon = false;
478 if (this->vehicle_list.size() > pos) {
479 *veh = this->vehicle_list[pos];
480 /* Skip vehicles that are scrolled off the list */
481 if (this->type == VEH_TRAIN) x += this->hscroll->GetPosition();
482 } else {
483 pos -= (uint)this->vehicle_list.size();
484 *veh = this->wagon_list[pos];
485 /* free wagons don't have an initial loco. */
486 x -= ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH);
487 wagon = true;
488 }
489
490 const Train *v = nullptr;
491 if (this->type == VEH_TRAIN) {
492 v = Train::From(*veh);
493 d->head = d->wagon = v;
494 }
495
497 switch (this->type) {
498 case VEH_TRAIN:
499 if (wagon) return MODE_ERROR;
500 [[fallthrough]];
501
502 case VEH_ROAD:
503 if (xm <= this->flag_size.width) return MODE_START_STOP;
504 break;
505
506 case VEH_SHIP:
507 case VEH_AIRCRAFT:
508 if (xm <= this->flag_size.width && ym >= (uint)(GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal)) return MODE_START_STOP;
509 break;
510
511 default: NOT_REACHED();
512 }
513 return MODE_SHOW_VEHICLE;
514 }
515
516 if (this->type != VEH_TRAIN) return MODE_DRAG_VEHICLE;
517
518 /* Clicking on the counter */
519 if (xm >= matrix_widget->current_x - this->count_width) return wagon ? MODE_ERROR : MODE_SHOW_VEHICLE;
520
521 /* Account for the header */
522 x -= this->header_width;
523
524 /* find the vehicle in this row that was clicked */
525 for (; v != nullptr; v = v->Next()) {
526 x -= v->GetDisplayImageWidth();
527 if (x < 0) break;
528 }
529
530 d->wagon = (v != nullptr ? v->GetFirstEnginePart() : nullptr);
531
532 return MODE_DRAG_VEHICLE;
533 }
534
540 void DepotClick(int x, int y)
541 {
542 GetDepotVehiclePtData gdvp = { nullptr, nullptr };
543 const Vehicle *v = nullptr;
544 DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp);
545
546 if (this->type == VEH_TRAIN) v = gdvp.wagon;
547
548 switch (mode) {
549 case MODE_ERROR: // invalid
550 return;
551
552 case MODE_DRAG_VEHICLE: { // start dragging of vehicle
553 if (v != nullptr && VehicleClicked(v)) return;
554
555 VehicleID sel = this->sel;
556
557 if (this->type == VEH_TRAIN && sel != VehicleID::Invalid()) {
558 this->sel = VehicleID::Invalid();
559 TrainDepotMoveVehicle(v, sel, gdvp.head);
560 } else if (v != nullptr) {
563 _cursor.vehchain = _ctrl_pressed;
564
565 this->sel = v->index;
566 this->SetDirty();
567 }
568 break;
569 }
570
571 case MODE_SHOW_VEHICLE: // show info window
573 break;
574
575 case MODE_START_STOP: // click start/stop flag
576 StartStopVehicle(v, false);
577 break;
578
579 default: NOT_REACHED();
580 }
581 }
582
590 {
595
598
603
604 switch (type) {
605 default: NOT_REACHED();
606
607 case VEH_TRAIN:
609
610 /* Sprites */
611 this->GetWidget<NWidgetCore>(WID_D_SELL)->SetSprite(SPR_SELL_TRAIN);
612 this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->SetSprite(SPR_SELL_ALL_TRAIN);
613 this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->SetSprite(SPR_REPLACE_TRAIN);
614 break;
615
616 case VEH_ROAD:
618
619 /* Sprites */
620 this->GetWidget<NWidgetCore>(WID_D_SELL)->SetSprite(SPR_SELL_ROADVEH);
621 this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->SetSprite(SPR_SELL_ALL_ROADVEH);
622 this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->SetSprite(SPR_REPLACE_ROADVEH);
623 break;
624
625 case VEH_SHIP:
627
628 /* Sprites */
629 this->GetWidget<NWidgetCore>(WID_D_SELL)->SetSprite(SPR_SELL_SHIP);
630 this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->SetSprite(SPR_SELL_ALL_SHIP);
631 this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->SetSprite(SPR_REPLACE_SHIP);
632 break;
633
634 case VEH_AIRCRAFT:
636
637 /* Sprites */
638 this->GetWidget<NWidgetCore>(WID_D_SELL)->SetSprite(SPR_SELL_AIRCRAFT);
639 this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->SetSprite(SPR_SELL_ALL_AIRCRAFT);
640 this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->SetSprite(SPR_REPLACE_AIRCRAFT);
641 break;
642 }
643 }
644
645 void OnInit() override
646 {
648 this->flag_size = maxdim(GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED), GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING));
649 }
650
652 {
653 switch (widget) {
654 case WID_D_MATRIX: {
655 uint min_height = 0;
656
657 if (this->type == VEH_TRAIN) {
659 } else {
660 this->count_width = 0;
661 }
662
664
665 if (this->type == VEH_TRAIN || this->type == VEH_ROAD) {
666 min_height = std::max<uint>(unumber.height, this->flag_size.height);
668 } else {
669 min_height = unumber.height + WidgetDimensions::scaled.vsep_normal + this->flag_size.height;
670 this->header_width = std::max<uint>(unumber.width, this->flag_size.width) + WidgetDimensions::scaled.hsep_normal;
671 }
672 int base_width = this->count_width + this->header_width + padding.width;
673
674 resize.height = std::max<uint>(this->cell_size.height, min_height + padding.height);
675 if (this->type == VEH_TRAIN) {
676 resize.width = 1;
677 size.width = base_width + 2 * ScaleSpriteTrad(29); // about 2 parts
678 size.height = resize.height * 6;
679 } else {
681 size.width = resize.width * (this->type == VEH_ROAD ? 5 : 3);
682 size.height = resize.height * (this->type == VEH_ROAD ? 5 : 3);
683 }
684 fill.width = resize.width;
685 fill.height = resize.height;
686 break;
687 }
688 }
689 }
690
696 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
697 {
698 this->generate_list = true;
699 }
700
701 void RefreshVehicleList()
702 {
703 if (this->generate_list) {
704 /* Generate the vehicle list
705 * It's ok to use the wagon pointers for non-trains as they will be ignored */
706 BuildDepotVehicleList(this->type, TileIndex(this->window_number), &this->vehicle_list, &this->wagon_list);
707 this->generate_list = false;
708 DepotSortList(&this->vehicle_list);
709
710 this->check_unitnumber_digits = true;
711 }
712 }
713
714 void OnPaint() override
715 {
716 this->RefreshVehicleList();
717
718 if (this->check_unitnumber_digits) {
719 this->check_unitnumber_digits = false;
720 uint new_unitnumber_digits = GetUnitNumberDigits(this->vehicle_list);
721 /* Only increase the size; do not decrease to prevent constant changes */
722 if (this->unitnumber_digits < new_unitnumber_digits) {
723 this->unitnumber_digits = new_unitnumber_digits;
724 this->ReInit();
725 }
726 }
727
728 /* determine amount of items for scroller */
729 if (this->type == VEH_TRAIN) {
730 uint max_width = ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH);
731 for (uint num = 0; num < this->vehicle_list.size(); num++) {
732 uint width = 0;
733 for (const Train *v = Train::From(this->vehicle_list[num]); v != nullptr; v = v->Next()) {
735 }
736 max_width = std::max(max_width, width);
737 }
738 /* Always have 1 empty row, so people can change the setting of the train */
739 this->vscroll->SetCount(this->vehicle_list.size() + this->wagon_list.size() + 1);
740 /* Always make it longer than the longest train, so you can attach vehicles at the end, and also see the next vertical tile separator line */
741 this->hscroll->SetCount(max_width + ScaleSpriteTrad(2 * VEHICLEINFO_FULL_VEHICLE_WIDTH + 1));
742 } else {
743 this->vscroll->SetCount(CeilDiv((uint)this->vehicle_list.size(), this->num_columns));
744 }
745
746 /* Setup disabled buttons. */
747 TileIndex tile(this->window_number);
758
759 this->DrawWidgets();
760 }
761
762 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
763 {
764 switch (widget) {
765 case WID_D_MATRIX: // List
766 this->DepotClick(pt.x, pt.y);
767 break;
768
769 case WID_D_BUILD: // Build vehicle
771 ShowBuildVehicleWindow(TileIndex(this->window_number), this->type);
772 break;
773
774 case WID_D_CLONE: // Clone button
777
778 if (this->IsWidgetLowered(WID_D_CLONE)) {
779 static const CursorID clone_icons[] = {
780 SPR_CURSOR_CLONE_TRAIN, SPR_CURSOR_CLONE_ROADVEH,
781 SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
782 };
783
784 SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_VEHICLE, this);
785 } else {
787 }
788 break;
789
790 case WID_D_LOCATION:
791 if (_ctrl_pressed) {
793 } else {
795 }
796 break;
797
798 case WID_D_RENAME: // Rename button
801 break;
802
803 case WID_D_STOP_ALL:
804 case WID_D_START_ALL: {
805 VehicleListIdentifier vli(VL_DEPOT_LIST, this->type, this->owner);
807 break;
808 }
809
810 case WID_D_SELL_ALL:
811 /* Only open the confirmation window if there are anything to sell */
812 if (!this->vehicle_list.empty() || !this->wagon_list.empty()) {
813 ShowQuery(
816 this,
817 DepotSellAllConfirmationCallback
818 );
819 }
820 break;
821
823 ShowVehicleListWindow(GetTileOwner(this->window_number), this->type, TileIndex(this->window_number));
824 break;
825
827 Command<CMD_DEPOT_MASS_AUTOREPLACE>::Post(GetCmdAutoreplaceVehMsg(this->type), TileIndex(this->window_number), this->type);
828 break;
829
830 }
831 }
832
833 void OnQueryTextFinished(std::optional<std::string> str) override
834 {
835 if (!str.has_value()) return;
836
837 /* Do depot renaming */
839 }
840
841 bool OnRightClick([[maybe_unused]] Point pt, WidgetID widget) override
842 {
843 if (widget != WID_D_MATRIX) return false;
844
845 GetDepotVehiclePtData gdvp = { nullptr, nullptr };
846 const Vehicle *v = nullptr;
847 DepotGUIAction mode = this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp);
848
849 if (this->type == VEH_TRAIN) v = gdvp.wagon;
850
851 if (v == nullptr || mode != MODE_DRAG_VEHICLE) return false;
852
853 CargoArray capacity{}, loaded{};
854
855 /* Display info for single (articulated) vehicle, or for whole chain starting with selected vehicle */
856 bool whole_chain = (this->type == VEH_TRAIN && _ctrl_pressed);
857
858 /* loop through vehicle chain and collect cargoes */
859 uint num = 0;
860 for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
861 if (w->cargo_cap > 0 && w->cargo_type < NUM_CARGO) {
862 capacity[w->cargo_type] += w->cargo_cap;
863 loaded [w->cargo_type] += w->cargo.StoredCount();
864 }
865
866 if (w->type == VEH_TRAIN && !w->HasArticulatedPart()) {
867 num++;
868 if (!whole_chain) break;
869 }
870 }
871
872 /* Build tooltipstring */
873 static std::string details;
874 details.clear();
875
876 for (const CargoSpec *cs : _sorted_cargo_specs) {
877 CargoType cargo_type = cs->Index();
878 if (capacity[cargo_type] == 0) continue;
879
880 auto params = MakeParameters(cargo_type, loaded[cargo_type], cargo_type, capacity[cargo_type]);
881 AppendStringWithArgsInPlace(details, STR_DEPOT_VEHICLE_TOOLTIP_CARGO, params);
882 }
883
884 /* Show tooltip window */
885 if (whole_chain) {
887 } else {
889 }
890
891 return true;
892 }
893
899 bool OnVehicleSelect(const Vehicle *v) override
900 {
901 if (_ctrl_pressed) {
902 /* Share-clone, do not open new viewport, and keep tool active */
904 } else {
905 /* Copy-clone, open viewport for new vehicle, and deselect the tool (assume player wants to change things on new vehicle) */
908 }
909 }
910
911 return true;
912 }
913
920 bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
921 {
922 if (!_ctrl_pressed) {
923 /* If CTRL is not pressed: If all the vehicles in this list have the same orders, then copy orders */
924 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
926 })) {
927 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
929 })) {
930 OnVehicleSelect(*begin);
931 } else {
934 }
935 } else {
938 }
939 } else {
940 /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */
941 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
943 })) {
944 if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
945 return v1->FirstShared() == v2->FirstShared();
946 })) {
947 OnVehicleSelect(*begin);
948 } else {
951 }
952 } else {
955 }
956 }
957
958 return true;
959 }
960
961 void OnPlaceObjectAbort() override
962 {
963 /* abort clone */
966
967 /* abort drag & drop */
968 this->sel = VehicleID::Invalid();
969 this->vehicle_over = VehicleID::Invalid();
971
972 if (this->hovered_widget != -1) {
973 this->SetWidgetLoweredState(this->hovered_widget, false);
974 this->SetWidgetDirty(this->hovered_widget);
975 this->hovered_widget = -1;
976 }
977 }
978
979 void OnMouseLoop() override
980 {
981 if (last_overlay_state != ShowCargoIconOverlay()) {
982 last_overlay_state = ShowCargoIconOverlay();
983 this->SetDirty();
984 }
985 }
986
987 void OnMouseDrag(Point pt, WidgetID widget) override
988 {
989 if (this->sel == VehicleID::Invalid()) return;
990 if (widget != this->hovered_widget) {
991 if (this->hovered_widget == WID_D_SELL || this->hovered_widget == WID_D_SELL_CHAIN) {
992 this->SetWidgetLoweredState(this->hovered_widget, false);
993 this->SetWidgetDirty(this->hovered_widget);
994 }
995 this->hovered_widget = widget;
996 if (this->hovered_widget == WID_D_SELL || this->hovered_widget == WID_D_SELL_CHAIN) {
997 this->SetWidgetLoweredState(this->hovered_widget, true);
998 this->SetWidgetDirty(this->hovered_widget);
999 }
1000 }
1001 if (this->type != VEH_TRAIN) return;
1002
1003 /* A rail vehicle is dragged.. */
1004 if (widget != WID_D_MATRIX) { // ..outside of the depot matrix.
1005 if (this->vehicle_over != VehicleID::Invalid()) {
1006 this->vehicle_over = VehicleID::Invalid();
1008 }
1009 return;
1010 }
1011
1012 const Vehicle *v = nullptr;
1013 GetDepotVehiclePtData gdvp = {nullptr, nullptr};
1014
1015 if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp) != MODE_DRAG_VEHICLE) return;
1016
1017 VehicleID new_vehicle_over = VehicleID::Invalid();
1018 if (gdvp.head != nullptr) {
1019 if (gdvp.wagon == nullptr && gdvp.head->Last()->index != this->sel) { // ..at the end of the train.
1020 /* NOTE: As a wagon can't be moved at the begin of a train, head index isn't used to mark a drag-and-drop
1021 * destination inside a train. This head index is then used to indicate that a wagon is inserted at
1022 * the end of the train.
1023 */
1024 new_vehicle_over = gdvp.head->index;
1025 } else if (gdvp.wagon != nullptr && gdvp.head != gdvp.wagon &&
1026 gdvp.wagon->index != this->sel &&
1027 gdvp.wagon->Previous()->index != this->sel) { // ..over an existing wagon.
1028 new_vehicle_over = gdvp.wagon->index;
1029 }
1030 }
1031
1032 if (this->vehicle_over == new_vehicle_over) return;
1033
1034 this->vehicle_over = new_vehicle_over;
1035 this->SetWidgetDirty(widget);
1036 }
1037
1038 void OnDragDrop(Point pt, WidgetID widget) override
1039 {
1040 switch (widget) {
1041 case WID_D_MATRIX: {
1042 const Vehicle *v = nullptr;
1043 VehicleID sel = this->sel;
1044
1045 this->sel = VehicleID::Invalid();
1046 this->SetDirty();
1047
1048 if (this->type == VEH_TRAIN) {
1049 GetDepotVehiclePtData gdvp = { nullptr, nullptr };
1050
1051 if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp) == MODE_DRAG_VEHICLE && sel != VehicleID::Invalid()) {
1052 if (gdvp.wagon != nullptr && gdvp.wagon->index == sel && _ctrl_pressed) {
1054 } else if (gdvp.wagon == nullptr || gdvp.wagon->index != sel) {
1055 this->vehicle_over = VehicleID::Invalid();
1056 TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
1057 } else if (gdvp.head != nullptr && gdvp.head->IsFrontEngine()) {
1059 }
1060 }
1061 } else if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, nullptr) == MODE_DRAG_VEHICLE && v != nullptr && sel == v->index) {
1063 }
1064 break;
1065 }
1066
1067 case WID_D_SELL: case WID_D_SELL_CHAIN: {
1068 if (this->IsWidgetDisabled(widget)) return;
1069 if (this->sel == VehicleID::Invalid()) return;
1070
1071 this->HandleButtonClick(widget);
1072
1073 const Vehicle *v = Vehicle::Get(this->sel);
1074 this->sel = VehicleID::Invalid();
1075 this->SetDirty();
1076
1077 bool sell_cmd = (v->type == VEH_TRAIN && (widget == WID_D_SELL_CHAIN || _ctrl_pressed));
1078 Command<CMD_SELL_VEHICLE>::Post(GetCmdSellVehMsg(v->type), v->tile, v->index, sell_cmd, true, INVALID_CLIENT_ID);
1079 break;
1080 }
1081
1082 default:
1083 this->sel = VehicleID::Invalid();
1084 this->SetDirty();
1085 break;
1086 }
1087 this->hovered_widget = -1;
1088 _cursor.vehchain = false;
1089 }
1090
1091 void OnTimeout() override
1092 {
1093 if (!this->IsWidgetDisabled(WID_D_SELL)) {
1094 this->RaiseWidget(WID_D_SELL);
1096 }
1097 if (this->GetWidget<NWidgetBase>(WID_D_SELL) != nullptr && !this->IsWidgetDisabled(WID_D_SELL_CHAIN)) {
1100 }
1101 }
1102
1103 void OnResize() override
1104 {
1105 this->vscroll->SetCapacityFromWidget(this, WID_D_MATRIX);
1107 if (this->type == VEH_TRAIN) {
1108 this->hscroll->SetCapacity(nwi->current_x - this->header_width - this->count_width);
1109 } else {
1110 this->num_columns = nwi->current_x / nwi->resize_x;
1111 }
1112 }
1113
1115 {
1116 if (this->sel != VehicleID::Invalid()) {
1117 _cursor.vehchain = _ctrl_pressed;
1119 return ES_HANDLED;
1120 }
1121
1122 return ES_NOT_HANDLED;
1123 }
1124
1131 {
1133 }
1134};
1135
1136static void DepotSellAllConfirmationCallback(Window *win, bool confirmed)
1137{
1138 if (confirmed) {
1139 DepotWindow *w = (DepotWindow*)win;
1140 TileIndex tile(w->window_number);
1141 VehicleType vehtype = w->type;
1142 Command<CMD_DEPOT_SELL_ALL_VEHICLES>::Post(GetCmdSellAllVehMsg(vehtype), tile, vehtype);
1143 }
1144}
1145
1152{
1153 if (BringWindowToFrontById(WC_VEHICLE_DEPOT, tile) != nullptr) return;
1154
1155 switch (type) {
1156 default: NOT_REACHED();
1157 case VEH_TRAIN: new DepotWindow(_train_depot_desc, tile, type); break;
1158 case VEH_ROAD: new DepotWindow(_road_depot_desc, tile, type); break;
1159 case VEH_SHIP: new DepotWindow(_ship_depot_desc, tile, type); break;
1160 case VEH_AIRCRAFT: new DepotWindow(_aircraft_depot_desc, tile, type); break;
1161 }
1162}
1163
1169{
1170 DepotWindow *w;
1171
1172 /* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any depots either
1173 * If that is the case, we can skip looping though the windows and save time
1174 */
1175 if (_special_mouse_mode != WSM_DRAGDROP) return;
1176
1177 w = dynamic_cast<DepotWindow*>(FindWindowById(WC_VEHICLE_DEPOT, v->tile));
1178 if (w != nullptr) {
1179 if (w->sel == v->index) ResetObjectToPlace();
1180 }
1181}
Base for aircraft.
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of an aircraft sprite heading west (used for lists).
void DrawAircraftImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type)
Draws an image of an aircraft.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:75
std::vector< const CargoSpec * > _sorted_cargo_specs
Cargo specifications sorted alphabetically by name.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Common return value for all commands.
bool Failed() const
Did this command fail?
Base class for a 'real' widget.
Scrollbar data structure.
void SetCount(size_t num)
Sets the number of elements in the list.
void SetCapacity(size_t capacity)
Set the capacity of visible elements.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2447
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:2521
size_type GetPosition() const
Gets the position of the first visible element in the list.
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
RectPadding matrix
Padding of WWT_MATRIX items.
Definition window_gui.h:42
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
Functions related to commands.
Commands
List of commands.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
Base for all depots (except hangars)
Command definitions related to depots.
void InitDepotWindowBlockSizes()
Set the size of the blocks in the window so we can be sure that they are big enough for the vehicle s...
static constexpr NWidgetPart _nested_train_depot_widgets[]
Nested widget definition for train depots.
Definition depot_gui.cpp:49
static uint _consistent_train_width
Whether trains of all lengths are consistently scaled. Either TRAININFO_DEFAULT_VEHICLE_WIDTH,...
void DeleteDepotHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a depot window.
static VehicleCellSize _base_block_sizes_depot[VEH_COMPANY_END]
Cell size for vehicle images in the depot view.
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type)
Get the GUI cell size for a vehicle image.
void CcCloneVehicle(Commands, const CommandCost &result, VehicleID veh_id)
This is the Callback method after the cloning attempt of a vehicle.
static VehicleCellSize _base_block_sizes_purchase[VEH_COMPANY_END]
Cell size for vehicle images in the purchase list.
DestinationID GetDepotDestinationIndex(Tile t)
Get the destination index of a 'depot'.
Definition depot_map.h:66
static const uint MAX_LENGTH_DEPOT_NAME_CHARS
The maximum length of a depot name in characters including '\0'.
Definition depot_type.h:18
Types related to the depot widgets.
@ WID_D_LOCATION
Location button.
@ WID_D_AUTOREPLACE
Autoreplace button.
@ WID_D_RENAME
Rename button.
@ WID_D_SELL_CHAIN
Sell chain button.
@ WID_D_CLONE
Clone button.
@ WID_D_SHOW_SELL_CHAIN
Show sell chain panel.
@ WID_D_SELL
Sell button.
@ WID_D_H_SCROLL
Horizontal scrollbar.
@ WID_D_SHOW_H_SCROLL
Show horizontal scrollbar panel.
@ WID_D_MATRIX
Matrix of vehicles.
@ WID_D_V_SCROLL
Vertical scrollbar.
@ WID_D_SELL_ALL
Sell all button.
@ WID_D_VEHICLE_LIST
List of vehicles.
@ WID_D_START_ALL
Start all button.
@ WID_D_SHOW_RENAME
Show rename panel.
@ WID_D_BUILD
Build button.
@ WID_D_CAPTION
Caption of window.
@ WID_D_STOP_ALL
Stop all button.
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:67
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:246
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
uint32_t CursorID
The number of the cursor (sprite)
Definition gfx_type.h:19
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:379
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:387
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:945
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
void GuiShowTooltips(Window *parent, EncodedString &&text, TooltipCloseCondition close_tooltip)
Shows a tooltip.
Definition misc_gui.cpp:691
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
@ INVALID_CLIENT_ID
Client is not part of anything.
Functions related to order backups.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:387
Road vehicle states.
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a road vehicle sprite heading west (used for lists).
void DrawRoadVehImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a road vehicle chain.
A number of safeguards to prevent using unsafe methods.
Base for ships.
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a ship sprite heading west (used for lists).
Definition ship_cmd.cpp:120
void DrawShipImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type)
Draws an image of a ship.
Definition ship_gui.cpp:30
Functions to cache sprites in memory.
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition sprites.h:1394
Definition of base types and functions in a cross-platform compatible way.
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition string_type.h:25
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:248
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:426
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:230
Functions related to OTTD's strings.
auto MakeParameters(Args &&... args)
Helper to create the StringParameters with its own buffer with the given parameter values.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
VehicleType type
Type of vehicle.
Class for storing amounts of cargo.
Definition cargo_type.h:113
Specification of a cargo type.
Definition cargotype.h:74
bool vehchain
vehicle chain is dragged
Definition gfx_type.h:151
uint header_width
Width of unit number and flag, including separator.
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
VehicleID vehicle_over
Rail vehicle over which another one is dragged, VehicleID::Invalid() if none.
void OnDragDrop(Point pt, WidgetID widget) override
A dragged 'object' has been released.
uint count_width
Width of length count, including separator.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
DestinationID GetDestinationIndex() const
Gets the DepotID of the current window.
void OnTimeout() override
Called when this window's timeout has been reached.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
uint num_columns
Number of columns.
EventState OnCTRLStateChange() override
The state of the control key has changed.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void SetupWidgetData(VehicleType type)
Function to set up vehicle specific widgets (mainly sprites and strings).
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
bool OnRightClick(Point pt, WidgetID widget) override
A click with the right mouse button has been made on the window.
void OnMouseDrag(Point pt, WidgetID widget) override
An 'object' is being dragged at the provided position, highlight the target if possible.
bool OnVehicleSelect(const Vehicle *v) override
Clones a vehicle.
Dimension flag_size
Size of start/stop flag.
void DepotClick(int x, int y)
Handle click in the depot matrix.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Scrollbar * hscroll
Only for trains.
bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
Clones a vehicle from a vehicle list.
void OnResize() override
Called after the window got resized.
void OnPaint() override
The window must be repainted.
WidgetID hovered_widget
Index of the widget being hovered during drag/drop. -1 if no drag is in progress.
void OnInit() override
Notification that the nested widget tree gets initialized.
void DrawVehicleInDepot(const Vehicle *v, const Rect &r) const
Draw a vehicle in the depot window in the box with the top left corner at x,y.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
VehicleCellSize cell_size
Vehicle sprite cell size.
Dimensions (a width and height) of a rectangle in 2D.
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
uint16_t cached_total_length
Length of the whole vehicle (valid only for the first engine).
GroundVehicleCache gcache
Cache of often calculated values.
bool IsFreeWagon() const
Check if the vehicle is a free wagon (got no engine in front of it).
Partial widget specification to allow NWidgets to be written nested.
static void Reset(TileIndex tile=INVALID_TILE, bool from_gui=true)
Reset the OrderBackups from GUI/game logic.
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
uint step_width
Step-size of width resize changes.
Definition window_gui.h:212
T * Next() const
Get next vehicle in the chain.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * GetFirstEnginePart()
Get the first part of an articulated engine.
Data structure describing a sprite.
Definition spritecache.h:17
'Train' is either a loco or a wagon.
Definition train.h:90
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a train vehicle image in the GUI.
Dimensions of a cell in the purchase/depot windows.
Definition vehicle_gui.h:83
uint extend_left
Extend of the cell to the left.
Definition vehicle_gui.h:85
uint height
Vehicle cell height.
Definition vehicle_gui.h:84
uint extend_right
Extend of the cell to the right.
Definition vehicle_gui.h:86
The information about a vehicle list.
Definition vehiclelist.h:32
Vehicle data structure.
EngineID engine_type
The type of engine used for this vehicle.
Vehicle * Last()
Get the last vehicle of this vehicle chain.
VehStates vehstatus
Status.
Vehicle * Next() const
Get the next vehicle of this vehicle.
TimerGameCalendar::Date age
Age in calendar days.
TimerGameCalendar::Date max_age
Maximum age.
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
TileIndex tile
Current tile index.
UnitID unitnumber
unit number, for display purposes only
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:957
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1052
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1738
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:470
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1728
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:492
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:411
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:973
void HandleButtonClick(WidgetID widget)
Do all things to make a button look clicked and mark it to be unclicked in a few ticks.
Definition window.cpp:595
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
void ToggleWidgetLoweredState(WidgetID widget_index)
Invert the lowered/raised status of a widget.
Definition window_gui.h:451
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Stuff related to the text buffer GUI.
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static const uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:87
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
@ HT_DRAG
dragging items in the depot windows
@ HT_VEHICLE
vehicle is accepted as target as well (bitmask)
Base for the train class.
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a train sprite heading west, or both heads (used for lists).
Command definitions related to trains.
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
bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicle chains have the same list of engines.
Definition vehicle.cpp:3261
bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicles have the same list of orders.
Definition vehicle.cpp:3278
@ Stopped
Vehicle is stopped by the player.
Command definitions for vehicles.
Functions related to vehicles.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
uint GetUnitNumberDigits(VehicleList &vehicles)
Get the number of digits the biggest unit number of a set of vehicles has.
void ShowVehicleViewWindow(const Vehicle *v)
Shows the vehicle view window of the given vehicle.
bool VehicleClicked(const Vehicle *v)
Dispatch a "vehicle selected" event if any window waits for it.
void StartStopVehicle(const Vehicle *v, bool texteffect)
Executes CMD_START_STOP_VEHICLE for given vehicle.
void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
Set the mouse cursor to look like a vehicle.
bool ShowCargoIconOverlay()
Test if cargo icon overlays should be drawn.
uint GetVehicleHeight(VehicleType type)
Get the height of a single vehicle in the GUIs.
Definition vehicle_gui.h:74
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition vehicle_gui.h:97
EngineImageType
Visualisation contexts of vehicles and engines.
@ EIT_PURCHASE
Vehicle drawn in purchase list, autoreplace gui, ...
@ EIT_IN_DEPOT
Vehicle drawn in depot.
VehicleType
Available vehicle types.
@ VEH_INVALID
Non-existing type of vehicle.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ VEH_COMPANY_END
Last company-ownable type.
void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons, bool individual_wagons)
Generate a list of vehicles inside a depot.
Functions and type for generating vehicle lists.
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition vehiclelist.h:68
@ VL_DEPOT_LIST
Index is the destination (station for hangar of aircraft, depot for others)
Definition vehiclelist.h:26
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Functions related to (drawing on) viewports.
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:48
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_IMGBTN
(Toggle) Button with image
Definition widget_type.h:42
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition widget_type.h:74
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1145
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1228
SpecialMouseMode _special_mouse_mode
Mode of the mouse.
Definition window.cpp:95
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1103
Functions, definitions and such used only by the GUI.
bool AllEqual(It begin, It end, Pred pred)
Generic helper function that checks if all elements of the range are equal with respect to the given ...
Definition window_gui.h:936
@ WSM_DRAGDROP
Drag&drop an object.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers:
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107