OpenTTD Source  20241120-master-g6d3adc6169
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"
34 #include "core/geometry_func.hpp"
35 
36 #include "widgets/depot_widget.h"
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), SetDataTip(SPR_RENAME, STR_DEPOT_RENAME_TOOLTIP),
54  EndContainer(),
55  NWidget(WWT_CAPTION, COLOUR_GREY, WID_D_CAPTION), SetDataTip(STR_DEPOT_CAPTION, STR_NULL),
56  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_LOCATION), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetDataTip(SPR_GOTO_LOCATION, STR_NULL),
57  NWidget(WWT_SHADEBOX, COLOUR_GREY),
58  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
59  NWidget(WWT_STICKYBOX, COLOUR_GREY),
60  EndContainer(),
64  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_D_SHOW_H_SCROLL),
65  NWidget(NWID_HSCROLLBAR, COLOUR_GREY, WID_D_H_SCROLL),
66  EndContainer(),
67  EndContainer(),
69  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_D_SELL), SetDataTip(0x0, STR_NULL), SetResize(0, 1), SetFill(0, 1),
71  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_D_SELL_CHAIN), SetDataTip(SPR_SELL_CHAIN_TRAIN, STR_DEPOT_DRAG_WHOLE_TRAIN_TO_SELL_TOOLTIP), SetResize(0, 1), SetFill(0, 1),
72  EndContainer(),
73  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_SELL_ALL), SetDataTip(0x0, STR_NULL),
74  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_AUTOREPLACE), SetDataTip(0x0, STR_NULL),
75  EndContainer(),
76  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_D_V_SCROLL),
77  EndContainer(),
79  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_D_BUILD), SetDataTip(0x0, STR_NULL), SetFill(1, 1), SetResize(1, 0),
80  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_D_CLONE), SetDataTip(0x0, STR_NULL), SetFill(1, 1), SetResize(1, 0),
81  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_D_VEHICLE_LIST), SetDataTip(0x0, STR_NULL), SetAspect(WidgetDimensions::ASPECT_VEHICLE_ICON), SetFill(0, 1),
82  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_STOP_ALL), SetDataTip(SPR_FLAG_VEH_STOPPED, STR_NULL), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1),
83  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_D_START_ALL), SetDataTip(SPR_FLAG_VEH_RUNNING, STR_NULL), SetAspect(WidgetDimensions::ASPECT_VEHICLE_FLAG), SetFill(0, 1),
84  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
85  EndContainer(),
86 };
87 
88 static WindowDesc _train_depot_desc(
89  WDP_AUTO, "depot_train", 362, 123,
91  0,
93 );
94 
95 static WindowDesc _road_depot_desc(
96  WDP_AUTO, "depot_roadveh", 316, 97,
98  0,
100 );
101 
102 static WindowDesc _ship_depot_desc(
103  WDP_AUTO, "depot_ship", 306, 99,
105  0,
107 );
108 
109 static WindowDesc _aircraft_depot_desc(
110  WDP_AUTO, "depot_aircraft", 332, 99,
112  0,
114 );
115 
116 extern void DepotSortList(VehicleList *list);
117 
123 void 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 
132 static 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 ? INVALID_VEHICLE : 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 
170 static 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 
253 static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
254 const Sprite *GetAircraftSprite(EngineID engine);
255 
256 struct DepotWindow : Window {
257  VehicleID sel;
259  VehicleType type;
260  bool generate_list;
261  bool check_unitnumber_digits;
263  VehicleList vehicle_list;
264  VehicleList wagon_list;
265  uint unitnumber_digits;
266  uint num_columns;
268  Scrollbar *vscroll;
269 
270  DepotWindow(WindowDesc &desc, TileIndex tile, VehicleType type) : Window(desc)
271  {
272  assert(IsCompanyBuildableVehicleType(type)); // ensure that we make the call with a valid type
273 
274  this->sel = INVALID_VEHICLE;
275  this->vehicle_over = INVALID_VEHICLE;
276  this->generate_list = true;
277  this->check_unitnumber_digits = true;
278  this->hovered_widget = -1;
279  this->type = type;
280  this->num_columns = 1; // for non-trains this gets set in FinishInitNested()
281  this->unitnumber_digits = 2;
282 
283  this->CreateNestedTree();
284  this->hscroll = (this->type == VEH_TRAIN ? this->GetScrollbar(WID_D_H_SCROLL) : nullptr);
285  this->vscroll = this->GetScrollbar(WID_D_V_SCROLL);
286  /* Don't show 'rename button' of aircraft hangar */
287  this->GetWidget<NWidgetStacked>(WID_D_SHOW_RENAME)->SetDisplayedPlane(type == VEH_AIRCRAFT ? SZSP_NONE : 0);
288  /* Only train depots have a horizontal scrollbar and a 'sell chain' button */
289  if (type == VEH_TRAIN) this->GetWidget<NWidgetCore>(WID_D_MATRIX)->widget_data = 1 << MAT_COL_START;
290  this->GetWidget<NWidgetStacked>(WID_D_SHOW_H_SCROLL)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_HORIZONTAL);
291  this->GetWidget<NWidgetStacked>(WID_D_SHOW_SELL_CHAIN)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_NONE);
292  this->SetupWidgetData(type);
293  this->FinishInitNested(tile);
294 
295  this->owner = GetTileOwner(tile);
297  }
298 
299  void Close([[maybe_unused]] int data = 0) override
300  {
302  CloseWindowById(GetWindowClassForVehicleType(this->type), VehicleListIdentifier(VL_DEPOT_LIST, this->type, this->owner, this->GetDepotIndex()).Pack(), false);
304  this->Window::Close();
305  }
306 
312  void DrawVehicleInDepot(const Vehicle *v, const Rect &r) const
313  {
314  bool free_wagon = false;
315 
316  bool rtl = _current_text_dir == TD_RTL;
317  Rect text = r.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix); /* Ract for text elements, horizontal is already applied. */
318  Rect image = r.Indent(this->header_width, rtl).Indent(this->count_width, !rtl); /* Rect for vehicle images */
319 
320  switch (v->type) {
321  case VEH_TRAIN: {
322  const Train *u = Train::From(v);
323  free_wagon = u->IsFreeWagon();
324 
325  uint x_space = free_wagon ?
326  ScaleSpriteTrad(_consistent_train_width != 0 ? _consistent_train_width : TRAININFO_DEFAULT_VEHICLE_WIDTH) :
327  0;
328 
329  DrawTrainImage(u, image.Indent(x_space, rtl), this->sel, EIT_IN_DEPOT, free_wagon ? 0 : this->hscroll->GetPosition(), this->vehicle_over);
330 
331  /* Length of consist in tiles with 1 fractional digit (rounded up) */
333  SetDParam(1, 1);
334  Rect count = text.WithWidth(this->count_width - WidgetDimensions::scaled.hsep_normal, !rtl);
335  DrawString(count.left, count.right, count.bottom - GetCharacterHeight(FS_SMALL) + 1, STR_JUST_DECIMAL, TC_BLACK, SA_RIGHT, false, FS_SMALL); // Draw the counter
336  break;
337  }
338 
339  case VEH_ROAD: DrawRoadVehImage( v, image, this->sel, EIT_IN_DEPOT); break;
340  case VEH_SHIP: DrawShipImage( v, image, this->sel, EIT_IN_DEPOT); break;
341  case VEH_AIRCRAFT: DrawAircraftImage(v, image, this->sel, EIT_IN_DEPOT); break;
342  default: NOT_REACHED();
343  }
344 
345  uint diff_x, diff_y;
346  if (v->IsGroundVehicle()) {
347  /* Arrange unitnumber and flag horizontally */
348  diff_x = this->flag_size.width + WidgetDimensions::scaled.hsep_normal;
349  diff_y = WidgetDimensions::scaled.matrix.top;
350  } else {
351  /* Arrange unitnumber and flag vertically */
352  diff_x = 0;
354  }
355 
356  text = text.WithWidth(this->header_width - WidgetDimensions::scaled.hsep_normal, rtl).WithHeight(GetCharacterHeight(FS_NORMAL)).Indent(diff_x, rtl);
357  if (free_wagon) {
358  DrawString(text, STR_DEPOT_NO_ENGINE);
359  } else {
360  Rect flag = r.WithWidth(this->flag_size.width, rtl).WithHeight(this->flag_size.height).Translate(0, diff_y);
361  DrawSpriteIgnorePadding((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, flag, SA_CENTER);
362 
363  SetDParam(0, v->unitnumber);
364  DrawString(text, STR_JUST_COMMA, (v->max_age - CalendarTime::DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED);
365  }
366  }
367 
368  void DrawWidget(const Rect &r, WidgetID widget) const override
369  {
370  if (widget != WID_D_MATRIX) return;
371 
372  bool rtl = _current_text_dir == TD_RTL;
373 
374  /* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
375  const NWidgetCore *wid = this->GetWidget<NWidgetCore>(WID_D_MATRIX);
376 
377  /* Set up rect for each cell */
378  Rect ir = r.WithHeight(this->resize.step_height);
379  if (this->num_columns != 1) ir = ir.WithWidth(this->resize.step_width, rtl);
380  ir = ir.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero);
381 
382  /* Draw vertical separators at whole tiles.
383  * This only works in two cases:
384  * - All vehicles use VEHICLEINFO_FULL_VEHICLE_WIDTH as reference width.
385  * - All vehicles are 8/8. This cannot be checked for NewGRF, so instead we check for "all vehicles are original vehicles".
386  */
387  if (this->type == VEH_TRAIN && _consistent_train_width != 0) {
389  int col = GetColourGradient(wid->colour, SHADE_NORMAL);
390  Rect image = ir.Indent(this->header_width, rtl).Indent(this->count_width, !rtl);
391  int first_line = w + (-this->hscroll->GetPosition()) % w;
392  if (rtl) {
393  for (int x = image.right - first_line; x >= image.left; x -= w) {
394  GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
395  }
396  } else {
397  for (int x = image.left + first_line; x <= image.right; x += w) {
398  GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
399  }
400  }
401  }
402 
403  uint16_t rows_in_display = wid->current_y / wid->resize_y;
404 
405  uint num = this->vscroll->GetPosition() * this->num_columns;
406  uint maxval = static_cast<uint>(std::min<size_t>(this->vehicle_list.size(), num + (rows_in_display * this->num_columns)));
407  for (; num < maxval; ir = ir.Translate(0, this->resize.step_height)) { // Draw the rows
408  Rect cell = ir; /* Keep track of horizontal cells */
409  for (uint i = 0; i < this->num_columns && num < maxval; i++, num++) {
410  /* Draw all vehicles in the current row */
411  const Vehicle *v = this->vehicle_list[num];
412  this->DrawVehicleInDepot(v, cell);
413  cell = cell.Translate(rtl ? -(int)this->resize.step_width : (int)this->resize.step_width, 0);
414  }
415  }
416 
417  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)));
418 
419  /* Draw the train wagons without an engine in front. */
420  for (; num < maxval; num++, ir = ir.Translate(0, this->resize.step_height)) {
421  const Vehicle *v = this->wagon_list[num - this->vehicle_list.size()];
422  this->DrawVehicleInDepot(v, ir);
423  }
424  }
425 
426  void SetStringParameters(WidgetID widget) const override
427  {
428  if (widget != WID_D_CAPTION) return;
429 
430  SetDParam(0, this->type);
431  SetDParam(1, this->GetDepotIndex());
432  }
433 
435  const Vehicle *head;
436  const Vehicle *wagon;
437  };
438 
439  enum DepotGUIAction {
440  MODE_ERROR,
441  MODE_DRAG_VEHICLE,
442  MODE_SHOW_VEHICLE,
443  MODE_START_STOP,
444  };
445 
446  DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d)
447  {
448  this->RefreshVehicleList();
449 
450  const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(WID_D_MATRIX);
451  /* Make X relative to widget. Y is left alone for GetScrolledRowFromWidget(). */
452  x -= matrix_widget->pos_x;
453  /* In case of RTL the widgets are swapped as a whole */
454  if (_current_text_dir == TD_RTL) x = matrix_widget->current_x - x;
455 
456  uint xt = 0, xm = 0, ym = 0;
457  if (this->type == VEH_TRAIN) {
458  xm = x;
459  } else {
460  xt = x / this->resize.step_width;
461  xm = x % this->resize.step_width;
462  if (xt >= this->num_columns) return MODE_ERROR;
463  }
464  ym = (y - matrix_widget->pos_y) % this->resize.step_height;
465 
466  int32_t row = this->vscroll->GetScrolledRowFromWidget(y, this, WID_D_MATRIX);
467  uint pos = (row * this->num_columns) + xt;
468 
469  if (row == INT32_MAX || this->vehicle_list.size() + this->wagon_list.size() <= pos) {
470  /* Clicking on 'line' / 'block' without a vehicle */
471  if (this->type == VEH_TRAIN) {
472  /* End the dragging */
473  d->head = nullptr;
474  d->wagon = nullptr;
475  return MODE_DRAG_VEHICLE;
476  } else {
477  return MODE_ERROR; // empty block, so no vehicle is selected
478  }
479  }
480 
481  bool wagon = false;
482  if (this->vehicle_list.size() > pos) {
483  *veh = this->vehicle_list[pos];
484  /* Skip vehicles that are scrolled off the list */
485  if (this->type == VEH_TRAIN) x += this->hscroll->GetPosition();
486  } else {
487  pos -= (uint)this->vehicle_list.size();
488  *veh = this->wagon_list[pos];
489  /* free wagons don't have an initial loco. */
490  x -= ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH);
491  wagon = true;
492  }
493 
494  const Train *v = nullptr;
495  if (this->type == VEH_TRAIN) {
496  v = Train::From(*veh);
497  d->head = d->wagon = v;
498  }
499 
500  if (xm <= this->header_width) {
501  switch (this->type) {
502  case VEH_TRAIN:
503  if (wagon) return MODE_ERROR;
504  [[fallthrough]];
505 
506  case VEH_ROAD:
507  if (xm <= this->flag_size.width) return MODE_START_STOP;
508  break;
509 
510  case VEH_SHIP:
511  case VEH_AIRCRAFT:
512  if (xm <= this->flag_size.width && ym >= (uint)(GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal)) return MODE_START_STOP;
513  break;
514 
515  default: NOT_REACHED();
516  }
517  return MODE_SHOW_VEHICLE;
518  }
519 
520  if (this->type != VEH_TRAIN) return MODE_DRAG_VEHICLE;
521 
522  /* Clicking on the counter */
523  if (xm >= matrix_widget->current_x - this->count_width) return wagon ? MODE_ERROR : MODE_SHOW_VEHICLE;
524 
525  /* Account for the header */
526  x -= this->header_width;
527 
528  /* find the vehicle in this row that was clicked */
529  for (; v != nullptr; v = v->Next()) {
530  x -= v->GetDisplayImageWidth();
531  if (x < 0) break;
532  }
533 
534  d->wagon = (v != nullptr ? v->GetFirstEnginePart() : nullptr);
535 
536  return MODE_DRAG_VEHICLE;
537  }
538 
544  void DepotClick(int x, int y)
545  {
546  GetDepotVehiclePtData gdvp = { nullptr, nullptr };
547  const Vehicle *v = nullptr;
548  DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp);
549 
550  if (this->type == VEH_TRAIN) v = gdvp.wagon;
551 
552  switch (mode) {
553  case MODE_ERROR: // invalid
554  return;
555 
556  case MODE_DRAG_VEHICLE: { // start dragging of vehicle
557  if (v != nullptr && VehicleClicked(v)) return;
558 
559  VehicleID sel = this->sel;
560 
561  if (this->type == VEH_TRAIN && sel != INVALID_VEHICLE) {
562  this->sel = INVALID_VEHICLE;
563  TrainDepotMoveVehicle(v, sel, gdvp.head);
564  } else if (v != nullptr) {
565  SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
567  _cursor.vehchain = _ctrl_pressed;
568 
569  this->sel = v->index;
570  this->SetDirty();
571  }
572  break;
573  }
574 
575  case MODE_SHOW_VEHICLE: // show info window
577  break;
578 
579  case MODE_START_STOP: // click start/stop flag
580  StartStopVehicle(v, false);
581  break;
582 
583  default: NOT_REACHED();
584  }
585  }
586 
594  {
595  this->GetWidget<NWidgetCore>(WID_D_STOP_ALL)->tool_tip = STR_DEPOT_MASS_STOP_DEPOT_TRAIN_TOOLTIP + type;
596  this->GetWidget<NWidgetCore>(WID_D_START_ALL)->tool_tip = STR_DEPOT_MASS_START_DEPOT_TRAIN_TOOLTIP + type;
597  this->GetWidget<NWidgetCore>(WID_D_SELL)->tool_tip = STR_DEPOT_TRAIN_SELL_TOOLTIP + type;
598  this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->tool_tip = STR_DEPOT_SELL_ALL_BUTTON_TRAIN_TOOLTIP + type;
599 
600  this->GetWidget<NWidgetCore>(WID_D_BUILD)->SetDataTip(STR_DEPOT_TRAIN_NEW_VEHICLES_BUTTON + type, STR_DEPOT_TRAIN_NEW_VEHICLES_TOOLTIP + type);
601  this->GetWidget<NWidgetCore>(WID_D_CLONE)->SetDataTip(STR_DEPOT_CLONE_TRAIN + type, STR_DEPOT_CLONE_TRAIN_DEPOT_INFO + type);
602 
603  this->GetWidget<NWidgetCore>(WID_D_LOCATION)->tool_tip = STR_DEPOT_TRAIN_LOCATION_TOOLTIP + type;
604  this->GetWidget<NWidgetCore>(WID_D_VEHICLE_LIST)->tool_tip = STR_DEPOT_VEHICLE_ORDER_LIST_TRAIN_TOOLTIP + type;
605  this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->tool_tip = STR_DEPOT_AUTOREPLACE_TRAIN_TOOLTIP + type;
606  this->GetWidget<NWidgetCore>(WID_D_MATRIX)->tool_tip = STR_DEPOT_TRAIN_LIST_TOOLTIP + this->type;
607 
608  switch (type) {
609  default: NOT_REACHED();
610 
611  case VEH_TRAIN:
612  this->GetWidget<NWidgetCore>(WID_D_VEHICLE_LIST)->widget_data = STR_TRAIN;
613 
614  /* Sprites */
615  this->GetWidget<NWidgetCore>(WID_D_SELL)->widget_data = SPR_SELL_TRAIN;
616  this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->widget_data = SPR_SELL_ALL_TRAIN;
617  this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->widget_data = SPR_REPLACE_TRAIN;
618  break;
619 
620  case VEH_ROAD:
621  this->GetWidget<NWidgetCore>(WID_D_VEHICLE_LIST)->widget_data = STR_LORRY;
622 
623  /* Sprites */
624  this->GetWidget<NWidgetCore>(WID_D_SELL)->widget_data = SPR_SELL_ROADVEH;
625  this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->widget_data = SPR_SELL_ALL_ROADVEH;
626  this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->widget_data = SPR_REPLACE_ROADVEH;
627  break;
628 
629  case VEH_SHIP:
630  this->GetWidget<NWidgetCore>(WID_D_VEHICLE_LIST)->widget_data = STR_SHIP;
631 
632  /* Sprites */
633  this->GetWidget<NWidgetCore>(WID_D_SELL)->widget_data = SPR_SELL_SHIP;
634  this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->widget_data = SPR_SELL_ALL_SHIP;
635  this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->widget_data = SPR_REPLACE_SHIP;
636  break;
637 
638  case VEH_AIRCRAFT:
639  this->GetWidget<NWidgetCore>(WID_D_VEHICLE_LIST)->widget_data = STR_PLANE;
640 
641  /* Sprites */
642  this->GetWidget<NWidgetCore>(WID_D_SELL)->widget_data = SPR_SELL_AIRCRAFT;
643  this->GetWidget<NWidgetCore>(WID_D_SELL_ALL)->widget_data = SPR_SELL_ALL_AIRCRAFT;
644  this->GetWidget<NWidgetCore>(WID_D_AUTOREPLACE)->widget_data = SPR_REPLACE_AIRCRAFT;
645  break;
646  }
647  }
648 
649  uint count_width;
653 
654  void OnInit() override
655  {
656  this->cell_size = GetVehicleImageCellSize(this->type, EIT_IN_DEPOT);
657  this->flag_size = maxdim(GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED), GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING));
658  }
659 
660  void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
661  {
662  switch (widget) {
663  case WID_D_MATRIX: {
664  uint min_height = 0;
665 
666  if (this->type == VEH_TRAIN) {
667  SetDParamMaxValue(0, 1000, 0, FS_SMALL);
668  SetDParam(1, 1);
669  this->count_width = GetStringBoundingBox(STR_JUST_DECIMAL, FS_SMALL).width + WidgetDimensions::scaled.hsep_normal;
670  } else {
671  this->count_width = 0;
672  }
673 
674  SetDParamMaxDigits(0, this->unitnumber_digits);
675  Dimension unumber = GetStringBoundingBox(STR_JUST_COMMA);
676 
677  if (this->type == VEH_TRAIN || this->type == VEH_ROAD) {
678  min_height = std::max<uint>(unumber.height, this->flag_size.height);
679  this->header_width = unumber.width + WidgetDimensions::scaled.hsep_normal + this->flag_size.width + WidgetDimensions::scaled.hsep_normal;
680  } else {
681  min_height = unumber.height + WidgetDimensions::scaled.vsep_normal + this->flag_size.height;
682  this->header_width = std::max<uint>(unumber.width, this->flag_size.width) + WidgetDimensions::scaled.hsep_normal;
683  }
684  int base_width = this->count_width + this->header_width + padding.width;
685 
686  resize.height = std::max<uint>(this->cell_size.height, min_height + padding.height);
687  if (this->type == VEH_TRAIN) {
688  resize.width = 1;
689  size.width = base_width + 2 * ScaleSpriteTrad(29); // about 2 parts
690  size.height = resize.height * 6;
691  } else {
692  resize.width = base_width + this->cell_size.extend_left + this->cell_size.extend_right;
693  size.width = resize.width * (this->type == VEH_ROAD ? 5 : 3);
694  size.height = resize.height * (this->type == VEH_ROAD ? 5 : 3);
695  }
696  fill.width = resize.width;
697  fill.height = resize.height;
698  break;
699  }
700  }
701  }
702 
708  void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
709  {
710  this->generate_list = true;
711  }
712 
713  void RefreshVehicleList()
714  {
715  if (this->generate_list) {
716  /* Generate the vehicle list
717  * It's ok to use the wagon pointers for non-trains as they will be ignored */
718  BuildDepotVehicleList(this->type, this->window_number, &this->vehicle_list, &this->wagon_list);
719  this->generate_list = false;
720  DepotSortList(&this->vehicle_list);
721 
722  this->check_unitnumber_digits = true;
723  }
724  }
725 
726  void OnPaint() override
727  {
728  this->RefreshVehicleList();
729 
730  if (this->check_unitnumber_digits) {
731  this->check_unitnumber_digits = false;
732  uint new_unitnumber_digits = GetUnitNumberDigits(this->vehicle_list);
733  /* Only increase the size; do not decrease to prevent constant changes */
734  if (this->unitnumber_digits < new_unitnumber_digits) {
735  this->unitnumber_digits = new_unitnumber_digits;
736  this->ReInit();
737  }
738  }
739 
740  /* determine amount of items for scroller */
741  if (this->type == VEH_TRAIN) {
742  uint max_width = ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH);
743  for (uint num = 0; num < this->vehicle_list.size(); num++) {
744  uint width = 0;
745  for (const Train *v = Train::From(this->vehicle_list[num]); v != nullptr; v = v->Next()) {
746  width += v->GetDisplayImageWidth();
747  }
748  max_width = std::max(max_width, width);
749  }
750  /* Always have 1 empty row, so people can change the setting of the train */
751  this->vscroll->SetCount(this->vehicle_list.size() + this->wagon_list.size() + 1);
752  /* 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 */
753  this->hscroll->SetCount(max_width + ScaleSpriteTrad(2 * VEHICLEINFO_FULL_VEHICLE_WIDTH + 1));
754  } else {
755  this->vscroll->SetCount(CeilDiv((uint)this->vehicle_list.size(), this->num_columns));
756  }
757 
758  /* Setup disabled buttons. */
759  TileIndex tile = this->window_number;
763  WID_D_SELL,
766  WID_D_BUILD,
767  WID_D_CLONE,
768  WID_D_RENAME,
770 
771  this->DrawWidgets();
772  }
773 
774  void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
775  {
776  switch (widget) {
777  case WID_D_MATRIX: // List
778  this->DepotClick(pt.x, pt.y);
779  break;
780 
781  case WID_D_BUILD: // Build vehicle
783  ShowBuildVehicleWindow(this->window_number, this->type);
784  break;
785 
786  case WID_D_CLONE: // Clone button
789 
790  if (this->IsWidgetLowered(WID_D_CLONE)) {
791  static const CursorID clone_icons[] = {
792  SPR_CURSOR_CLONE_TRAIN, SPR_CURSOR_CLONE_ROADVEH,
793  SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
794  };
795 
796  SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_VEHICLE, this);
797  } else {
799  }
800  break;
801 
802  case WID_D_LOCATION:
803  if (_ctrl_pressed) {
805  } else {
807  }
808  break;
809 
810  case WID_D_RENAME: // Rename button
811  SetDParam(0, this->type);
812  SetDParam(1, Depot::GetByTile((TileIndex)this->window_number)->index);
813  ShowQueryString(STR_DEPOT_NAME, STR_DEPOT_RENAME_DEPOT_CAPTION, MAX_LENGTH_DEPOT_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
814  break;
815 
816  case WID_D_STOP_ALL:
817  case WID_D_START_ALL: {
818  VehicleListIdentifier vli(VL_DEPOT_LIST, this->type, this->owner);
820  break;
821  }
822 
823  case WID_D_SELL_ALL:
824  /* Only open the confirmation window if there are anything to sell */
825  if (!this->vehicle_list.empty() || !this->wagon_list.empty()) {
826  SetDParam(0, this->type);
827  SetDParam(1, this->GetDepotIndex());
828  ShowQuery(
829  STR_DEPOT_CAPTION,
830  STR_DEPOT_SELL_CONFIRMATION_TEXT,
831  this,
832  DepotSellAllConfirmationCallback
833  );
834  }
835  break;
836 
837  case WID_D_VEHICLE_LIST:
838  ShowVehicleListWindow(GetTileOwner(this->window_number), this->type, (TileIndex)this->window_number);
839  break;
840 
841  case WID_D_AUTOREPLACE:
843  break;
844 
845  }
846  }
847 
848  void OnQueryTextFinished(std::optional<std::string> str) override
849  {
850  if (!str.has_value()) return;
851 
852  /* Do depot renaming */
853  Command<CMD_RENAME_DEPOT>::Post(STR_ERROR_CAN_T_RENAME_DEPOT, this->GetDepotIndex(), *str);
854  }
855 
856  bool OnRightClick([[maybe_unused]] Point pt, WidgetID widget) override
857  {
858  if (widget != WID_D_MATRIX) return false;
859 
860  GetDepotVehiclePtData gdvp = { nullptr, nullptr };
861  const Vehicle *v = nullptr;
862  DepotGUIAction mode = this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp);
863 
864  if (this->type == VEH_TRAIN) v = gdvp.wagon;
865 
866  if (v == nullptr || mode != MODE_DRAG_VEHICLE) return false;
867 
868  CargoArray capacity{}, loaded{};
869 
870  /* Display info for single (articulated) vehicle, or for whole chain starting with selected vehicle */
871  bool whole_chain = (this->type == VEH_TRAIN && _ctrl_pressed);
872 
873  /* loop through vehicle chain and collect cargoes */
874  uint num = 0;
875  for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
876  if (w->cargo_cap > 0 && w->cargo_type < NUM_CARGO) {
877  capacity[w->cargo_type] += w->cargo_cap;
878  loaded [w->cargo_type] += w->cargo.StoredCount();
879  }
880 
881  if (w->type == VEH_TRAIN && !w->HasArticulatedPart()) {
882  num++;
883  if (!whole_chain) break;
884  }
885  }
886 
887  /* Build tooltipstring */
888  static std::string details;
889  details.clear();
890 
891  for (const CargoSpec *cs : _sorted_cargo_specs) {
892  CargoID cargo_type = cs->Index();
893  if (capacity[cargo_type] == 0) continue;
894 
895  SetDParam(0, cargo_type); // {CARGO} #1
896  SetDParam(1, loaded[cargo_type]); // {CARGO} #2
897  SetDParam(2, cargo_type); // {SHORTCARGO} #1
898  SetDParam(3, capacity[cargo_type]); // {SHORTCARGO} #2
899  AppendStringInPlace(details, STR_DEPOT_VEHICLE_TOOLTIP_CARGO);
900  }
901 
902  /* Show tooltip window */
903  SetDParam(0, whole_chain ? num : v->engine_type);
904  SetDParamStr(1, details);
905  GuiShowTooltips(this, whole_chain ? STR_DEPOT_VEHICLE_TOOLTIP_CHAIN : STR_DEPOT_VEHICLE_TOOLTIP, TCC_RIGHT_CLICK, 2);
906 
907  return true;
908  }
909 
915  bool OnVehicleSelect(const Vehicle *v) override
916  {
917  if (_ctrl_pressed) {
918  /* Share-clone, do not open new viewport, and keep tool active */
919  Command<CMD_CLONE_VEHICLE>::Post(STR_ERROR_CAN_T_BUY_TRAIN + v->type, this->window_number, v->index, true);
920  } else {
921  /* Copy-clone, open viewport for new vehicle, and deselect the tool (assume player wants to change things on new vehicle) */
922  if (Command<CMD_CLONE_VEHICLE>::Post(STR_ERROR_CAN_T_BUY_TRAIN + v->type, CcCloneVehicle, this->window_number, v->index, false)) {
924  }
925  }
926 
927  return true;
928  }
929 
936  bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
937  {
938  if (!_ctrl_pressed) {
939  /* If CTRL is not pressed: If all the vehicles in this list have the same orders, then copy orders */
940  if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
941  return VehiclesHaveSameEngineList(v1, v2);
942  })) {
943  if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
944  return VehiclesHaveSameOrderList(v1, v2);
945  })) {
946  OnVehicleSelect(*begin);
947  } else {
948  ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST, WL_INFO);
949  }
950  } else {
951  ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, WL_INFO);
952  }
953  } else {
954  /* If CTRL is pressed: If all the vehicles in this list share orders, then copy orders */
955  if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
956  return VehiclesHaveSameEngineList(v1, v2);
957  })) {
958  if (AllEqual(begin, end, [](const Vehicle *v1, const Vehicle *v2) {
959  return v1->FirstShared() == v2->FirstShared();
960  })) {
961  OnVehicleSelect(*begin);
962  } else {
963  ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST, WL_INFO);
964  }
965  } else {
966  ShowErrorMessage(STR_ERROR_CAN_T_BUY_TRAIN + (*begin)->type, STR_ERROR_CAN_T_CLONE_VEHICLE_LIST, WL_INFO);
967  }
968  }
969 
970  return true;
971  }
972 
973  void OnPlaceObjectAbort() override
974  {
975  /* abort clone */
976  this->RaiseWidget(WID_D_CLONE);
978 
979  /* abort drag & drop */
980  this->sel = INVALID_VEHICLE;
981  this->vehicle_over = INVALID_VEHICLE;
983 
984  if (this->hovered_widget != -1) {
985  this->SetWidgetLoweredState(this->hovered_widget, false);
986  this->SetWidgetDirty(this->hovered_widget);
987  this->hovered_widget = -1;
988  }
989  }
990 
991  bool last_overlay_state;
992  void OnMouseLoop() override
993  {
994  if (last_overlay_state != ShowCargoIconOverlay()) {
995  last_overlay_state = ShowCargoIconOverlay();
996  this->SetDirty();
997  }
998  }
999 
1000  void OnMouseDrag(Point pt, WidgetID widget) override
1001  {
1002  if (this->sel == INVALID_VEHICLE) return;
1003  if (widget != this->hovered_widget) {
1004  if (this->hovered_widget == WID_D_SELL || this->hovered_widget == WID_D_SELL_CHAIN) {
1005  this->SetWidgetLoweredState(this->hovered_widget, false);
1006  this->SetWidgetDirty(this->hovered_widget);
1007  }
1008  this->hovered_widget = widget;
1009  if (this->hovered_widget == WID_D_SELL || this->hovered_widget == WID_D_SELL_CHAIN) {
1010  this->SetWidgetLoweredState(this->hovered_widget, true);
1011  this->SetWidgetDirty(this->hovered_widget);
1012  }
1013  }
1014  if (this->type != VEH_TRAIN) return;
1015 
1016  /* A rail vehicle is dragged.. */
1017  if (widget != WID_D_MATRIX) { // ..outside of the depot matrix.
1018  if (this->vehicle_over != INVALID_VEHICLE) {
1019  this->vehicle_over = INVALID_VEHICLE;
1021  }
1022  return;
1023  }
1024 
1025  const Vehicle *v = nullptr;
1026  GetDepotVehiclePtData gdvp = {nullptr, nullptr};
1027 
1028  if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp) != MODE_DRAG_VEHICLE) return;
1029 
1030  VehicleID new_vehicle_over = INVALID_VEHICLE;
1031  if (gdvp.head != nullptr) {
1032  if (gdvp.wagon == nullptr && gdvp.head->Last()->index != this->sel) { // ..at the end of the train.
1033  /* 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
1034  * destination inside a train. This head index is then used to indicate that a wagon is inserted at
1035  * the end of the train.
1036  */
1037  new_vehicle_over = gdvp.head->index;
1038  } else if (gdvp.wagon != nullptr && gdvp.head != gdvp.wagon &&
1039  gdvp.wagon->index != this->sel &&
1040  gdvp.wagon->Previous()->index != this->sel) { // ..over an existing wagon.
1041  new_vehicle_over = gdvp.wagon->index;
1042  }
1043  }
1044 
1045  if (this->vehicle_over == new_vehicle_over) return;
1046 
1047  this->vehicle_over = new_vehicle_over;
1048  this->SetWidgetDirty(widget);
1049  }
1050 
1051  void OnDragDrop(Point pt, WidgetID widget) override
1052  {
1053  switch (widget) {
1054  case WID_D_MATRIX: {
1055  const Vehicle *v = nullptr;
1056  VehicleID sel = this->sel;
1057 
1058  this->sel = INVALID_VEHICLE;
1059  this->SetDirty();
1060 
1061  if (this->type == VEH_TRAIN) {
1062  GetDepotVehiclePtData gdvp = { nullptr, nullptr };
1063 
1064  if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, &gdvp) == MODE_DRAG_VEHICLE && sel != INVALID_VEHICLE) {
1065  if (gdvp.wagon != nullptr && gdvp.wagon->index == sel && _ctrl_pressed) {
1066  Command<CMD_REVERSE_TRAIN_DIRECTION>::Post(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE, Vehicle::Get(sel)->tile, Vehicle::Get(sel)->index, true);
1067  } else if (gdvp.wagon == nullptr || gdvp.wagon->index != sel) {
1068  this->vehicle_over = INVALID_VEHICLE;
1069  TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
1070  } else if (gdvp.head != nullptr && gdvp.head->IsFrontEngine()) {
1071  ShowVehicleViewWindow(gdvp.head);
1072  }
1073  }
1074  } else if (this->GetVehicleFromDepotWndPt(pt.x, pt.y, &v, nullptr) == MODE_DRAG_VEHICLE && v != nullptr && sel == v->index) {
1076  }
1077  break;
1078  }
1079 
1080  case WID_D_SELL: case WID_D_SELL_CHAIN: {
1081  if (this->IsWidgetDisabled(widget)) return;
1082  if (this->sel == INVALID_VEHICLE) return;
1083 
1084  this->HandleButtonClick(widget);
1085 
1086  const Vehicle *v = Vehicle::Get(this->sel);
1087  this->sel = INVALID_VEHICLE;
1088  this->SetDirty();
1089 
1090  bool sell_cmd = (v->type == VEH_TRAIN && (widget == WID_D_SELL_CHAIN || _ctrl_pressed));
1091  Command<CMD_SELL_VEHICLE>::Post(GetCmdSellVehMsg(v->type), v->tile, v->index, sell_cmd, true, INVALID_CLIENT_ID);
1092  break;
1093  }
1094 
1095  default:
1096  this->sel = INVALID_VEHICLE;
1097  this->SetDirty();
1098  break;
1099  }
1100  this->hovered_widget = -1;
1101  _cursor.vehchain = false;
1102  }
1103 
1104  void OnTimeout() override
1105  {
1106  if (!this->IsWidgetDisabled(WID_D_SELL)) {
1107  this->RaiseWidget(WID_D_SELL);
1108  this->SetWidgetDirty(WID_D_SELL);
1109  }
1110  if (this->GetWidget<NWidgetBase>(WID_D_SELL) != nullptr && !this->IsWidgetDisabled(WID_D_SELL_CHAIN)) {
1113  }
1114  }
1115 
1116  void OnResize() override
1117  {
1118  this->vscroll->SetCapacityFromWidget(this, WID_D_MATRIX);
1119  NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_D_MATRIX);
1120  if (this->type == VEH_TRAIN) {
1121  this->hscroll->SetCapacity(nwi->current_x - this->header_width - this->count_width);
1122  } else {
1123  this->num_columns = nwi->current_x / nwi->resize_x;
1124  }
1125  }
1126 
1128  {
1129  if (this->sel != INVALID_VEHICLE) {
1130  _cursor.vehchain = _ctrl_pressed;
1132  return ES_HANDLED;
1133  }
1134 
1135  return ES_NOT_HANDLED;
1136  }
1137 
1143  inline uint16_t GetDepotIndex() const
1144  {
1145  return (this->type == VEH_AIRCRAFT) ? ::GetStationIndex(this->window_number) : ::GetDepotIndex(this->window_number);
1146  }
1147 };
1148 
1149 static void DepotSellAllConfirmationCallback(Window *win, bool confirmed)
1150 {
1151  if (confirmed) {
1152  DepotWindow *w = (DepotWindow*)win;
1153  TileIndex tile = w->window_number;
1154  VehicleType vehtype = w->type;
1156  }
1157 }
1158 
1165 {
1166  if (BringWindowToFrontById(WC_VEHICLE_DEPOT, tile) != nullptr) return;
1167 
1168  switch (type) {
1169  default: NOT_REACHED();
1170  case VEH_TRAIN: new DepotWindow(_train_depot_desc, tile, type); break;
1171  case VEH_ROAD: new DepotWindow(_road_depot_desc, tile, type); break;
1172  case VEH_SHIP: new DepotWindow(_ship_depot_desc, tile, type); break;
1173  case VEH_AIRCRAFT: new DepotWindow(_aircraft_depot_desc, tile, type); break;
1174  }
1175 }
1176 
1182 {
1183  DepotWindow *w;
1184 
1185  /* If we haven't got any vehicles on the mouse pointer, we haven't got any highlighted in any depots either
1186  * If that is the case, we can skip looping though the windows and save time
1187  */
1188  if (_special_mouse_mode != WSM_DRAGDROP) return;
1189 
1190  w = dynamic_cast<DepotWindow*>(FindWindowById(WC_VEHICLE_DEPOT, v->tile));
1191  if (w != nullptr) {
1192  if (w->sel == v->index) ResetObjectToPlace();
1193  }
1194 }
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 CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
Definition: cargo_type.h:74
std::vector< const CargoSpec * > _sorted_cargo_specs
Cargo specifications sorted alphabetically by name.
Definition: cargotype.cpp:183
Common return value for all commands.
Definition: command_type.h:23
bool Failed() const
Did this command fail?
Definition: command_type.h:171
uint resize_x
Horizontal resize step (0 means not resizable).
Definition: widget_type.h:235
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:243
int pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:249
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:248
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:236
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:244
Base class for a 'real' widget.
Definition: widget_type.h:370
Colours colour
Colour of this widget.
Definition: widget_type.h:391
Scrollbar data structure.
Definition: widget_type.h:694
void SetCount(size_t num)
Sets the number of elements in the list.
Definition: widget_type.h:780
void SetCapacity(size_t capacity)
Set the capacity of visible elements.
Definition: widget_type.h:794
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:2394
size_type GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:740
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:68
int vsep_normal
Normal vertical spacing.
Definition: window_gui.h:60
RectPadding matrix
Padding of WWT_MATRIX items.
Definition: window_gui.h:44
int hsep_normal
Normal horizontal spacing.
Definition: window_gui.h:63
Functions related to commands.
Commands
List of commands.
Definition: command_type.h:187
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
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...
Definition: depot_gui.cpp:218
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,...
Definition: depot_gui.cpp:152
void DeleteDepotHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a depot window.
Definition: depot_gui.cpp:1181
static VehicleCellSize _base_block_sizes_depot[VEH_COMPANY_END]
Cell size for vehicle images in the depot view.
Definition: depot_gui.cpp:150
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
Definition: depot_gui.cpp:1164
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type)
Get the GUI cell size for a vehicle image.
Definition: depot_gui.cpp:161
void CcCloneVehicle(Commands, const CommandCost &result, VehicleID veh_id)
This is the Callback method after the cloning attempt of a vehicle.
Definition: depot_gui.cpp:123
static VehicleCellSize _base_block_sizes_purchase[VEH_COMPANY_END]
Cell size for vehicle images in the purchase list.
Definition: depot_gui.cpp:151
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.
Definition: depot_widget.h:27
@ WID_D_AUTOREPLACE
Autoreplace button.
Definition: depot_widget.h:20
@ WID_D_RENAME
Rename button.
Definition: depot_widget.h:29
@ WID_D_SELL_CHAIN
Sell chain button.
Definition: depot_widget.h:18
@ WID_D_CLONE
Clone button.
Definition: depot_widget.h:26
@ WID_D_SHOW_SELL_CHAIN
Show sell chain panel.
Definition: depot_widget.h:17
@ WID_D_SELL
Sell button.
Definition: depot_widget.h:16
@ WID_D_H_SCROLL
Horizontal scrollbar.
Definition: depot_widget.h:24
@ WID_D_SHOW_H_SCROLL
Show horizontal scrollbar panel.
Definition: depot_widget.h:23
@ WID_D_MATRIX
Matrix of vehicles.
Definition: depot_widget.h:21
@ WID_D_V_SCROLL
Vertical scrollbar.
Definition: depot_widget.h:22
@ WID_D_SELL_ALL
Sell all button.
Definition: depot_widget.h:19
@ WID_D_VEHICLE_LIST
List of vehicles.
Definition: depot_widget.h:30
@ WID_D_START_ALL
Start all button.
Definition: depot_widget.h:32
@ WID_D_SHOW_RENAME
Show rename panel.
Definition: depot_widget.h:28
@ WID_D_BUILD
Build button.
Definition: depot_widget.h:25
@ WID_D_CAPTION
Caption of window.
Definition: depot_widget.h:15
@ WID_D_STOP_ALL
Stop all button.
Definition: depot_widget.h:31
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Definition: error_gui.cpp:367
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition: error.h:24
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:851
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:657
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:38
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition: widget.cpp:54
@ SA_RIGHT
Right align the text (must be a single bit).
Definition: gfx_type.h:345
@ SA_CENTER
Center both horizontally and vertically.
Definition: gfx_type.h:353
uint32_t CursorID
The number of the cursor (sprite)
Definition: gfx_type.h:20
@ FS_SMALL
Index of the small font in the font tables.
Definition: gfx_type.h:210
@ FS_NORMAL
Index of the normal font in the font tables.
Definition: gfx_type.h:209
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition: widget_type.h:1181
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1284
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1202
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
Definition: widget_type.h:1309
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition: widget_type.h:1191
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
Definition: widget_type.h:1295
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition: widget_type.h:1126
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:940
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.
Definition: math_func.hpp:320
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, StringID str, TooltipCloseCondition close_tooltip, uint paramcount)
Shows a tooltip.
Definition: misc_gui.cpp:760
void ShowQuery(StringID caption, StringID 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...
Definition: misc_gui.cpp:1223
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:1079
@ INVALID_CLIENT_ID
Client is not part of anything.
Definition: network_type.h:50
Functions related to order backups.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition: palette.cpp:314
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:1390
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition: station_map.h:28
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
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
void AppendStringInPlace(std::string &result, StringID string)
Resolve the given StringID and append in place into an existing std::string with all the associated D...
Definition: strings.cpp:331
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
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:56
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:357
void SetDParamMaxDigits(size_t n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:143
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
Definition: strings_type.h:24
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Class for storing amounts of cargo.
Definition: cargo_type.h:114
Specification of a cargo type.
Definition: cargotype.h:71
bool vehchain
vehicle chain is dragged
Definition: gfx_type.h:150
uint header_width
Width of unit number and flag, including separator.
Definition: depot_gui.cpp:650
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
Definition: depot_gui.cpp:992
VehicleID vehicle_over
Rail vehicle over which another one is dragged, INVALID_VEHICLE if none.
Definition: depot_gui.cpp:258
void OnInvalidateData([[maybe_unused]] int data=0, [[maybe_unused]] bool gui_scope=true) override
Some data on this window has become invalid.
Definition: depot_gui.cpp:708
uint count_width
Width of length count, including separator.
Definition: depot_gui.cpp:649
void OnTimeout() override
Called when this window's timeout has been reached.
Definition: depot_gui.cpp:1104
uint num_columns
Number of columns.
Definition: depot_gui.cpp:266
uint16_t GetDepotIndex() const
Gets the DepotID of the current window.
Definition: depot_gui.cpp:1143
EventState OnCTRLStateChange() override
The state of the control key has changed.
Definition: depot_gui.cpp:1127
void SetupWidgetData(VehicleType type)
Function to set up vehicle specific widgets (mainly sprites and strings).
Definition: depot_gui.cpp:593
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
Definition: depot_gui.cpp:973
bool OnVehicleSelect(const Vehicle *v) override
Clones a vehicle.
Definition: depot_gui.cpp:915
Dimension flag_size
Size of start/stop flag.
Definition: depot_gui.cpp:651
void DepotClick(int x, int y)
Handle click in the depot matrix.
Definition: depot_gui.cpp:544
Scrollbar * hscroll
Only for trains.
Definition: depot_gui.cpp:267
bool OnVehicleSelect(VehicleList::const_iterator begin, VehicleList::const_iterator end) override
Clones a vehicle from a vehicle list.
Definition: depot_gui.cpp:936
void OnResize() override
Called after the window got resized.
Definition: depot_gui.cpp:1116
void OnPaint() override
The window must be repainted.
Definition: depot_gui.cpp:726
WidgetID hovered_widget
Index of the widget being hovered during drag/drop. -1 if no drag is in progress.
Definition: depot_gui.cpp:262
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition: depot_gui.cpp:654
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.
Definition: depot_gui.cpp:312
VehicleCellSize cell_size
Vehicle sprite cell size.
Definition: depot_gui.cpp:652
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.
Definition: engine_base.h:186
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.
Definition: widget_type.h:1075
static void Reset(TileIndex tile=INVALID_TILE, bool from_gui=true)
Reset the OrderBackups from GUI/game logic.
Coordinates of a point in 2D.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
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:214
uint step_width
Step-size of width resize changes.
Definition: window_gui.h:213
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * Next() const
Get next vehicle in the chain.
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:89
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:460
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:28
Vehicle data structure.
Definition: vehicle_base.h:244
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
Definition: vehicle_base.h:639
Vehicle * Last()
Get the last vehicle of this vehicle chain.
Definition: vehicle_base.h:651
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
TimerGameCalendar::Date age
Age in calendar days.
Definition: vehicle_base.h:292
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:726
TimerGameCalendar::Date max_age
Maximum age.
Definition: vehicle_base.h:294
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:515
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:326
High level window description.
Definition: window_gui.h:159
Data structure for an opened window.
Definition: window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:952
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition: window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1733
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:731
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition: window_gui.h:475
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:551
ResizeInfo resize
Resize information.
Definition: window_gui.h:314
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition: window_gui.h:521
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1723
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition: window_gui.h:497
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition: window_gui.h:416
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition: window_gui.h:316
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:447
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:590
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:314
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:311
void ToggleWidgetLoweredState(WidgetID widget_index)
Invert the lowered/raised status of a widget.
Definition: window_gui.h:456
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:302
Stuff related to the text buffer GUI.
@ QSF_ENABLE_DEFAULT
enable the 'Default' button ("\0" is returned)
Definition: textbuf_gui.h:21
@ QSF_LEN_IN_CHARS
the length of the string is counted in characters
Definition: textbuf_gui.h:22
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
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
Definition: viewport.cpp:3498
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:3435
@ 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).
Definition: train_cmd.cpp:581
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:3272
bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicles have the same list of orders.
Definition: vehicle.cpp:3289
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
Command definitions for vehicles.
Functions related to vehicles.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:91
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.
Definition: vehicle_type.h:78
@ EIT_PURCHASE
Vehicle drawn in purchase list, autoreplace gui, ...
Definition: vehicle_type.h:83
@ EIT_IN_DEPOT
Vehicle drawn in depot.
Definition: vehicle_type.h:80
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
@ VEH_COMPANY_END
Last company-ownable type.
Definition: vehicle_type.h:29
uint32_t VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
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:54
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2515
Functions related to (drawing on) viewports.
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:482
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:483
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:524
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:112
@ WWT_IMGBTN
(Toggle) Button with image
Definition: widget_type.h:52
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:113
@ NWID_HORIZONTAL
Horizontal container.
Definition: widget_type.h:75
@ WWT_TEXTBTN
(Toggle) Button with text
Definition: widget_type.h:55
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
@ WWT_MATRIX
Grid of rows and columns.
Definition: widget_type.h:59
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition: widget_type.h:84
@ NWID_VERTICAL
Vertical container.
Definition: widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition: widget_type.h:69
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition: widget_type.h:83
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition: widget_type.h:65
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
static constexpr uint8_t MAT_COL_START
Bits of the WWT_MATRIX widget data.
Definition: widget_type.h:22
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:1140
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition: window.cpp:1223
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1098
SpecialMouseMode _special_mouse_mode
Mode of the mouse.
Definition: window.cpp:93
Functions, definitions and such used only by the GUI.
@ WSM_DRAGDROP
Drag&drop an object.
Definition: window_gui.h:1041
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:940
@ WDP_AUTO
Find a place automatically.
Definition: window_gui.h:147
int WidgetID
Widget ID.
Definition: window_type.h:18
EventState
State of handling an event.
Definition: window_type.h:743
@ ES_HANDLED
The passed event is handled.
Definition: window_type.h:744
@ ES_NOT_HANDLED
The passed event is not handled.
Definition: window_type.h:745
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition: window_type.h:351
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:45
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers:
Definition: window_type.h:389
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition: zoom_func.h:107
int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:117