OpenTTD
vehicle_gui.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "debug.h"
12 #include "company_func.h"
13 #include "gui.h"
14 #include "textbuf_gui.h"
15 #include "command_func.h"
16 #include "vehicle_gui_base.h"
17 #include "viewport_func.h"
18 #include "newgrf_text.h"
19 #include "newgrf_debug.h"
20 #include "roadveh.h"
21 #include "train.h"
22 #include "aircraft.h"
23 #include "depot_map.h"
24 #include "group_gui.h"
25 #include "strings_func.h"
26 #include "vehicle_func.h"
27 #include "autoreplace_gui.h"
28 #include "string_func.h"
29 #include "widgets/dropdown_func.h"
30 #include "timetable.h"
31 #include "articulated_vehicles.h"
32 #include "spritecache.h"
33 #include "core/geometry_func.hpp"
34 #include "company_base.h"
35 #include "engine_func.h"
36 #include "station_base.h"
37 #include "tilehighlight_func.h"
38 #include "zoom_func.h"
39 
40 #include "safeguards.h"
41 
42 
43 Sorting _sorting;
44 
58 
59 GUIVehicleList::SortFunction * const BaseVehicleListWindow::vehicle_sorter_funcs[] = {
73 };
74 
75 const StringID BaseVehicleListWindow::vehicle_sorter_names[] = {
76  STR_SORT_BY_NUMBER,
77  STR_SORT_BY_NAME,
78  STR_SORT_BY_AGE,
79  STR_SORT_BY_PROFIT_THIS_YEAR,
80  STR_SORT_BY_PROFIT_LAST_YEAR,
81  STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE,
82  STR_SORT_BY_RELIABILITY,
83  STR_SORT_BY_MAX_SPEED,
84  STR_SORT_BY_MODEL,
85  STR_SORT_BY_VALUE,
86  STR_SORT_BY_LENGTH,
87  STR_SORT_BY_LIFE_TIME,
88  STR_SORT_BY_TIMETABLE_DELAY,
90 };
91 
92 const StringID BaseVehicleListWindow::vehicle_depot_name[] = {
93  STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT,
94  STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT,
95  STR_VEHICLE_LIST_SEND_SHIP_TO_DEPOT,
96  STR_VEHICLE_LIST_SEND_AIRCRAFT_TO_HANGAR
97 };
98 
105 {
106  uint unitnumber = 0;
107  for (const Vehicle *v : vehicles) {
108  unitnumber = max<uint>(unitnumber, v->unitnumber);
109  }
110 
111  if (unitnumber >= 10000) return 5;
112  if (unitnumber >= 1000) return 4;
113  if (unitnumber >= 100) return 3;
114 
115  /*
116  * When the smallest unit number is less than 10, it is
117  * quite likely that it will expand to become more than
118  * 10 quite soon.
119  */
120  return 2;
121 }
122 
123 void BaseVehicleListWindow::BuildVehicleList()
124 {
125  if (!this->vehicles.NeedRebuild()) return;
126 
127  DEBUG(misc, 3, "Building vehicle list type %d for company %d given index %d", this->vli.type, this->vli.company, this->vli.index);
128 
129  GenerateVehicleSortList(&this->vehicles, this->vli);
130 
132 
133  this->vehicles.RebuildDone();
134  this->vscroll->SetCount((uint)this->vehicles.size());
135 }
136 
143 Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bool show_group)
144 {
145  Dimension d = {0, 0};
146 
147  if (show_autoreplace) d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_REPLACE_VEHICLES));
148  d = maxdim(d, GetStringBoundingBox(STR_VEHICLE_LIST_SEND_FOR_SERVICING));
149  d = maxdim(d, GetStringBoundingBox(this->vehicle_depot_name[this->vli.vtype]));
150 
151  if (show_group) {
152  d = maxdim(d, GetStringBoundingBox(STR_GROUP_ADD_SHARED_VEHICLE));
153  d = maxdim(d, GetStringBoundingBox(STR_GROUP_REMOVE_ALL_VEHICLES));
154  }
155 
156  return d;
157 }
158 
165 DropDownList BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplace, bool show_group)
166 {
167  DropDownList list;
168 
169  if (show_autoreplace) list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false));
170  list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false));
171  list.emplace_back(new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false));
172 
173  if (show_group) {
174  list.emplace_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false));
175  list.emplace_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false));
176  }
177 
178  return list;
179 }
180 
181 /* cached values for VehicleNameSorter to spare many GetString() calls */
182 static const Vehicle *_last_vehicle[2] = { nullptr, nullptr };
183 
184 void BaseVehicleListWindow::SortVehicleList()
185 {
186  if (this->vehicles.Sort()) return;
187 
188  /* invalidate cached values for name sorter - vehicle names could change */
189  _last_vehicle[0] = _last_vehicle[1] = nullptr;
190 }
191 
192 void DepotSortList(VehicleList *list)
193 {
194  if (list->size() < 2) return;
195  std::sort(list->begin(), list->end(), &VehicleNumberSorter);
196 }
197 
199 static void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
200 {
201  SpriteID spr;
202 
203  /* draw profit-based coloured icons */
204  if (v->age <= VEHICLE_PROFIT_MIN_AGE) {
205  spr = SPR_PROFIT_NA;
206  } else if (v->GetDisplayProfitLastYear() < 0) {
207  spr = SPR_PROFIT_NEGATIVE;
209  spr = SPR_PROFIT_SOME;
210  } else {
211  spr = SPR_PROFIT_LOT;
212  }
213  DrawSprite(spr, PAL_NONE, x, y);
214 }
215 
217 static const uint MAX_REFIT_CYCLE = 256;
218 
228 byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
229 {
230  v_from = v_from->GetFirstEnginePart();
231  v_for = v_for->GetFirstEnginePart();
232 
233  /* Create a list of subtypes used by the various parts of v_for */
234  static std::vector<StringID> subtypes;
235  subtypes.clear();
236  for (; v_from != nullptr; v_from = v_from->HasArticulatedPart() ? v_from->GetNextArticulatedPart() : nullptr) {
237  const Engine *e_from = v_from->GetEngine();
238  if (!e_from->CanCarryCargo() || !HasBit(e_from->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
239  include(subtypes, GetCargoSubtypeText(v_from));
240  }
241 
242  byte ret_refit_cyc = 0;
243  bool success = false;
244  if (subtypes.size() > 0) {
245  /* Check whether any articulated part is refittable to 'dest_cargo_type' with a subtype listed in 'subtypes' */
246  for (Vehicle *v = v_for; v != nullptr; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr) {
247  const Engine *e = v->GetEngine();
248  if (!e->CanCarryCargo() || !HasBit(e->info.callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) continue;
249  if (!HasBit(e->info.refit_mask, dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
250 
251  CargoID old_cargo_type = v->cargo_type;
252  byte old_cargo_subtype = v->cargo_subtype;
253 
254  /* Set the 'destination' cargo */
255  v->cargo_type = dest_cargo_type;
256 
257  /* Cycle through the refits */
258  for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
259  v->cargo_subtype = refit_cyc;
260 
261  /* Make sure we don't pick up anything cached. */
262  v->First()->InvalidateNewGRFCache();
263  v->InvalidateNewGRFCache();
264 
265  StringID subtype = GetCargoSubtypeText(v);
266  if (subtype == STR_EMPTY) break;
267 
268  if (std::find(subtypes.begin(), subtypes.end(), subtype) == subtypes.end()) continue;
269 
270  /* We found something matching. */
271  ret_refit_cyc = refit_cyc;
272  success = true;
273  break;
274  }
275 
276  /* Reset the vehicle's cargo type */
277  v->cargo_type = old_cargo_type;
278  v->cargo_subtype = old_cargo_subtype;
279 
280  /* Make sure we don't taint the vehicle. */
281  v->First()->InvalidateNewGRFCache();
282  v->InvalidateNewGRFCache();
283 
284  if (success) break;
285  }
286  }
287 
288  return ret_refit_cyc;
289 }
290 
292 struct RefitOption {
294  byte subtype;
296 
302  inline bool operator != (const RefitOption &other) const
303  {
304  return other.cargo != this->cargo || other.string != this->string;
305  }
306 
312  inline bool operator == (const RefitOption &other) const
313  {
314  return other.cargo == this->cargo && other.string == this->string;
315  }
316 };
317 
318 typedef std::vector<RefitOption> SubtypeList;
319 
329 static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
330 {
331  uint y = r.top + WD_MATRIX_TOP;
332  uint current = 0;
333 
334  bool rtl = _current_text_dir == TD_RTL;
335  uint iconwidth = max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width);
336  uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
337  int linecolour = _colour_gradient[COLOUR_ORANGE][4];
338 
339  int iconleft = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT;
340  int iconcenter = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth / 2 : r.left + WD_MATRIX_LEFT + iconwidth / 2;
341  int iconinner = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT + iconwidth;
342 
343  int textleft = r.left + WD_MATRIX_LEFT + (rtl ? 0 : iconwidth + 4);
344  int textright = r.right - WD_MATRIX_RIGHT - (rtl ? iconwidth + 4 : 0);
345 
346  /* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
347  for (uint i = 0; current < pos + rows && i < NUM_CARGO; i++) {
348  for (uint j = 0; current < pos + rows && j < list[i].size(); j++) {
349  const RefitOption &refit = list[i][j];
350 
351  /* Hide subtypes if sel[0] does not match */
352  if (sel[0] != (int)i && refit.subtype != 0xFF) continue;
353 
354  /* Refit options with a position smaller than pos don't have to be drawn. */
355  if (current < pos) {
356  current++;
357  continue;
358  }
359 
360  if (list[i].size() > 1) {
361  if (refit.subtype != 0xFF) {
362  /* Draw tree lines */
363  int ycenter = y + FONT_HEIGHT_NORMAL / 2;
364  GfxDrawLine(iconcenter, y - WD_MATRIX_TOP, iconcenter, j == list[i].size() - 1 ? ycenter : y - WD_MATRIX_TOP + delta - 1, linecolour);
365  GfxDrawLine(iconcenter, ycenter, iconinner, ycenter, linecolour);
366  } else {
367  /* Draw expand/collapse icon */
368  DrawSprite(sel[0] == (int)i ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, y + (FONT_HEIGHT_NORMAL - iconheight) / 2);
369  }
370  }
371 
372  TextColour colour = (sel[0] == (int)i && (uint)sel[1] == j) ? TC_WHITE : TC_BLACK;
373  /* Get the cargo name. */
374  SetDParam(0, CargoSpec::Get(refit.cargo)->name);
375  SetDParam(1, refit.string);
376  DrawString(textleft, textright, y, STR_JUST_STRING_STRING, colour);
377 
378  y += delta;
379  current++;
380  }
381  }
382 }
383 
385 struct RefitWindow : public Window {
386  int sel[2];
397  int click_x;
399  uint8 num_vehicles;
400  bool auto_refit;
401 
406  {
407  for (uint i = 0; i < NUM_CARGO; i++) this->list[i].clear();
408  Vehicle *v = Vehicle::Get(this->window_number);
409 
410  /* Check only the selected vehicles. */
411  VehicleSet vehicles_to_refit;
412  GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
413 
414  do {
415  if (v->type == VEH_TRAIN && std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), v->index) == vehicles_to_refit.end()) continue;
416  const Engine *e = v->GetEngine();
417  CargoTypes cmask = e->info.refit_mask;
418  byte callback_mask = e->info.callback_mask;
419 
420  /* Skip this engine if it does not carry anything */
421  if (!e->CanCarryCargo()) continue;
422  /* Skip this engine if we build the list for auto-refitting and engine doesn't allow it. */
423  if (this->auto_refit && !HasBit(e->info.misc_flags, EF_AUTO_REFIT)) continue;
424 
425  /* Loop through all cargoes in the refit mask */
426  int current_index = 0;
427  const CargoSpec *cs;
429  CargoID cid = cs->Index();
430  /* Skip cargo type if it's not listed */
431  if (!HasBit(cmask, cid)) {
432  current_index++;
433  continue;
434  }
435 
436  bool first_vehicle = this->list[current_index].size() == 0;
437  if (first_vehicle) {
438  /* Keeping the current subtype is always an option. It also serves as the option in case of no subtypes */
439  this->list[current_index].push_back({cid, 0xFF, STR_EMPTY});
440  }
441 
442  /* Check the vehicle's callback mask for cargo suffixes.
443  * This is not supported for ordered refits, since subtypes only have a meaning
444  * for a specific vehicle at a specific point in time, which conflicts with shared orders,
445  * autoreplace, autorenew, clone, order restoration, ... */
446  if (this->order == INVALID_VEH_ORDER_ID && HasBit(callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
447  /* Make a note of the original cargo type. It has to be
448  * changed to test the cargo & subtype... */
449  CargoID temp_cargo = v->cargo_type;
450  byte temp_subtype = v->cargo_subtype;
451 
452  v->cargo_type = cid;
453 
454  for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
455  v->cargo_subtype = refit_cyc;
456 
457  /* Make sure we don't pick up anything cached. */
460 
461  StringID subtype = GetCargoSubtypeText(v);
462 
463  if (first_vehicle) {
464  /* Append new subtype (don't add duplicates though) */
465  if (subtype == STR_EMPTY) break;
466 
467  RefitOption option;
468  option.cargo = cid;
469  option.subtype = refit_cyc;
470  option.string = subtype;
471  include(this->list[current_index], option);
472  } else {
473  /* Intersect the subtypes of earlier vehicles with the subtypes of this vehicle */
474  if (subtype == STR_EMPTY) {
475  /* No more subtypes for this vehicle, delete all subtypes >= refit_cyc */
476  SubtypeList &l = this->list[current_index];
477  /* 0xFF item is in front, other subtypes are sorted. So just truncate the list in the right spot */
478  for (uint i = 1; i < l.size(); i++) {
479  if (l[i].subtype >= refit_cyc) {
480  l.resize(i);
481  break;
482  }
483  }
484  break;
485  } else {
486  /* Check whether the subtype matches with the subtype of earlier vehicles. */
487  uint pos = 1;
488  SubtypeList &l = this->list[current_index];
489  while (pos < l.size() && l[pos].subtype != refit_cyc) pos++;
490  if (pos < l.size() && l[pos].string != subtype) {
491  /* String mismatch, remove item keeping the order */
492  l.erase(l.begin() + pos);
493  }
494  }
495  }
496  }
497 
498  /* Reset the vehicle's cargo type */
499  v->cargo_type = temp_cargo;
500  v->cargo_subtype = temp_subtype;
501 
502  /* And make sure we haven't tainted the cache */
505  }
506  current_index++;
507  }
508  } while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
509  }
510 
515  {
516  uint scroll_row = 0;
517  uint row = 0;
518 
519  for (uint i = 0; i < NUM_CARGO; i++) {
520  for (uint j = 0; j < this->list[i].size(); j++) {
521  const RefitOption &refit = this->list[i][j];
522 
523  /* Hide subtypes if sel[0] does not match */
524  if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
525 
526  if (this->sel[0] == (int)i && (uint)this->sel[1] == j) scroll_row = row;
527 
528  row++;
529  }
530  }
531 
532  this->vscroll->SetCount(row);
533  if (scroll_row < row) this->vscroll->ScrollTowards(scroll_row);
534  }
535 
540  void SetSelection(uint click_row)
541  {
542  uint row = 0;
543 
544  for (uint i = 0; i < NUM_CARGO; i++) {
545  for (uint j = 0; j < this->list[i].size(); j++) {
546  const RefitOption &refit = this->list[i][j];
547 
548  /* Hide subtypes if sel[0] does not match */
549  if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
550 
551  if (row == click_row) {
552  this->sel[0] = i;
553  this->sel[1] = j;
554  return;
555  }
556 
557  row++;
558  }
559  }
560 
561  this->sel[0] = -1;
562  this->sel[1] = 0;
563  }
564 
570  {
571  if (this->sel[0] < 0) return nullptr;
572 
573  SubtypeList &l = this->list[this->sel[0]];
574  if ((uint)this->sel[1] >= l.size()) return nullptr;
575 
576  return &l[this->sel[1]];
577  }
578 
579  RefitWindow(WindowDesc *desc, const Vehicle *v, VehicleOrderID order, bool auto_refit) : Window(desc)
580  {
581  this->sel[0] = -1;
582  this->sel[1] = 0;
583  this->auto_refit = auto_refit;
584  this->order = order;
585  this->CreateNestedTree();
586 
587  this->vscroll = this->GetScrollbar(WID_VR_SCROLLBAR);
588  this->hscroll = (v->IsGroundVehicle() ? this->GetScrollbar(WID_VR_HSCROLLBAR) : nullptr);
589  this->GetWidget<NWidgetCore>(WID_VR_SELECT_HEADER)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
590  this->GetWidget<NWidgetCore>(WID_VR_MATRIX)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
591  NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VR_REFIT);
592  nwi->widget_data = STR_REFIT_TRAIN_REFIT_BUTTON + v->type;
593  nwi->tool_tip = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
594  this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
595  this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
596 
597  this->FinishInitNested(v->index);
598  this->owner = v->owner;
599 
600  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
601  }
602 
603  void OnInit() override
604  {
605  if (this->cargo != nullptr) {
606  /* Store the RefitOption currently in use. */
607  RefitOption current_refit_option = *(this->cargo);
608 
609  /* Rebuild the refit list */
610  this->BuildRefitList();
611  this->sel[0] = -1;
612  this->sel[1] = 0;
613  this->cargo = nullptr;
614  for (uint i = 0; this->cargo == nullptr && i < NUM_CARGO; i++) {
615  for (uint j = 0; j < list[i].size(); j++) {
616  if (list[i][j] == current_refit_option) {
617  this->sel[0] = i;
618  this->sel[1] = j;
619  this->cargo = &list[i][j];
620  break;
621  }
622  }
623  }
624 
625  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
626  this->RefreshScrollbar();
627  } else {
628  /* Rebuild the refit list */
630  }
631  }
632 
633  void OnPaint() override
634  {
635  /* Determine amount of items for scroller. */
636  if (this->hscroll != nullptr) this->hscroll->SetCount(this->vehicle_width);
637 
638  /* Calculate sprite position. */
639  NWidgetCore *vehicle_panel_display = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
640  int sprite_width = max(0, ((int)vehicle_panel_display->current_x - this->vehicle_width) / 2);
641  this->sprite_left = vehicle_panel_display->pos_x;
642  this->sprite_right = vehicle_panel_display->pos_x + vehicle_panel_display->current_x - 1;
643  if (_current_text_dir == TD_RTL) {
644  this->sprite_right -= sprite_width;
645  this->vehicle_margin = vehicle_panel_display->current_x - sprite_right;
646  } else {
647  this->sprite_left += sprite_width;
648  this->vehicle_margin = sprite_left;
649  }
650 
651  this->DrawWidgets();
652  }
653 
654  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
655  {
656  switch (widget) {
657  case WID_VR_MATRIX:
659  size->height = resize->height * 8;
660  break;
661 
663  size->height = ScaleGUITrad(GetVehicleHeight(Vehicle::Get(this->window_number)->type));
664  break;
665 
666  case WID_VR_INFO:
667  size->width = WD_FRAMERECT_LEFT + this->information_width + WD_FRAMERECT_RIGHT;
668  break;
669  }
670  }
671 
672  void SetStringParameters(int widget) const override
673  {
674  if (widget == WID_VR_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
675  }
676 
684  {
685  assert(_current_company == _local_company);
686  Vehicle *v = Vehicle::Get(this->window_number);
687  CommandCost cost = DoCommand(v->tile, this->selected_vehicle, option->cargo | option->subtype << 8 | this->num_vehicles << 16 |
688  (int)this->auto_refit << 24, DC_QUERY_COST, GetCmdRefitVeh(v->type));
689 
690  if (cost.Failed()) return INVALID_STRING_ID;
691 
692  SetDParam(0, option->cargo);
694 
695  Money money = cost.GetCost();
697  SetDParam(2, CT_MAIL);
699  if (this->order != INVALID_VEH_ORDER_ID) {
700  /* No predictable cost */
701  return STR_PURCHASE_INFO_AIRCRAFT_CAPACITY;
702  } else if (money <= 0) {
703  SetDParam(4, -money);
704  return STR_REFIT_NEW_CAPACITY_INCOME_FROM_AIRCRAFT_REFIT;
705  } else {
706  SetDParam(4, money);
707  return STR_REFIT_NEW_CAPACITY_COST_OF_AIRCRAFT_REFIT;
708  }
709  } else {
710  if (this->order != INVALID_VEH_ORDER_ID) {
711  /* No predictable cost */
712  SetDParam(2, STR_EMPTY);
713  return STR_PURCHASE_INFO_CAPACITY;
714  } else if (money <= 0) {
715  SetDParam(2, -money);
716  return STR_REFIT_NEW_CAPACITY_INCOME_FROM_REFIT;
717  } else {
718  SetDParam(2, money);
719  return STR_REFIT_NEW_CAPACITY_COST_OF_REFIT;
720  }
721  }
722  }
723 
724  void DrawWidget(const Rect &r, int widget) const override
725  {
726  switch (widget) {
728  Vehicle *v = Vehicle::Get(this->window_number);
729  DrawVehicleImage(v, this->sprite_left + WD_FRAMERECT_LEFT, this->sprite_right - WD_FRAMERECT_RIGHT,
730  r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != nullptr ? this->hscroll->GetPosition() : 0);
731 
732  /* Highlight selected vehicles. */
733  if (this->order != INVALID_VEH_ORDER_ID) break;
734  int x = 0;
735  switch (v->type) {
736  case VEH_TRAIN: {
737  VehicleSet vehicles_to_refit;
738  GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
739 
740  int left = INT32_MIN;
741  int width = 0;
742 
743  for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
744  /* Start checking. */
745  const bool contained = std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), u->index) != vehicles_to_refit.end();
746  if (contained && left == INT32_MIN) {
747  left = x - this->hscroll->GetPosition() + r.left + this->vehicle_margin;
748  width = 0;
749  }
750 
751  /* Draw a selection. */
752  if ((!contained || u->Next() == nullptr) && left != INT32_MIN) {
753  if (u->Next() == nullptr && contained) {
754  int current_width = u->GetDisplayImageWidth();
755  width += current_width;
756  x += current_width;
757  }
758 
759  int right = Clamp(left + width, 0, r.right);
760  left = max(0, left);
761 
762  if (_current_text_dir == TD_RTL) {
763  right = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->current_x - left;
764  left = right - width;
765  }
766 
767  if (left != right) {
768  DrawFrameRect(left, r.top + WD_FRAMERECT_TOP, right, r.top + WD_FRAMERECT_TOP + ScaleGUITrad(14) - 1, COLOUR_WHITE, FR_BORDERONLY);
769  }
770 
771  left = INT32_MIN;
772  }
773 
774  int current_width = u->GetDisplayImageWidth();
775  width += current_width;
776  x += current_width;
777  }
778  break;
779  }
780 
781  default: break;
782  }
783  break;
784  }
785 
786  case WID_VR_MATRIX:
787  DrawVehicleRefitWindow(this->list, this->sel, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->resize.step_height, r);
788  break;
789 
790  case WID_VR_INFO:
791  if (this->cargo != nullptr) {
792  StringID string = this->GetCapacityString(this->cargo);
793  if (string != INVALID_STRING_ID) {
795  r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM, string);
796  }
797  }
798  break;
799  }
800  }
801 
807  void OnInvalidateData(int data = 0, bool gui_scope = true) override
808  {
809  switch (data) {
810  case VIWD_AUTOREPLACE: // Autoreplace replaced the vehicle; selected_vehicle became invalid.
811  case VIWD_CONSIST_CHANGED: { // The consist has changed; rebuild the entire list.
812  /* Clear the selection. */
813  Vehicle *v = Vehicle::Get(this->window_number);
814  this->selected_vehicle = v->index;
815  this->num_vehicles = UINT8_MAX;
816  FALLTHROUGH;
817  }
818 
819  case 2: { // The vehicle selection has changed; rebuild the entire list.
820  if (!gui_scope) break;
821  this->BuildRefitList();
822 
823  /* The vehicle width has changed too. */
824  this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
825  uint max_width = 0;
826 
827  /* Check the width of all cargo information strings. */
828  for (uint i = 0; i < NUM_CARGO; i++) {
829  for (uint j = 0; j < this->list[i].size(); j++) {
830  StringID string = this->GetCapacityString(&list[i][j]);
831  if (string != INVALID_STRING_ID) {
832  Dimension dim = GetStringBoundingBox(string);
833  max_width = max(dim.width, max_width);
834  }
835  }
836  }
837 
838  if (this->information_width < max_width) {
839  this->information_width = max_width;
840  this->ReInit();
841  }
842  FALLTHROUGH;
843  }
844 
845  case 1: // A new cargo has been selected.
846  if (!gui_scope) break;
847  this->cargo = GetRefitOption();
848  this->RefreshScrollbar();
849  break;
850  }
851  }
852 
853  int GetClickPosition(int click_x)
854  {
855  const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY);
856  if (_current_text_dir == TD_RTL) click_x = matrix_widget->current_x - click_x;
857  click_x -= this->vehicle_margin;
858  if (this->hscroll != nullptr) click_x += this->hscroll->GetPosition();
859 
860  return click_x;
861  }
862 
863  void SetSelectedVehicles(int drag_x)
864  {
865  drag_x = GetClickPosition(drag_x);
866 
867  int left_x = min(this->click_x, drag_x);
868  int right_x = max(this->click_x, drag_x);
869  this->num_vehicles = 0;
870 
871  Vehicle *v = Vehicle::Get(this->window_number);
872  /* Find the vehicle part that was clicked. */
873  switch (v->type) {
874  case VEH_TRAIN: {
875  /* Don't select anything if we are not clicking in the vehicle. */
876  if (left_x >= 0) {
877  const Train *u = Train::From(v);
878  bool start_counting = false;
879  for (; u != nullptr; u = u->Next()) {
880  int current_width = u->GetDisplayImageWidth();
881  left_x -= current_width;
882  right_x -= current_width;
883 
884  if (left_x < 0 && !start_counting) {
885  this->selected_vehicle = u->index;
886  start_counting = true;
887 
888  /* Count the first vehicle, even if articulated part */
889  this->num_vehicles++;
890  } else if (start_counting && !u->IsArticulatedPart()) {
891  /* Do not count articulated parts */
892  this->num_vehicles++;
893  }
894 
895  if (right_x < 0) break;
896  }
897  }
898 
899  /* If the selection is not correct, clear it. */
900  if (this->num_vehicles != 0) {
901  if (_ctrl_pressed) this->num_vehicles = UINT8_MAX;
902  break;
903  }
904  FALLTHROUGH;
905  }
906 
907  default:
908  /* Clear the selection. */
909  this->selected_vehicle = v->index;
910  this->num_vehicles = UINT8_MAX;
911  break;
912  }
913  }
914 
915  void OnClick(Point pt, int widget, int click_count) override
916  {
917  switch (widget) {
918  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
919  if (this->order != INVALID_VEH_ORDER_ID) break;
920  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
921  this->click_x = GetClickPosition(pt.x - nwi->pos_x);
922  this->SetSelectedVehicles(pt.x - nwi->pos_x);
924  if (!_ctrl_pressed) {
925  SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, HT_DRAG, this);
926  } else {
927  /* The vehicle selection has changed. */
928  this->InvalidateData(2);
929  }
930  break;
931  }
932 
933  case WID_VR_MATRIX: { // listbox
934  this->SetSelection(this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VR_MATRIX));
935  this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
936  this->InvalidateData(1);
937 
938  if (click_count == 1) break;
939  FALLTHROUGH;
940  }
941 
942  case WID_VR_REFIT: // refit button
943  if (this->cargo != nullptr) {
944  const Vehicle *v = Vehicle::Get(this->window_number);
945 
946  if (this->order == INVALID_VEH_ORDER_ID) {
947  bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
948  if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) delete this;
949  } else {
950  if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) delete this;
951  }
952  }
953  break;
954  }
955  }
956 
957  void OnMouseDrag(Point pt, int widget) override
958  {
959  switch (widget) {
960  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
961  if (this->order != INVALID_VEH_ORDER_ID) break;
962  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
963  this->SetSelectedVehicles(pt.x - nwi->pos_x);
965  break;
966  }
967  }
968  }
969 
970  void OnDragDrop(Point pt, int widget) override
971  {
972  switch (widget) {
973  case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
974  if (this->order != INVALID_VEH_ORDER_ID) break;
975  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
976  this->SetSelectedVehicles(pt.x - nwi->pos_x);
977  this->InvalidateData(2);
978  break;
979  }
980  }
981  }
982 
983  void OnResize() override
984  {
985  this->vehicle_width = GetVehicleWidth(Vehicle::Get(this->window_number), EIT_IN_DETAILS);
986  this->vscroll->SetCapacityFromWidget(this, WID_VR_MATRIX);
987  if (this->hscroll != nullptr) this->hscroll->SetCapacityFromWidget(this, WID_VR_VEHICLE_PANEL_DISPLAY);
988  }
989 };
990 
991 static const NWidgetPart _nested_vehicle_refit_widgets[] = {
993  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
994  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VR_CAPTION), SetDataTip(STR_REFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
995  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
996  EndContainer(),
997  /* Vehicle display + scrollbar. */
1000  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VR_SHOW_HSCROLLBAR),
1001  NWidget(NWID_HSCROLLBAR, COLOUR_GREY, WID_VR_HSCROLLBAR),
1002  EndContainer(),
1003  EndContainer(),
1004  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VR_SELECT_HEADER), SetDataTip(STR_REFIT_TITLE, STR_NULL), SetResize(1, 0),
1005  /* Matrix + scrollbar. */
1007  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VR_MATRIX), SetMinimalSize(228, 112), SetResize(1, 14), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VR_SCROLLBAR),
1008  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VR_SCROLLBAR),
1009  EndContainer(),
1012  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VR_REFIT), SetFill(1, 0), SetResize(1, 0),
1013  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1014  EndContainer(),
1015 };
1016 
1017 static WindowDesc _vehicle_refit_desc(
1018  WDP_AUTO, "view_vehicle_refit", 240, 174,
1021  _nested_vehicle_refit_widgets, lengthof(_nested_vehicle_refit_widgets)
1022 );
1023 
1031 void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
1032 {
1034  RefitWindow *w = new RefitWindow(&_vehicle_refit_desc, v, order, auto_refit);
1035  w->parent = parent;
1036 }
1037 
1039 uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
1040 {
1041  /* List of cargo types of this engine */
1042  CargoTypes cmask = GetUnionOfArticulatedRefitMasks(engine, false);
1043  /* List of cargo types available in this climate */
1044  CargoTypes lmask = _cargo_mask;
1045 
1046  /* Draw nothing if the engine is not refittable */
1047  if (HasAtMostOneBit(cmask)) return y;
1048 
1049  if (cmask == lmask) {
1050  /* Engine can be refitted to all types in this climate */
1051  SetDParam(0, STR_PURCHASE_INFO_ALL_TYPES);
1052  } else {
1053  /* Check if we are able to refit to more cargo types and unable to. If
1054  * so, invert the cargo types to list those that we can't refit to. */
1055  if (CountBits(cmask ^ lmask) < CountBits(cmask) && CountBits(cmask ^ lmask) <= 7) {
1056  cmask ^= lmask;
1057  SetDParam(0, STR_PURCHASE_INFO_ALL_BUT);
1058  } else {
1059  SetDParam(0, STR_JUST_CARGO_LIST);
1060  }
1061  SetDParam(1, cmask);
1062  }
1063 
1064  return DrawStringMultiLine(left, right, y, INT32_MAX, STR_PURCHASE_INFO_REFITTABLE_TO);
1065 }
1066 
1069 {
1070  if (HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
1071  uint16 cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v);
1072  if (cb != CALLBACK_FAILED) {
1074  if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED;
1075  }
1076  if (cb != CALLBACK_FAILED) {
1077  return GetGRFStringID(v->GetGRFID(), 0xD000 + cb);
1078  }
1079  }
1080  return STR_EMPTY;
1081 }
1082 
1084 static bool VehicleNumberSorter(const Vehicle * const &a, const Vehicle * const &b)
1085 {
1086  return a->unitnumber < b->unitnumber;
1087 }
1088 
1090 static bool VehicleNameSorter(const Vehicle * const &a, const Vehicle * const &b)
1091 {
1092  static char last_name[2][64];
1093 
1094  if (a != _last_vehicle[0]) {
1095  _last_vehicle[0] = a;
1096  SetDParam(0, a->index);
1097  GetString(last_name[0], STR_VEHICLE_NAME, lastof(last_name[0]));
1098  }
1099 
1100  if (b != _last_vehicle[1]) {
1101  _last_vehicle[1] = b;
1102  SetDParam(0, b->index);
1103  GetString(last_name[1], STR_VEHICLE_NAME, lastof(last_name[1]));
1104  }
1105 
1106  int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
1107  return (r != 0) ? r < 0: VehicleNumberSorter(a, b);
1108 }
1109 
1111 static bool VehicleAgeSorter(const Vehicle * const &a, const Vehicle * const &b)
1112 {
1113  int r = a->age - b->age;
1114  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1115 }
1116 
1118 static bool VehicleProfitThisYearSorter(const Vehicle * const &a, const Vehicle * const &b)
1119 {
1121  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1122 }
1123 
1125 static bool VehicleProfitLastYearSorter(const Vehicle * const &a, const Vehicle * const &b)
1126 {
1128  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1129 }
1130 
1132 static bool VehicleCargoSorter(const Vehicle * const &a, const Vehicle * const &b)
1133 {
1134  const Vehicle *v;
1135  CargoArray diff;
1136 
1137  /* Append the cargo of the connected waggons */
1138  for (v = a; v != nullptr; v = v->Next()) diff[v->cargo_type] += v->cargo_cap;
1139  for (v = b; v != nullptr; v = v->Next()) diff[v->cargo_type] -= v->cargo_cap;
1140 
1141  int r = 0;
1142  for (CargoID i = 0; i < NUM_CARGO; i++) {
1143  r = diff[i];
1144  if (r != 0) break;
1145  }
1146 
1147  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1148 }
1149 
1151 static bool VehicleReliabilitySorter(const Vehicle * const &a, const Vehicle * const &b)
1152 {
1153  int r = a->reliability - b->reliability;
1154  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1155 }
1156 
1158 static bool VehicleMaxSpeedSorter(const Vehicle * const &a, const Vehicle * const &b)
1159 {
1161  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1162 }
1163 
1165 static bool VehicleModelSorter(const Vehicle * const &a, const Vehicle * const &b)
1166 {
1167  int r = a->engine_type - b->engine_type;
1168  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1169 }
1170 
1172 static bool VehicleValueSorter(const Vehicle * const &a, const Vehicle * const &b)
1173 {
1174  const Vehicle *u;
1175  Money diff = 0;
1176 
1177  for (u = a; u != nullptr; u = u->Next()) diff += u->value;
1178  for (u = b; u != nullptr; u = u->Next()) diff -= u->value;
1179 
1180  int r = ClampToI32(diff);
1181  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1182 }
1183 
1185 static bool VehicleLengthSorter(const Vehicle * const &a, const Vehicle * const &b)
1186 {
1188  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1189 }
1190 
1192 static bool VehicleTimeToLiveSorter(const Vehicle * const &a, const Vehicle * const &b)
1193 {
1194  int r = ClampToI32((a->max_age - a->age) - (b->max_age - b->age));
1195  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1196 }
1197 
1199 static bool VehicleTimetableDelaySorter(const Vehicle * const &a, const Vehicle * const &b)
1200 {
1201  int r = a->lateness_counter - b->lateness_counter;
1202  return (r != 0) ? r < 0 : VehicleNumberSorter(a, b);
1203 }
1204 
1205 void InitializeGUI()
1206 {
1207  MemSetT(&_sorting, 0);
1208 }
1209 
1216 static inline void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
1217 {
1218  Window *w = FindWindowById(window_class, from_index);
1219  if (w != nullptr) {
1220  /* Update window_number */
1221  w->window_number = to_index;
1222  if (w->viewport != nullptr) w->viewport->follow_vehicle = to_index;
1223 
1224  /* Update vehicle drag data */
1225  if (_thd.window_class == window_class && _thd.window_number == (WindowNumber)from_index) {
1226  _thd.window_number = to_index;
1227  }
1228 
1229  /* Notify the window. */
1230  w->InvalidateData(VIWD_AUTOREPLACE, false);
1231  }
1232 }
1233 
1239 void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
1240 {
1241  ChangeVehicleWindow(WC_VEHICLE_VIEW, from_index, to_index);
1242  ChangeVehicleWindow(WC_VEHICLE_ORDERS, from_index, to_index);
1243  ChangeVehicleWindow(WC_VEHICLE_REFIT, from_index, to_index);
1244  ChangeVehicleWindow(WC_VEHICLE_DETAILS, from_index, to_index);
1245  ChangeVehicleWindow(WC_VEHICLE_TIMETABLE, from_index, to_index);
1246 }
1247 
1248 static const NWidgetPart _nested_vehicle_list[] = {
1250  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1251  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VL_CAPTION),
1252  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1253  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1254  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1255  EndContainer(),
1256 
1258  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
1259  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
1260  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0),
1261  EndContainer(),
1262  EndContainer(),
1263 
1265  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VL_LIST), SetMinimalSize(248, 0), SetFill(1, 0), SetResize(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VL_SCROLLBAR),
1266  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VL_SCROLLBAR),
1267  EndContainer(),
1268 
1270  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_HIDE_BUTTONS),
1272  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_AVAILABLE_VEHICLES), SetMinimalSize(106, 12), SetFill(0, 1),
1273  SetDataTip(STR_BLACK_STRING, STR_VEHICLE_LIST_AVAILABLE_ENGINES_TOOLTIP),
1274  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), SetFill(1, 1), EndContainer(),
1276  SetDataTip(STR_VEHICLE_LIST_MANAGE_LIST, STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP),
1277  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_STOP_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1278  SetDataTip(SPR_FLAG_VEH_STOPPED, STR_VEHICLE_LIST_MASS_STOP_LIST_TOOLTIP),
1279  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VL_START_ALL), SetMinimalSize(12, 12), SetFill(0, 1),
1280  SetDataTip(SPR_FLAG_VEH_RUNNING, STR_VEHICLE_LIST_MASS_START_LIST_TOOLTIP),
1281  EndContainer(),
1282  /* Widget to be shown for other companies hiding the previous 5 widgets. */
1283  NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1284  EndContainer(),
1285  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1286  EndContainer(),
1287 };
1288 
1289 static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y, VehicleOrderID start = 0)
1290 {
1291  const Order *order = v->GetOrder(start);
1292  if (order == nullptr) return;
1293 
1294  bool rtl = _current_text_dir == TD_RTL;
1295  int l_offset = rtl ? 0 : ScaleGUITrad(6);
1296  int r_offset = rtl ? ScaleGUITrad(6) : 0;
1297  int i = 0;
1298  VehicleOrderID oid = start;
1299 
1300  do {
1301  if (oid == v->cur_real_order_index) DrawString(left, right, y, STR_TINY_RIGHT_ARROW, TC_BLACK);
1302 
1303  if (order->IsType(OT_GOTO_STATION)) {
1304  SetDParam(0, order->GetDestination());
1305  DrawString(left + l_offset, right - r_offset, y, STR_TINY_BLACK_STATION);
1306 
1307  y += FONT_HEIGHT_SMALL;
1308  if (++i == 4) break;
1309  }
1310 
1311  oid++;
1312  order = order->next;
1313  if (order == nullptr) {
1314  order = v->orders.list->GetFirstOrder();
1315  oid = 0;
1316  }
1317  } while (oid != start);
1318 }
1319 
1329 void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
1330 {
1331  switch (v->type) {
1332  case VEH_TRAIN: DrawTrainImage(Train::From(v), left, right, y, selection, image_type, skip); break;
1333  case VEH_ROAD: DrawRoadVehImage(v, left, right, y, selection, image_type, skip); break;
1334  case VEH_SHIP: DrawShipImage(v, left, right, y, selection, image_type); break;
1335  case VEH_AIRCRAFT: DrawAircraftImage(v, left, right, y, selection, image_type); break;
1336  default: NOT_REACHED();
1337  }
1338 }
1339 
1346 uint GetVehicleListHeight(VehicleType type, uint divisor)
1347 {
1348  /* Name + vehicle + profit */
1349  uint base = ScaleGUITrad(GetVehicleHeight(type)) + 2 * FONT_HEIGHT_SMALL;
1350  /* Drawing of the 4 small orders + profit*/
1351  if (type >= VEH_SHIP) base = max(base, 5U * FONT_HEIGHT_SMALL);
1352 
1353  if (divisor == 1) return base;
1354 
1355  /* Make sure the height is dividable by divisor */
1356  uint rem = base % divisor;
1357  return base + (rem == 0 ? 0 : divisor - rem);
1358 }
1359 
1366 void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
1367 {
1368  int left = r.left + WD_MATRIX_LEFT;
1369  int right = r.right - WD_MATRIX_RIGHT;
1370  int width = right - left;
1371  bool rtl = _current_text_dir == TD_RTL;
1372 
1373  int text_offset = max<int>(GetSpriteSize(SPR_PROFIT_LOT).width, GetDigitWidth() * this->unitnumber_digits) + WD_FRAMERECT_RIGHT;
1374  int text_left = left + (rtl ? 0 : text_offset);
1375  int text_right = right - (rtl ? text_offset : 0);
1376 
1377  bool show_orderlist = this->vli.vtype >= VEH_SHIP;
1378  int orderlist_left = left + (rtl ? 0 : max(ScaleGUITrad(100) + text_offset, width / 2));
1379  int orderlist_right = right - (rtl ? max(ScaleGUITrad(100) + text_offset, width / 2) : 0);
1380 
1381  int image_left = (rtl && show_orderlist) ? orderlist_right : text_left;
1382  int image_right = (!rtl && show_orderlist) ? orderlist_left : text_right;
1383 
1384  int vehicle_button_x = rtl ? right - GetSpriteSize(SPR_PROFIT_LOT).width : left;
1385 
1386  int y = r.top;
1387  uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (uint)this->vehicles.size());
1388  for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
1389  const Vehicle *v = this->vehicles[i];
1390  StringID str;
1391 
1394 
1395  DrawVehicleImage(v, image_left, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
1396  DrawString(text_left, text_right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1, STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
1397 
1398  if (v->name != nullptr) {
1399  /* The vehicle got a name so we will print it */
1400  SetDParam(0, v->index);
1401  DrawString(text_left, text_right, y, STR_TINY_BLACK_VEHICLE);
1402  } else if (v->group_id != DEFAULT_GROUP) {
1403  /* The vehicle has no name, but is member of a group, so print group name */
1404  SetDParam(0, v->group_id);
1405  DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK);
1406  }
1407 
1408  if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_real_order_index);
1409 
1410  if (v->IsChainInDepot()) {
1411  str = STR_BLUE_COMMA;
1412  } else {
1413  str = (v->age > v->max_age - DAYS_IN_LEAP_YEAR) ? STR_RED_COMMA : STR_BLACK_COMMA;
1414  }
1415 
1416  SetDParam(0, v->unitnumber);
1417  DrawString(left, right, y + 2, str);
1418 
1419  DrawVehicleProfitButton(v, vehicle_button_x, y + FONT_HEIGHT_NORMAL + 3);
1420 
1421  y += line_height;
1422  }
1423 }
1424 
1435 private:
1440  };
1441 
1442 public:
1444  {
1445  /* Set up sorting. Make the window-specific _sorting variable
1446  * point to the correct global _sorting struct so we are freed
1447  * from having conditionals during window operation */
1448  switch (this->vli.vtype) {
1449  case VEH_TRAIN: this->sorting = &_sorting.train; break;
1450  case VEH_ROAD: this->sorting = &_sorting.roadveh; break;
1451  case VEH_SHIP: this->sorting = &_sorting.ship; break;
1452  case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break;
1453  default: NOT_REACHED();
1454  }
1455 
1456  this->CreateNestedTree();
1457 
1458  this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR);
1459 
1460  this->vehicles.SetListing(*this->sorting);
1461  this->vehicles.ForceRebuild();
1462  this->vehicles.NeedResort();
1463  this->BuildVehicleList();
1464  this->SortVehicleList();
1465 
1466  /* Set up the window widgets */
1467  this->GetWidget<NWidgetCore>(WID_VL_LIST)->tool_tip = STR_VEHICLE_LIST_TRAIN_LIST_TOOLTIP + this->vli.vtype;
1468 
1469  if (this->vli.type == VL_SHARED_ORDERS) {
1470  this->GetWidget<NWidgetCore>(WID_VL_CAPTION)->widget_data = STR_VEHICLE_LIST_SHARED_ORDERS_LIST_CAPTION;
1471  } else {
1472  this->GetWidget<NWidgetCore>(WID_VL_CAPTION)->widget_data = STR_VEHICLE_LIST_TRAIN_CAPTION + this->vli.vtype;
1473  }
1474 
1475  this->FinishInitNested(window_number);
1476  if (this->vli.company != OWNER_NONE) this->owner = this->vli.company;
1477  }
1478 
1480  {
1481  *this->sorting = this->vehicles.GetListing();
1482  }
1483 
1484  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1485  {
1486  switch (widget) {
1487  case WID_VL_LIST:
1488  resize->height = GetVehicleListHeight(this->vli.vtype, 1);
1489 
1490  switch (this->vli.vtype) {
1491  case VEH_TRAIN:
1492  case VEH_ROAD:
1493  size->height = 6 * resize->height;
1494  break;
1495  case VEH_SHIP:
1496  case VEH_AIRCRAFT:
1497  size->height = 4 * resize->height;
1498  break;
1499  default: NOT_REACHED();
1500  }
1501  break;
1502 
1503  case WID_VL_SORT_ORDER: {
1504  Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
1505  d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
1506  d.height += padding.height;
1507  *size = maxdim(*size, d);
1508  break;
1509  }
1510 
1512  Dimension d = this->GetActionDropdownSize(this->vli.type == VL_STANDARD, false);
1513  d.height += padding.height;
1514  d.width += padding.width;
1515  *size = maxdim(*size, d);
1516  break;
1517  }
1518  }
1519  }
1520 
1521  void SetStringParameters(int widget) const override
1522  {
1523  switch (widget) {
1525  SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
1526  break;
1527 
1528  case WID_VL_CAPTION: {
1529  switch (this->vli.type) {
1530  case VL_SHARED_ORDERS: // Shared Orders
1531  if (this->vehicles.size() == 0) {
1532  /* We can't open this window without vehicles using this order
1533  * and we should close the window when deleting the order. */
1534  NOT_REACHED();
1535  }
1536  SetDParam(0, this->vscroll->GetCount());
1537  break;
1538 
1539  case VL_STANDARD: // Company Name
1540  SetDParam(0, STR_COMPANY_NAME);
1541  SetDParam(1, this->vli.index);
1542  SetDParam(3, this->vscroll->GetCount());
1543  break;
1544 
1545  case VL_STATION_LIST: // Station/Waypoint Name
1546  SetDParam(0, Station::IsExpected(BaseStation::Get(this->vli.index)) ? STR_STATION_NAME : STR_WAYPOINT_NAME);
1547  SetDParam(1, this->vli.index);
1548  SetDParam(3, this->vscroll->GetCount());
1549  break;
1550 
1551  case VL_DEPOT_LIST:
1552  SetDParam(0, STR_DEPOT_CAPTION);
1553  SetDParam(1, this->vli.vtype);
1554  SetDParam(2, this->vli.index);
1555  SetDParam(3, this->vscroll->GetCount());
1556  break;
1557  default: NOT_REACHED();
1558  }
1559  break;
1560  }
1561  }
1562  }
1563 
1564  void DrawWidget(const Rect &r, int widget) const override
1565  {
1566  switch (widget) {
1567  case WID_VL_SORT_ORDER:
1568  /* draw arrow pointing up/down for ascending/descending sorting */
1569  this->DrawSortButtonState(widget, this->vehicles.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
1570  break;
1571 
1572  case WID_VL_LIST:
1574  break;
1575  }
1576  }
1577 
1578  void OnPaint() override
1579  {
1580  this->BuildVehicleList();
1581  this->SortVehicleList();
1582 
1583  if (this->vehicles.size() == 0 && this->IsWidgetLowered(WID_VL_MANAGE_VEHICLES_DROPDOWN)) {
1584  HideDropDownMenu(this);
1585  }
1586 
1587  /* Hide the widgets that we will not use in this window
1588  * Some windows contains actions only fit for the owner */
1589  int plane_to_show = (this->owner == _local_company) ? BP_SHOW_BUTTONS : BP_HIDE_BUTTONS;
1590  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VL_HIDE_BUTTONS);
1591  if (plane_to_show != nwi->shown_plane) {
1592  nwi->SetDisplayedPlane(plane_to_show);
1593  nwi->SetDirty(this);
1594  }
1595  if (this->owner == _local_company) {
1596  this->SetWidgetDisabledState(WID_VL_AVAILABLE_VEHICLES, this->vli.type != VL_STANDARD);
1597  this->SetWidgetsDisabledState(this->vehicles.size() == 0,
1601  WIDGET_LIST_END);
1602  }
1603 
1604  /* Set text of sort by dropdown widget. */
1605  this->GetWidget<NWidgetCore>(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->vehicle_sorter_names[this->vehicles.SortType()];
1606 
1607  this->DrawWidgets();
1608  }
1609 
1610  void OnClick(Point pt, int widget, int click_count) override
1611  {
1612  switch (widget) {
1613  case WID_VL_SORT_ORDER: // Flip sorting method ascending/descending
1614  this->vehicles.ToggleSortOrder();
1615  this->SetDirty();
1616  break;
1617 
1618  case WID_VL_SORT_BY_PULLDOWN:// Select sorting criteria dropdown menu
1619  ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(), WID_VL_SORT_BY_PULLDOWN, 0,
1620  (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
1621  return;
1622 
1623  case WID_VL_LIST: { // Matrix to show vehicles
1624  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VL_LIST);
1625  if (id_v >= this->vehicles.size()) return; // click out of list bound
1626 
1627  const Vehicle *v = this->vehicles[id_v];
1628  if (!VehicleClicked(v)) {
1629  if (_ctrl_pressed) {
1631  } else {
1633  }
1634  }
1635  break;
1636  }
1637 
1639  ShowBuildVehicleWindow(INVALID_TILE, this->vli.vtype);
1640  break;
1641 
1644  break;
1645  }
1646 
1647  case WID_VL_STOP_ALL:
1648  case WID_VL_START_ALL:
1649  DoCommandP(0, (1 << 1) | (widget == WID_VL_START_ALL ? (1 << 0) : 0), this->window_number, CMD_MASS_START_STOP);
1650  break;
1651  }
1652  }
1653 
1654  void OnDropdownSelect(int widget, int index) override
1655  {
1656  switch (widget) {
1658  this->vehicles.SetSortType(index);
1659  break;
1661  assert(this->vehicles.size() != 0);
1662 
1663  switch (index) {
1664  case ADI_REPLACE: // Replace window
1666  break;
1667  case ADI_SERVICE: // Send for servicing
1668  case ADI_DEPOT: // Send to Depots
1669  DoCommandP(0, DEPOT_MASS_SEND | (index == ADI_SERVICE ? DEPOT_SERVICE : (DepotCommand)0), this->window_number, GetCmdSendToDepot(this->vli.vtype));
1670  break;
1671 
1672  default: NOT_REACHED();
1673  }
1674  break;
1675  default: NOT_REACHED();
1676  }
1677  this->SetDirty();
1678  }
1679 
1680  void OnGameTick() override
1681  {
1682  if (this->vehicles.NeedResort()) {
1683  StationID station = (this->vli.type == VL_STATION_LIST) ? this->vli.index : INVALID_STATION;
1684 
1685  DEBUG(misc, 3, "Periodic resort %d list company %d at station %d", this->vli.vtype, this->owner, station);
1686  this->SetDirty();
1687  }
1688  }
1689 
1690  void OnResize() override
1691  {
1692  this->vscroll->SetCapacityFromWidget(this, WID_VL_LIST);
1693  }
1694 
1700  void OnInvalidateData(int data = 0, bool gui_scope = true) override
1701  {
1702  if (!gui_scope && HasBit(data, 31) && this->vli.type == VL_SHARED_ORDERS) {
1703  /* Needs to be done in command-scope, so everything stays valid */
1704  this->vli.index = GB(data, 0, 20);
1705  this->window_number = this->vli.Pack();
1706  this->vehicles.ForceRebuild();
1707  return;
1708  }
1709 
1710  if (data == 0) {
1711  /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
1712  this->vehicles.ForceRebuild();
1713  } else {
1714  this->vehicles.ForceResort();
1715  }
1716  }
1717 };
1718 
1719 static WindowDesc _vehicle_list_other_desc(
1720  WDP_AUTO, "list_vehicles", 260, 246,
1722  0,
1723  _nested_vehicle_list, lengthof(_nested_vehicle_list)
1724 );
1725 
1726 static WindowDesc _vehicle_list_train_desc(
1727  WDP_AUTO, "list_vehicles_train", 325, 246,
1729  0,
1730  _nested_vehicle_list, lengthof(_nested_vehicle_list)
1731 );
1732 
1733 static void ShowVehicleListWindowLocal(CompanyID company, VehicleListType vlt, VehicleType vehicle_type, uint32 unique_number)
1734 {
1735  if (!Company::IsValidID(company) && company != OWNER_NONE) return;
1736 
1737  WindowNumber num = VehicleListIdentifier(vlt, vehicle_type, company, unique_number).Pack();
1738  if (vehicle_type == VEH_TRAIN) {
1739  AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_train_desc, num);
1740  } else {
1741  _vehicle_list_other_desc.cls = GetWindowClassForVehicleType(vehicle_type);
1742  AllocateWindowDescFront<VehicleListWindow>(&_vehicle_list_other_desc, num);
1743  }
1744 }
1745 
1746 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type)
1747 {
1748  /* If _settings_client.gui.advanced_vehicle_list > 1, display the Advanced list
1749  * if _settings_client.gui.advanced_vehicle_list == 1, display Advanced list only for local company
1750  * if _ctrl_pressed, do the opposite action (Advanced list x Normal list)
1751  */
1752 
1753  if ((_settings_client.gui.advanced_vehicle_list > (uint)(company != _local_company)) != _ctrl_pressed) {
1754  ShowCompanyGroup(company, vehicle_type);
1755  } else {
1756  ShowVehicleListWindowLocal(company, VL_STANDARD, vehicle_type, company);
1757  }
1758 }
1759 
1760 void ShowVehicleListWindow(const Vehicle *v)
1761 {
1762  ShowVehicleListWindowLocal(v->owner, VL_SHARED_ORDERS, v->type, v->FirstShared()->index);
1763 }
1764 
1765 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, StationID station)
1766 {
1767  ShowVehicleListWindowLocal(company, VL_STATION_LIST, vehicle_type, station);
1768 }
1769 
1770 void ShowVehicleListWindow(CompanyID company, VehicleType vehicle_type, TileIndex depot_tile)
1771 {
1772  uint16 depot_airport_index;
1773 
1774  if (vehicle_type == VEH_AIRCRAFT) {
1775  depot_airport_index = GetStationIndex(depot_tile);
1776  } else {
1777  depot_airport_index = GetDepotIndex(depot_tile);
1778  }
1779  ShowVehicleListWindowLocal(company, VL_DEPOT_LIST, vehicle_type, depot_airport_index);
1780 }
1781 
1782 
1783 /* Unified vehicle GUI - Vehicle Details Window */
1784 
1789 
1793  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1794  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1795  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */),
1796  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1797  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1798  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1799  EndContainer(),
1800  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetMinimalSize(405, 42), SetResize(1, 0), EndContainer(),
1801  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_MIDDLE_DETAILS), SetMinimalSize(405, 45), SetResize(1, 0), EndContainer(),
1804  SetDataTip(AWV_DECREASE, STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP),
1806  SetDataTip(AWV_INCREASE, STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP),
1808  SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
1809  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1810  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1811  EndContainer(),
1812 };
1813 
1817  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1818  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetDataTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1819  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VD_RENAME_VEHICLE), SetMinimalSize(40, 0), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetDataTip(STR_VEHICLE_NAME_BUTTON, STR_NULL /* filled in later */),
1820  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1821  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1822  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1823  EndContainer(),
1824  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_TOP_DETAILS), SetResize(1, 0), SetMinimalSize(405, 42), EndContainer(),
1826  NWidget(WWT_MATRIX, COLOUR_GREY, WID_VD_MATRIX), SetResize(1, 1), SetMinimalSize(393, 45), SetMatrixDataTip(1, 0, STR_NULL), SetFill(1, 0), SetScrollbar(WID_VD_SCROLLBAR),
1827  NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VD_SCROLLBAR),
1828  EndContainer(),
1831  SetDataTip(AWV_DECREASE, STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP),
1833  SetDataTip(AWV_INCREASE, STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP),
1835  SetDataTip(STR_EMPTY, STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP),
1836  NWidget(WWT_PANEL, COLOUR_GREY, WID_VD_SERVICING_INTERVAL), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1837  EndContainer(),
1840  SetDataTip(STR_VEHICLE_DETAIL_TAB_CARGO, STR_VEHICLE_DETAILS_TRAIN_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1842  SetDataTip(STR_VEHICLE_DETAIL_TAB_INFORMATION, STR_VEHICLE_DETAILS_TRAIN_INFORMATION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1844  SetDataTip(STR_VEHICLE_DETAIL_TAB_CAPACITIES, STR_VEHICLE_DETAILS_TRAIN_CAPACITIES_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1846  SetDataTip(STR_VEHICLE_DETAIL_TAB_TOTAL_CARGO, STR_VEHICLE_DETAILS_TRAIN_TOTAL_CARGO_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1847  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1848  EndContainer(),
1849 };
1850 
1851 
1852 extern int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab);
1853 extern void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab);
1854 extern void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y);
1855 extern void DrawShipDetails(const Vehicle *v, int left, int right, int y);
1856 extern void DrawAircraftDetails(const Aircraft *v, int left, int right, int y);
1857 
1858 static StringID _service_interval_dropdown[] = {
1859  STR_VEHICLE_DETAILS_DEFAULT,
1860  STR_VEHICLE_DETAILS_DAYS,
1861  STR_VEHICLE_DETAILS_PERCENT,
1863 };
1864 
1868  Scrollbar *vscroll;
1869 
1872  {
1873  const Vehicle *v = Vehicle::Get(window_number);
1874 
1875  this->CreateNestedTree();
1876  this->vscroll = (v->type == VEH_TRAIN ? this->GetScrollbar(WID_VD_SCROLLBAR) : nullptr);
1877  this->FinishInitNested(window_number);
1878 
1879  this->GetWidget<NWidgetCore>(WID_VD_RENAME_VEHICLE)->tool_tip = STR_VEHICLE_DETAILS_TRAIN_RENAME + v->type;
1880 
1881  this->owner = v->owner;
1882  this->tab = TDW_TAB_CARGO;
1883  }
1884 
1890  void OnInvalidateData(int data = 0, bool gui_scope = true) override
1891  {
1892  if (data == VIWD_AUTOREPLACE) {
1893  /* Autoreplace replaced the vehicle.
1894  * Nothing to do for this window. */
1895  return;
1896  }
1897  if (!gui_scope) return;
1898  const Vehicle *v = Vehicle::Get(this->window_number);
1899  if (v->type == VEH_ROAD) {
1900  const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_VD_MIDDLE_DETAILS);
1901  uint aimed_height = this->GetRoadVehDetailsHeight(v);
1902  /* If the number of articulated parts changes, the size of the window must change too. */
1903  if (aimed_height != nwid_info->current_y) {
1904  this->ReInit();
1905  }
1906  }
1907  }
1908 
1915  {
1916  uint desired_height;
1917  if (v->HasArticulatedPart()) {
1918  /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
1919  desired_height = WD_FRAMERECT_TOP + ScaleGUITrad(15) + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM;
1920  /* Add space for the cargo amount for each part. */
1921  for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
1922  if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1;
1923  }
1924  } else {
1925  desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
1926  }
1927  return desired_height;
1928  }
1929 
1930  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1931  {
1932  switch (widget) {
1933  case WID_VD_TOP_DETAILS: {
1934  Dimension dim = { 0, 0 };
1936 
1937  for (uint i = 0; i < 4; i++) SetDParamMaxValue(i, INT16_MAX);
1938  static const StringID info_strings[] = {
1939  STR_VEHICLE_INFO_MAX_SPEED,
1940  STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED,
1941  STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE,
1942  STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR,
1943  STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS
1944  };
1945  for (uint i = 0; i < lengthof(info_strings); i++) {
1946  dim = maxdim(dim, GetStringBoundingBox(info_strings[i]));
1947  }
1948  SetDParam(0, STR_VEHICLE_INFO_AGE);
1949  dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_AGE_RUNNING_COST_YR));
1950  size->width = dim.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1951  break;
1952  }
1953 
1954  case WID_VD_MIDDLE_DETAILS: {
1955  const Vehicle *v = Vehicle::Get(this->window_number);
1956  switch (v->type) {
1957  case VEH_ROAD:
1958  size->height = this->GetRoadVehDetailsHeight(v);
1959  break;
1960 
1961  case VEH_SHIP:
1962  size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
1963  break;
1964 
1965  case VEH_AIRCRAFT:
1966  size->height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + 4 + WD_FRAMERECT_BOTTOM;
1967  break;
1968 
1969  default:
1970  NOT_REACHED(); // Train uses WID_VD_MATRIX instead.
1971  }
1972  break;
1973  }
1974 
1975  case WID_VD_MATRIX:
1977  size->height = 4 * resize->height;
1978  break;
1979 
1981  StringID *strs = _service_interval_dropdown;
1982  while (*strs != INVALID_STRING_ID) {
1983  *size = maxdim(*size, GetStringBoundingBox(*strs++));
1984  }
1985  size->width += padding.width;
1987  break;
1988  }
1989 
1991  SetDParamMaxValue(0, MAX_SERVINT_DAYS); // Roughly the maximum interval
1992  SetDParamMaxValue(1, MAX_YEAR * DAYS_IN_YEAR); // Roughly the maximum year
1993  size->width = max(GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width, GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1995  break;
1996  }
1997  }
1998 
2000  static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
2001  {
2002  const VehicleDefaultSettings *vds = &Company::Get(company_id)->settings.vehicle;
2003  switch (vehicle_type) {
2004  default: NOT_REACHED();
2005  case VEH_TRAIN: return vds->servint_trains != 0;
2006  case VEH_ROAD: return vds->servint_roadveh != 0;
2007  case VEH_SHIP: return vds->servint_ships != 0;
2008  case VEH_AIRCRAFT: return vds->servint_aircraft != 0;
2009  }
2010  }
2011 
2023  static void DrawVehicleDetails(const Vehicle *v, int left, int right, int y, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
2024  {
2025  switch (v->type) {
2026  case VEH_TRAIN: DrawTrainDetails(Train::From(v), left, right, y, vscroll_pos, vscroll_cap, det_tab); break;
2027  case VEH_ROAD: DrawRoadVehDetails(v, left, right, y); break;
2028  case VEH_SHIP: DrawShipDetails(v, left, right, y); break;
2029  case VEH_AIRCRAFT: DrawAircraftDetails(Aircraft::From(v), left, right, y); break;
2030  default: NOT_REACHED();
2031  }
2032  }
2033 
2034  void SetStringParameters(int widget) const override
2035  {
2036  if (widget == WID_VD_CAPTION) SetDParam(0, Vehicle::Get(this->window_number)->index);
2037  }
2038 
2039  void DrawWidget(const Rect &r, int widget) const override
2040  {
2041  const Vehicle *v = Vehicle::Get(this->window_number);
2042 
2043  switch (widget) {
2044  case WID_VD_TOP_DETAILS: {
2045  int y = r.top + WD_FRAMERECT_TOP;
2046 
2047  /* Draw running cost */
2048  SetDParam(1, v->age / DAYS_IN_LEAP_YEAR);
2049  SetDParam(0, (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_INFO_AGE : STR_VEHICLE_INFO_AGE_RED);
2052  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
2053  y += FONT_HEIGHT_NORMAL;
2054 
2055  /* Draw max speed */
2056  StringID string;
2057  if (v->type == VEH_TRAIN ||
2058  (v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) {
2059  const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
2060  SetDParam(2, v->GetDisplayMaxSpeed());
2061  SetDParam(1, gcache->cached_power);
2062  SetDParam(0, gcache->cached_weight);
2063  SetDParam(3, gcache->cached_max_te / 1000);
2064  if (v->type == VEH_TRAIN && (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ||
2065  GetRailTypeInfo(Train::From(v)->railtype)->acceleration_type == 2)) {
2066  string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED;
2067  } else {
2068  string = STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE;
2069  }
2070  } else {
2071  SetDParam(0, v->GetDisplayMaxSpeed());
2072  if (v->type == VEH_AIRCRAFT) {
2074  if (Aircraft::From(v)->GetRange() > 0) {
2075  SetDParam(2, Aircraft::From(v)->GetRange());
2076  string = STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE;
2077  } else {
2078  string = STR_VEHICLE_INFO_MAX_SPEED_TYPE;
2079  }
2080  } else {
2081  string = STR_VEHICLE_INFO_MAX_SPEED;
2082  }
2083  }
2084  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, string);
2085  y += FONT_HEIGHT_NORMAL;
2086 
2087  /* Draw profit */
2090  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR);
2091  y += FONT_HEIGHT_NORMAL;
2092 
2093  /* Draw breakdown & reliability */
2096  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
2097  break;
2098  }
2099 
2100  case WID_VD_MATRIX:
2101  /* For trains only. */
2102  DrawVehicleDetails(v, r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, r.top + WD_MATRIX_TOP, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->tab);
2103  break;
2104 
2105  case WID_VD_MIDDLE_DETAILS: {
2106  /* For other vehicles, at the place of the matrix. */
2107  bool rtl = _current_text_dir == TD_RTL;
2109 
2110  uint text_left = r.left + (rtl ? 0 : sprite_width);
2111  uint text_right = r.right - (rtl ? sprite_width : 0);
2112 
2113  /* Articulated road vehicles use a complete line. */
2114  if (v->type == VEH_ROAD && v->HasArticulatedPart()) {
2115  DrawVehicleImage(v, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2116  } else {
2117  uint sprite_left = rtl ? text_right : r.left;
2118  uint sprite_right = rtl ? r.right : text_left;
2119 
2120  DrawVehicleImage(v, sprite_left + WD_FRAMERECT_LEFT, sprite_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
2121  }
2122  DrawVehicleDetails(v, text_left + WD_FRAMERECT_LEFT, text_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, 0, 0, this->tab);
2123  break;
2124  }
2125 
2127  /* Draw service interval text */
2128  SetDParam(0, v->GetServiceInterval());
2130  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + (r.bottom - r.top + 1 - FONT_HEIGHT_NORMAL) / 2,
2131  v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS);
2132  break;
2133  }
2134  }
2135 
2137  void OnPaint() override
2138  {
2139  const Vehicle *v = Vehicle::Get(this->window_number);
2140 
2142 
2143  if (v->type == VEH_TRAIN) {
2144  this->DisableWidget(this->tab + WID_VD_DETAILS_CARGO_CARRIED);
2145  this->vscroll->SetCount(GetTrainDetailsWndVScroll(v->index, this->tab));
2146  }
2147 
2148  /* Disable service-scroller when interval is set to disabled */
2149  this->SetWidgetsDisabledState(!IsVehicleServiceIntervalEnabled(v->type, v->owner),
2152  WIDGET_LIST_END);
2153 
2154  StringID str = v->ServiceIntervalIsCustom() ?
2155  (v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : STR_VEHICLE_DETAILS_DAYS) :
2156  STR_VEHICLE_DETAILS_DEFAULT;
2157  this->GetWidget<NWidgetCore>(WID_VD_SERVICE_INTERVAL_DROPDOWN)->widget_data = str;
2158 
2159  this->DrawWidgets();
2160  }
2161 
2162  void OnClick(Point pt, int widget, int click_count) override
2163  {
2164  switch (widget) {
2165  case WID_VD_RENAME_VEHICLE: { // rename
2166  const Vehicle *v = Vehicle::Get(this->window_number);
2167  SetDParam(0, v->index);
2168  ShowQueryString(STR_VEHICLE_NAME, STR_QUERY_RENAME_TRAIN_CAPTION + v->type,
2170  break;
2171  }
2172 
2173  case WID_VD_INCREASE_SERVICING_INTERVAL: // increase int
2174  case WID_VD_DECREASE_SERVICING_INTERVAL: { // decrease int
2175  int mod = _ctrl_pressed ? 5 : 10;
2176  const Vehicle *v = Vehicle::Get(this->window_number);
2177 
2178  mod = (widget == WID_VD_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
2179  mod = GetServiceIntervalClamped(mod + v->GetServiceInterval(), v->ServiceIntervalIsPercent());
2180  if (mod == v->GetServiceInterval()) return;
2181 
2182  DoCommandP(v->tile, v->index, mod | (1 << 16) | (v->ServiceIntervalIsPercent() << 17), CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SERVICING));
2183  break;
2184  }
2185 
2187  const Vehicle *v = Vehicle::Get(this->window_number);
2188  ShowDropDownMenu(this, _service_interval_dropdown, v->ServiceIntervalIsCustom() ? (v->ServiceIntervalIsPercent() ? 2 : 1) : 0, widget, 0, 0);
2189  break;
2190  }
2191 
2196  this->SetWidgetsDisabledState(false,
2201  widget,
2202  WIDGET_LIST_END);
2203 
2204  this->tab = (TrainDetailsWindowTabs)(widget - WID_VD_DETAILS_CARGO_CARRIED);
2205  this->SetDirty();
2206  break;
2207  }
2208  }
2209 
2210  void OnDropdownSelect(int widget, int index) override
2211  {
2212  switch (widget) {
2214  const Vehicle *v = Vehicle::Get(this->window_number);
2215  bool iscustom = index != 0;
2216  bool ispercent = iscustom ? (index == 2) : Company::Get(v->owner)->settings.vehicle.servint_ispercent;
2217  uint16 interval = GetServiceIntervalClamped(v->GetServiceInterval(), ispercent);
2218  DoCommandP(v->tile, v->index, interval | (iscustom << 16) | (ispercent << 17), CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_SERVICING));
2219  break;
2220  }
2221  }
2222  }
2223 
2224  void OnQueryTextFinished(char *str) override
2225  {
2226  if (str == nullptr) return;
2227 
2228  DoCommandP(0, this->window_number, 0, CMD_RENAME_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_RENAME_TRAIN + Vehicle::Get(this->window_number)->type), nullptr, str);
2229  }
2230 
2231  void OnResize() override
2232  {
2233  NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VD_MATRIX);
2234  if (nwi != nullptr) {
2235  this->vscroll->SetCapacityFromWidget(this, WID_VD_MATRIX);
2236  }
2237  }
2238 };
2239 
2242  WDP_AUTO, "view_vehicle_details_train", 405, 178,
2244  0,
2245  _nested_train_vehicle_details_widgets, lengthof(_nested_train_vehicle_details_widgets)
2246 );
2247 
2250  WDP_AUTO, "view_vehicle_details", 405, 113,
2252  0,
2253  _nested_nontrain_vehicle_details_widgets, lengthof(_nested_nontrain_vehicle_details_widgets)
2254 );
2255 
2257 static void ShowVehicleDetailsWindow(const Vehicle *v)
2258 {
2261  AllocateWindowDescFront<VehicleDetailsWindow>((v->type == VEH_TRAIN) ? &_train_vehicle_details_desc : &_nontrain_vehicle_details_desc, v->index);
2262 }
2263 
2264 
2265 /* Unified vehicle GUI - Vehicle View Window */
2266 
2270  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2271  NWidget(WWT_CAPTION, COLOUR_GREY, WID_VV_CAPTION), SetDataTip(STR_VEHICLE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2272  NWidget(WWT_DEBUGBOX, COLOUR_GREY),
2273  NWidget(WWT_SHADEBOX, COLOUR_GREY),
2274  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
2275  NWidget(WWT_STICKYBOX, COLOUR_GREY),
2276  EndContainer(),
2278  NWidget(WWT_PANEL, COLOUR_GREY),
2279  NWidget(WWT_INSET, COLOUR_GREY), SetPadding(2, 2, 2, 2),
2280  NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_VV_VIEWPORT), SetMinimalSize(226, 84), SetResize(1, 1), SetPadding(1, 1, 1, 1),
2281  EndContainer(),
2282  EndContainer(),
2284  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_CENTER_MAIN_VIEW), SetMinimalSize(18, 18), SetDataTip(SPR_CENTRE_VIEW_VEHICLE, 0x0 /* filled later */),
2286  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_GOTO_DEPOT), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2287  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_CLONE), SetMinimalSize(18, 18), SetDataTip(0x0 /* filled later */, 0x0 /* filled later */),
2288  EndContainer(),
2289  /* For trains only, 'ignore signal' button. */
2291  SetDataTip(SPR_IGNORE_SIGNALS, STR_VEHICLE_VIEW_TRAIN_IGNORE_SIGNAL_TOOLTIP),
2293  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_REFIT), SetMinimalSize(18, 18), SetDataTip(SPR_REFIT_VEHICLE, 0x0 /* filled later */),
2294  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_TURN_AROUND), SetMinimalSize(18, 18),
2295  SetDataTip(SPR_FORCE_VEHICLE_TURN, STR_VEHICLE_VIEW_ROAD_VEHICLE_REVERSE_TOOLTIP),
2296  EndContainer(),
2297  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_ORDERS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_ORDERS, 0x0 /* filled later */),
2298  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_SHOW_DETAILS), SetMinimalSize(18, 18), SetDataTip(SPR_SHOW_VEHICLE_DETAILS, 0x0 /* filled later */),
2299  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(18, 0), SetResize(0, 1), EndContainer(),
2300  EndContainer(),
2301  EndContainer(),
2304  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
2305  EndContainer(),
2306 };
2307 
2310  WDP_AUTO, "view_vehicle", 250, 116,
2312  0,
2313  _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets)
2314 );
2315 
2321  WDP_AUTO, "view_vehicle_train", 250, 134,
2323  0,
2324  _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets)
2325 );
2326 
2327 
2328 /* Just to make sure, nobody has changed the vehicle type constants, as we are
2329  using them for array indexing in a number of places here. */
2330 assert_compile(VEH_TRAIN == 0);
2331 assert_compile(VEH_ROAD == 1);
2332 assert_compile(VEH_SHIP == 2);
2333 assert_compile(VEH_AIRCRAFT == 3);
2334 
2339  ZOOM_LVL_SHIP,
2341 };
2342 
2343 /* Constants for geometry of vehicle view viewport */
2344 static const int VV_INITIAL_VIEWPORT_WIDTH = 226;
2345 static const int VV_INITIAL_VIEWPORT_HEIGHT = 84;
2346 static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102;
2347 
2350  VCT_CMD_START_STOP = 0,
2351  VCT_CMD_CLONE_VEH,
2352  VCT_CMD_TURN_AROUND,
2353 };
2354 
2356 static const uint32 _vehicle_command_translation_table[][4] = {
2357  { // VCT_CMD_START_STOP
2358  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_TRAIN),
2359  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_ROAD_VEHICLE),
2360  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_SHIP),
2361  CMD_START_STOP_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_STOP_START_AIRCRAFT)
2362  },
2363  { // VCT_CMD_CLONE_VEH
2364  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN),
2365  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_ROAD_VEHICLE),
2366  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_SHIP),
2367  CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_AIRCRAFT)
2368  },
2369  { // VCT_CMD_TURN_AROUND
2370  CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN),
2371  CMD_TURN_ROADVEH | CMD_MSG(STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN),
2372  0xffffffff, // invalid for ships
2373  0xffffffff // invalid for aircraft
2374  },
2375 };
2376 
2384 void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
2385 {
2386  if (result.Failed()) return;
2387 
2388  const Vehicle *v = Vehicle::GetIfValid(p1);
2389  if (v == nullptr || !v->IsPrimaryVehicle() || v->owner != _local_company) return;
2390 
2391  StringID msg = (v->vehstatus & VS_STOPPED) ? STR_VEHICLE_COMMAND_STOPPED : STR_VEHICLE_COMMAND_STARTED;
2392  Point pt = RemapCoords(v->x_pos, v->y_pos, v->z_pos);
2393  AddTextEffect(msg, pt.x, pt.y, DAY_TICKS, TE_RISING);
2394 }
2395 
2401 void StartStopVehicle(const Vehicle *v, bool texteffect)
2402 {
2403  assert(v->IsPrimaryVehicle());
2404  DoCommandP(v->tile, v->index, 0, _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type], texteffect ? CcStartStopVehicle : nullptr);
2405 }
2406 
2408 static bool IsVehicleRefitable(const Vehicle *v)
2409 {
2410  if (!v->IsStoppedInDepot()) return false;
2411 
2412  do {
2413  if (IsEngineRefittable(v->engine_type)) return true;
2414  } while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
2415 
2416  return false;
2417 }
2418 
2421 private:
2426 
2429 
2430  SEL_DC_BASEPLANE = SEL_DC_GOTO_DEPOT,
2431  SEL_RT_BASEPLANE = SEL_RT_REFIT,
2432  };
2433 
2439  {
2440  switch (plane) {
2441  case SEL_DC_GOTO_DEPOT:
2442  case SEL_DC_CLONE:
2443  this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE)->SetDisplayedPlane(plane - SEL_DC_BASEPLANE);
2444  break;
2445 
2446  case SEL_RT_REFIT:
2447  case SEL_RT_TURN_AROUND:
2448  this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN)->SetDisplayedPlane(plane - SEL_RT_BASEPLANE);
2449  break;
2450 
2451  default:
2452  NOT_REACHED();
2453  }
2454  }
2455 
2456 public:
2458  {
2459  this->flags |= WF_DISABLE_VP_SCROLL;
2460  this->CreateNestedTree();
2461 
2462  /* Sprites for the 'send to depot' button indexed by vehicle type. */
2463  static const SpriteID vehicle_view_goto_depot_sprites[] = {
2464  SPR_SEND_TRAIN_TODEPOT,
2465  SPR_SEND_ROADVEH_TODEPOT,
2466  SPR_SEND_SHIP_TODEPOT,
2467  SPR_SEND_AIRCRAFT_TODEPOT,
2468  };
2469  const Vehicle *v = Vehicle::Get(window_number);
2470  this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->widget_data = vehicle_view_goto_depot_sprites[v->type];
2471 
2472  /* Sprites for the 'clone vehicle' button indexed by vehicle type. */
2473  static const SpriteID vehicle_view_clone_sprites[] = {
2475  SPR_CLONE_ROADVEH,
2476  SPR_CLONE_SHIP,
2477  SPR_CLONE_AIRCRAFT,
2478  };
2479  this->GetWidget<NWidgetCore>(WID_VV_CLONE)->widget_data = vehicle_view_clone_sprites[v->type];
2480 
2481  switch (v->type) {
2482  case VEH_TRAIN:
2483  this->GetWidget<NWidgetCore>(WID_VV_TURN_AROUND)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REVERSE_TOOLTIP;
2484  break;
2485 
2486  case VEH_ROAD:
2487  break;
2488 
2489  case VEH_SHIP:
2490  case VEH_AIRCRAFT:
2491  this->SelectPlane(SEL_RT_REFIT);
2492  break;
2493 
2494  default: NOT_REACHED();
2495  }
2496  this->FinishInitNested(window_number);
2497  this->owner = v->owner;
2498  this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT)->InitializeViewport(this, this->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
2499 
2500  this->GetWidget<NWidgetCore>(WID_VV_START_STOP)->tool_tip = STR_VEHICLE_VIEW_TRAIN_STATE_START_STOP_TOOLTIP + v->type;
2501  this->GetWidget<NWidgetCore>(WID_VV_CENTER_MAIN_VIEW)->tool_tip = STR_VEHICLE_VIEW_TRAIN_LOCATION_TOOLTIP + v->type;
2502  this->GetWidget<NWidgetCore>(WID_VV_REFIT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_REFIT_TOOLTIP + v->type;
2503  this->GetWidget<NWidgetCore>(WID_VV_GOTO_DEPOT)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SEND_TO_DEPOT_TOOLTIP + v->type;
2504  this->GetWidget<NWidgetCore>(WID_VV_SHOW_ORDERS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_ORDERS_TOOLTIP + v->type;
2505  this->GetWidget<NWidgetCore>(WID_VV_SHOW_DETAILS)->tool_tip = STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP + v->type;
2506  this->GetWidget<NWidgetCore>(WID_VV_CLONE)->tool_tip = STR_VEHICLE_VIEW_CLONE_TRAIN_INFO + v->type;
2507 
2508  this->UpdateButtonStatus();
2509  }
2510 
2512  {
2517  }
2518 
2519  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2520  {
2521  const Vehicle *v = Vehicle::Get(this->window_number);
2522  switch (widget) {
2523  case WID_VV_START_STOP:
2524  size->height = max(size->height, max(GetSpriteSize(SPR_FLAG_VEH_STOPPED).height, GetSpriteSize(SPR_FLAG_VEH_RUNNING).height) + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2525  break;
2526 
2527  case WID_VV_FORCE_PROCEED:
2528  if (v->type != VEH_TRAIN) {
2529  size->height = 0;
2530  size->width = 0;
2531  }
2532  break;
2533 
2534  case WID_VV_VIEWPORT:
2535  size->width = VV_INITIAL_VIEWPORT_WIDTH;
2536  size->height = (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT;
2537  break;
2538  }
2539  }
2540 
2541  void OnPaint() override
2542  {
2543  const Vehicle *v = Vehicle::Get(this->window_number);
2544  bool is_localcompany = v->owner == _local_company;
2545  bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
2546 
2547  this->SetWidgetDisabledState(WID_VV_GOTO_DEPOT, !is_localcompany);
2548  this->SetWidgetDisabledState(WID_VV_REFIT, !refitable_and_stopped_in_depot || !is_localcompany);
2549  this->SetWidgetDisabledState(WID_VV_CLONE, !is_localcompany);
2550 
2551  if (v->type == VEH_TRAIN) {
2553  this->SetWidgetDisabledState(WID_VV_FORCE_PROCEED, !is_localcompany);
2554  this->SetWidgetDisabledState(WID_VV_TURN_AROUND, !is_localcompany);
2555  }
2556 
2557  this->DrawWidgets();
2558  }
2559 
2560  void SetStringParameters(int widget) const override
2561  {
2562  if (widget != WID_VV_CAPTION) return;
2563 
2564  const Vehicle *v = Vehicle::Get(this->window_number);
2565  SetDParam(0, v->index);
2566  }
2567 
2568  void DrawWidget(const Rect &r, int widget) const override
2569  {
2570  if (widget != WID_VV_START_STOP) return;
2571 
2572  const Vehicle *v = Vehicle::Get(this->window_number);
2573  StringID str;
2574  if (v->vehstatus & VS_CRASHED) {
2575  str = STR_VEHICLE_STATUS_CRASHED;
2576  } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
2577  str = STR_VEHICLE_STATUS_BROKEN_DOWN;
2578  } else if (v->vehstatus & VS_STOPPED) {
2579  if (v->type == VEH_TRAIN) {
2580  if (v->cur_speed == 0) {
2581  if (Train::From(v)->gcache.cached_power == 0) {
2582  str = STR_VEHICLE_STATUS_TRAIN_NO_POWER;
2583  } else {
2584  str = STR_VEHICLE_STATUS_STOPPED;
2585  }
2586  } else {
2587  SetDParam(0, v->GetDisplaySpeed());
2588  str = STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL;
2589  }
2590  } else { // no train
2591  str = STR_VEHICLE_STATUS_STOPPED;
2592  }
2593  } else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {
2594  str = STR_VEHICLE_STATUS_TRAIN_STUCK;
2595  } else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) {
2596  str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
2597  } else { // vehicle is in a "normal" state, show current order
2598  switch (v->current_order.GetType()) {
2599  case OT_GOTO_STATION: {
2601  SetDParam(1, v->GetDisplaySpeed());
2602  str = STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL;
2603  break;
2604  }
2605 
2606  case OT_GOTO_DEPOT: {
2607  SetDParam(0, v->type);
2609  SetDParam(2, v->GetDisplaySpeed());
2611  /* This case *only* happens when multiple nearest depot orders
2612  * follow each other (including an order list only one order: a
2613  * nearest depot order) and there are no reachable depots.
2614  * It is primarily to guard for the case that there is no
2615  * depot with index 0, which would be used as fallback for
2616  * evaluating the string in the status bar. */
2617  str = STR_EMPTY;
2618  } else if (v->current_order.GetDepotActionType() & ODATFB_HALT) {
2619  str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_VEL;
2620  } else {
2621  str = STR_VEHICLE_STATUS_HEADING_FOR_DEPOT_SERVICE_VEL;
2622  }
2623  break;
2624  }
2625 
2626  case OT_LOADING:
2627  str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
2628  break;
2629 
2630  case OT_GOTO_WAYPOINT: {
2631  assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
2633  str = STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL;
2634  SetDParam(1, v->GetDisplaySpeed());
2635  break;
2636  }
2637 
2638  case OT_LEAVESTATION:
2639  if (v->type != VEH_AIRCRAFT) {
2640  str = STR_VEHICLE_STATUS_LEAVING;
2641  break;
2642  }
2643  FALLTHROUGH;
2644  default:
2645  if (v->GetNumManualOrders() == 0) {
2646  str = STR_VEHICLE_STATUS_NO_ORDERS_VEL;
2647  SetDParam(0, v->GetDisplaySpeed());
2648  } else {
2649  str = STR_EMPTY;
2650  }
2651  break;
2652  }
2653  }
2654 
2655  /* Draw the flag plus orders. */
2656  bool rtl = (_current_text_dir == TD_RTL);
2657  uint text_offset = max(GetSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetSpriteSize(SPR_FLAG_VEH_RUNNING).width) + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
2658  int text_left = r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : text_offset);
2659  int text_right = r.right - (rtl ? text_offset : (uint)WD_FRAMERECT_RIGHT);
2660  int image_left = (rtl ? text_right + 1 : r.left) + WD_IMGBTN_LEFT;
2661  int image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING;
2662  int lowered = this->IsWidgetLowered(WID_VV_START_STOP) ? 1 : 0;
2663  DrawSprite(image, PAL_NONE, image_left + lowered, r.top + WD_IMGBTN_TOP + lowered);
2664  DrawString(text_left + lowered, text_right + lowered, r.top + WD_FRAMERECT_TOP + lowered, str, TC_FROMSTRING, SA_HOR_CENTER);
2665  }
2666 
2667  void OnClick(Point pt, int widget, int click_count) override
2668  {
2669  const Vehicle *v = Vehicle::Get(this->window_number);
2670 
2671  switch (widget) {
2672  case WID_VV_START_STOP: // start stop
2673  if (_ctrl_pressed) {
2674  /* Scroll to current order destination */
2675  TileIndex tile = v->current_order.GetLocation(v);
2676  if (tile != INVALID_TILE) ScrollMainWindowToTile(tile);
2677  } else {
2678  /* Start/Stop */
2679  StartStopVehicle(v, false);
2680  }
2681  break;
2682  case WID_VV_CENTER_MAIN_VIEW: {// center main view
2683  const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
2684  /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
2685  if (_ctrl_pressed && mainwindow->viewport->zoom <= ZOOM_LVL_OUT_4X) {
2686  mainwindow->viewport->follow_vehicle = v->index;
2687  } else {
2688  ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos);
2689  }
2690  break;
2691  }
2692 
2693  case WID_VV_GOTO_DEPOT: // goto hangar
2694  DoCommandP(v->tile, v->index | (_ctrl_pressed ? DEPOT_SERVICE : 0U), 0, GetCmdSendToDepot(v));
2695  break;
2696  case WID_VV_REFIT: // refit
2698  break;
2699  case WID_VV_SHOW_ORDERS: // show orders
2700  if (_ctrl_pressed) {
2702  } else {
2703  ShowOrdersWindow(v);
2704  }
2705  break;
2706  case WID_VV_SHOW_DETAILS: // show details
2707  if (_ctrl_pressed) {
2709  } else {
2711  }
2712  break;
2713  case WID_VV_CLONE: // clone vehicle
2714  /* Suppress the vehicle GUI when share-cloning.
2715  * There is no point to it except for starting the vehicle.
2716  * For starting the vehicle the player has to open the depot GUI, which is
2717  * most likely already open, but is also visible in the vehicle viewport. */
2718  DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0,
2719  _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type],
2720  _ctrl_pressed ? nullptr : CcCloneVehicle);
2721  break;
2722  case WID_VV_TURN_AROUND: // turn around
2723  assert(v->IsGroundVehicle());
2724  DoCommandP(v->tile, v->index, 0,
2725  _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
2726  break;
2727  case WID_VV_FORCE_PROCEED: // force proceed
2728  assert(v->type == VEH_TRAIN);
2729  DoCommandP(v->tile, v->index, 0, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
2730  break;
2731  }
2732  }
2733 
2734  void OnResize() override
2735  {
2736  if (this->viewport != nullptr) {
2737  NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_VV_VIEWPORT);
2738  nvp->UpdateViewportCoordinates(this);
2739  }
2740  }
2741 
2742  void UpdateButtonStatus()
2743  {
2744  const Vehicle *v = Vehicle::Get(this->window_number);
2745  bool veh_stopped = v->IsStoppedInDepot();
2746 
2747  /* Widget WID_VV_GOTO_DEPOT must be hidden if the vehicle is already stopped in depot.
2748  * Widget WID_VV_CLONE_VEH should then be shown, since cloning is allowed only while in depot and stopped.
2749  */
2750  PlaneSelections plane = veh_stopped ? SEL_DC_CLONE : SEL_DC_GOTO_DEPOT;
2751  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_DEPOT_CLONE); // Selection widget 'send to depot' / 'clone'.
2752  if (nwi->shown_plane + SEL_DC_BASEPLANE != plane) {
2753  this->SelectPlane(plane);
2755  }
2756  /* The same system applies to widget WID_VV_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
2757  if (v->IsGroundVehicle()) {
2758  PlaneSelections plane = veh_stopped ? SEL_RT_REFIT : SEL_RT_TURN_AROUND;
2759  NWidgetStacked *nwi = this->GetWidget<NWidgetStacked>(WID_VV_SELECT_REFIT_TURN);
2760  if (nwi->shown_plane + SEL_RT_BASEPLANE != plane) {
2761  this->SelectPlane(plane);
2763  }
2764  }
2765  }
2766 
2772  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2773  {
2774  if (data == VIWD_AUTOREPLACE) {
2775  /* Autoreplace replaced the vehicle.
2776  * Nothing to do for this window. */
2777  return;
2778  }
2779 
2780  this->UpdateButtonStatus();
2781  }
2782 
2783  bool IsNewGRFInspectable() const override
2784  {
2786  }
2787 
2788  void ShowNewGRFInspectWindow() const override
2789  {
2791  }
2792 };
2793 
2794 
2797 {
2798  AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
2799 }
2800 
2806 bool VehicleClicked(const Vehicle *v)
2807 {
2808  assert(v != nullptr);
2809  if (!(_thd.place_mode & HT_VEHICLE)) return false;
2810 
2811  v = v->First();
2812  if (!v->IsPrimaryVehicle()) return false;
2813 
2814  return _thd.GetCallbackWnd()->OnVehicleSelect(v);
2815 }
2816 
2817 void StopGlobalFollowVehicle(const Vehicle *v)
2818 {
2820  if (w != nullptr && w->viewport->follow_vehicle == v->index) {
2821  ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos, true); // lock the main view on the vehicle's last position
2823  }
2824 }
2825 
2826 
2835 void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
2836 {
2837  if (result.Failed()) return;
2838 
2839  const Vehicle *v = Vehicle::Get(_new_vehicle_id);
2841 }
2842 
2849 {
2850  switch (v->type) {
2851  case VEH_TRAIN:
2852  return Train::From(v)->GetDisplayImageWidth();
2853 
2854  case VEH_ROAD:
2856 
2857  default:
2858  bool rtl = _current_text_dir == TD_RTL;
2859  VehicleSpriteSeq seq;
2860  v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
2861  Rect rec;
2862  seq.GetBounds(&rec);
2863  return UnScaleGUI(rec.right - rec.left + 1);
2864  }
2865 }
2866 
2872 int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
2873 {
2874  if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
2875  int vehicle_width = 0;
2876  for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2877  vehicle_width += GetSingleVehicleWidth(u, image_type);
2878  }
2879  return vehicle_width;
2880  } else {
2881  return GetSingleVehicleWidth(v, image_type);
2882  }
2883 }
2884 
2891 {
2892  bool rtl = _current_text_dir == TD_RTL;
2893 
2894  _cursor.sprite_count = 0;
2895  int total_width = 0;
2896  for (; v != nullptr; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr) {
2897  if (total_width >= 2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH) break;
2898 
2900  VehicleSpriteSeq seq;
2901  v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
2902 
2903  if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
2904 
2905  for (uint i = 0; i < seq.count; ++i) {
2906  PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
2907  _cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
2908  _cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
2909  _cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
2910  _cursor.sprite_pos[_cursor.sprite_count].y = 0;
2911  _cursor.sprite_count++;
2912  }
2913 
2914  total_width += GetSingleVehicleWidth(v, image_type);
2915  }
2916 
2917  int offs = ((int)VEHICLEINFO_FULL_VEHICLE_WIDTH - total_width) / 2;
2918  if (rtl) offs = -offs;
2919  for (uint i = 0; i < _cursor.sprite_count; ++i) {
2920  _cursor.sprite_pos[i].x += offs;
2921  }
2922 
2923  UpdateCursorSize();
2924 }
Nested widget containing a viewport.
Definition: widget_type.h:79
static const uint32 _vehicle_command_translation_table[][4]
Command codes for the shared buttons indexed by VehicleCommandTranslation and vehicle type...
Functions related to OTTD&#39;s strings.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Road vehicle states.
void ShowNewGRFInspectWindow() const override
Show the NewGRF inspection window.
void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the given position.
Definition: train_gui.cpp:361
VehicleSettings vehicle
options for vehicles
Functions/types related to NewGRF debugging.
Date max_age
Maximum age.
Definition: vehicle_base.h:257
CargoID cargo
Cargo to refit to.
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
WindowNumber window_number
The WindowNumber of the window that is responsible for the selection mode.
Vehicle is stopped by the player.
Definition: vehicle_base.h:31
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:103
void RebuildDone()
Notify the sortlist that the rebuild is done.
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a road vehicle image in the GUI.
Definition: roadveh_cmd.cpp:90
std::vector< RefitOption > SubtypeList
List of refit subtypes associated to a cargo.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:79
Definition of stuff that is very close to a company, like the company struct itself.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:302
Money value
Value of the vehicle.
Definition: vehicle_base.h:239
Default settings for vehicles.
uint32 widget_data
Data of the widget.
Definition: widget_type.h:303
static const RailtypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:304
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:29
void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
Report a change in vehicle IDs (due to autoreplace) to affected vehicle windows.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
CompanyID company
The company associated with this list.
Definition: vehiclelist.h:32
PlaneSelections
Display planes available in the vehicle view window.
Horizontally center the text.
Definition: gfx_func.h:95
The information about a vehicle list.
Definition: vehiclelist.h:29
ResizeInfo resize
Resize information.
Definition: window_gui.h:322
CargoTypes _cargo_mask
Bitmask of cargo types available.
Definition: cargotype.cpp:29
void ScrollTowards(int position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition: widget_type.h:729
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:928
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1867
static const int VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition: vehicle_func.h:27
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:392
Offset at right of a matrix cell.
Definition: window_gui.h:77
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:453
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition: vehicle_base.h:564
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:66
static WindowDesc _vehicle_view_desc(WDP_AUTO, "view_vehicle", 250, 116, WC_VEHICLE_VIEW, WC_NONE, 0, _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets))
Vehicle view window descriptor for all vehicles but trains.
void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
Draws an image of a ship.
Definition: ship_gui.cpp:32
Window * parent
Parent window.
Definition: window_gui.h:337
High level window description.
Definition: window_gui.h:166
Functions related to the autoreplace GUIs.
Vehicle * GetFirstEnginePart()
Get the first part of an articulated engine.
Definition: vehicle_base.h:919
uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1916
rename a whole vehicle
Definition: command_type.h:242
int sprite_right
Right position of the vehicle sprite.
WindowFlags flags
Window flags.
Definition: window_gui.h:310
StringID tool_tip
Tooltip of the widget.
Definition: widget_type.h:304
int left
x position of left edge of the window
Definition: window_gui.h:317
StringID GetAircraftTypeText() const
Get the name of the aircraft type for display purposes.
Definition: engine.cpp:468
Functions related to time tabling.
void DrawAircraftDetails(const Aircraft *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
bool VehicleClicked(const Vehicle *v)
Dispatch a "vehicle selected" event if any window waits for it.
Train vehicle type.
Definition: vehicle_type.h:24
union Vehicle::@49 orders
The orders currently assigned to the vehicle.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:602
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:291
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition: engine.cpp:171
void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a vehicle chain.
static Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap...
Definition: landscape.h:82
Header with question about the cargo to carry.
Show details of this vehicle.
Scrollbar data structure.
Definition: widget_type.h:587
Vehicle composition was changed.
Definition: vehicle_gui.h:34
Stacked widgets, widgets all occupying the same space in the window.
Definition: widget_type.h:403
West.
Base for the train class.
Point sprite_pos[16]
relative position of individual sprites
Definition: gfx_type.h:129
void SetWidgetDirty(byte widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:597
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:21
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:62
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Sort order.
void UpdateViewportCoordinates(Window *w)
Update the position and size of the viewport (after eg a resize).
Definition: widget.cpp:1934
void OnMouseDrag(Point pt, int widget) override
An &#39;object&#39; is being dragged at the provided position, highlight the target if possible.
Functions related to debugging.
static bool VehicleValueSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their value.
Horizontal container.
Definition: widget_type.h:73
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1130
change the server interval of a vehicle
Definition: command_type.h:230
static void DrawVehicleProfitButton(const Vehicle *v, int x, int y)
draw the vehicle profit button in the vehicle list window.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:52
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:36
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:35
uint16 cur_speed
current speed
Definition: vehicle_base.h:291
query cost only, don&#39;t build.
Definition: command_type.h:346
void CDECL SetWidgetsDisabledState(bool disab_stat, int widgets,...)
Sets the enabled/disabled status of a list of widgets.
Definition: window.cpp:536
NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX) ...
Definition: widget_type.h:61
uint sprite_count
number of sprites to draw
Definition: gfx_type.h:130
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:1119
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:76
Ship vehicle type.
Definition: vehicle_type.h:26
Maximal number of cargo types in a game.
Definition: cargo_type.h:64
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Tab with cargo capacity of the vehicles.
Definition: vehicle_gui.h:26
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:514
uint16 _returned_refit_capacity
Stores the capacity after a refit operation.
Definition: vehicle.cpp:85
#define FOR_ALL_SORTED_CARGOSPECS(var)
Loop header for iterating over cargoes, sorted by name.
Definition: cargotype.h:164
Specification of a cargo type.
Definition: cargotype.h:55
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
GUIVehicleList vehicles
The list of vehicles.
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:319
static WindowDesc _train_vehicle_details_desc(WDP_AUTO, "view_vehicle_details_train", 405, 178, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, _nested_train_vehicle_details_widgets, lengthof(_nested_train_vehicle_details_widgets))
Vehicle details window descriptor.
Clone this vehicle.
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:66
Pressed (inset) panel, most commonly used as combo box text area.
Definition: widget_type.h:49
Manage vehicles dropdown list.
Sort by dropdown list.
Show carried cargo per part of the train.
Vehicle data structure.
Definition: vehicle_base.h:210
Caption of window.
static bool IsExpected(const BaseStation *st)
Helper for checking whether the given station is of this type.
Scrollbar * vscroll
The main scrollbar.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Start or stop this vehicle, and show information about the current state.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:189
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:101
virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Definition: vehicle_base.h:440
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:28
Close box (at top-left of a window)
Definition: widget_type.h:67
Offset at top of a matrix cell.
Definition: window_gui.h:78
PaletteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition: vehicle.cpp:1982
Rename this vehicle.
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0...
void CcStartStopVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after attempting to start/stop a vehicle.
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
Base for aircraft.
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:963
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Horizontal scrollbar or the vehicle display.
void ReInit(int rx=0, int ry=0)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:995
Show the orders of this vehicle.
StringID GetGRFStringID(uint32 grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
void RefreshScrollbar()
Refresh scrollbar after selection changed.
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:82
Stuff related to the text buffer GUI.
static bool VehicleLengthSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their length.
WindowClass
Window classes.
Definition: window_type.h:37
byte GetDigitWidth(FontSize size)
Return the maximum width of single digit.
Definition: gfx.cpp:1165
int32 lateness_counter
How many ticks late (or early if negative) this vehicle is.
Definition: base_consist.h:22
void DisableWidget(byte widget_index)
Sets a widget to disabled.
Definition: window_gui.h:402
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
List of the vehicles.
Invalid window.
Definition: window_type.h:694
Common return value for all commands.
Definition: command_type.h:23
uint32 cached_power
Total power of the consist (valid only for the first engine).
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
Determine the cargo "suffixes" for each refit possibility of a cargo.
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after the construction attempt of a primary vehicle.
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:55
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
uint8 advanced_vehicle_list
use the "advanced" vehicle list
byte vehstatus
Status.
Definition: vehicle_base.h:315
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:85
WindowClass cls
Class of the window,.
Definition: window_gui.h:175
Cached, frequently calculated values.
Nested widget to display a viewport in a window.
Definition: widget_type.h:573
TileIndex GetLocation(const Vehicle *v, bool airport=false) const
Returns a tile somewhat representing the order destination (not suitable for pathfinding).
Definition: order_cmd.cpp:668
Common string list item.
Definition: dropdown_type.h:39
Option to refit a vehicle chain.
static Train * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Display &#39;goto depot&#39; button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
uint16 cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:121
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1828
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:741
void SetListing(Listing l)
Import sort conditions.
Ignore next signal, after the signal ignore being stuck.
Definition: train.h:40
Window * GetCallbackWnd()
Get the window that started the current highlighting.
Definition: viewport.cpp:2469
StringID name
Name of this type of cargo.
Definition: cargotype.h:70
Display &#39;clone vehicle&#39; button in WID_VV_SELECT_DEPOT_CLONE stacked widget.
bool NeedRebuild() const
Check if a rebuild is needed.
HighLightStyle place_mode
Method which is used to place the selection.
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:137
static const ZoomLevel _vehicle_view_zoom_levels[]
Zoom levels for vehicle views indexed by vehicle type.
virtual bool OnVehicleSelect(const struct Vehicle *v)
The user clicked on a vehicle while HT_VEHICLE has been set.
Definition: window_gui.h:758
Display with a representation of the vehicle to refit.
DepotCommand
Flags to add to p1 for goto depot commands.
Definition: vehicle_type.h:65
uint16 servint_ships
service interval for ships
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:175
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:49
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:673
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:668
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
Functions related to (drawing on) viewports.
start or stop a vehicle
Definition: command_type.h:311
void ForceRebuild()
Force that a rebuild is needed.
void ShowCompanyGroupForVehicle(const Vehicle *v)
Show the group window for the given vehicle.
Definition: group_gui.cpp:1071
StringID string
GRF-local String to display for the cargo.
void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
Draws an image of an aircraft.
bool IsEngineRefittable(EngineID engine)
Check if an engine is refittable.
Definition: engine.cpp:1103
Default zoom level for the aircraft view.
Definition: zoom_type.h:37
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Data structure for an opened window.
Definition: window_gui.h:276
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:261
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:35
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1844
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1030
Autoreplace replaced the vehicle.
Definition: vehicle_gui.h:35
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1044
Vehicle drawn in vehicle details, refit window, ...
Definition: vehicle_type.h:88
dragging items in the depot windows
uint16 cargo_cap
total capacity
Definition: vehicle_base.h:305
Bottom offset of image in the button.
Definition: window_gui.h:41
Header of Action 04 "universal holder" structure and functions.
Main window; Window numbers:
Definition: window_type.h:44
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:21
Vehicle orders; Window numbers:
Definition: window_type.h:205
proceed a train to pass a red signal
Definition: command_type.h:221
virtual int GetDisplayMaxSpeed() const
Gets the maximum speed in km-ish/h that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:484
Money GetDisplayRunningCost() const
Gets the running cost of a vehicle that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:558
Map related accessors for depots.
void SelectPlane(PlaneSelections plane)
Display a plane in the window.
void ShowCompanyGroup(CompanyID company, VehicleType vehicle_type, GroupID group=INVALID_GROUP, bool need_existing_window=false)
Show the group window for the given company and vehicle type.
Definition: group_gui.cpp:1052
Functions related to low-level strings.
Vehicle is crashed.
Definition: vehicle_base.h:37
byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
Get the best fitting subtype when &#39;cloning&#39;/&#39;replacing&#39; v_from with v_for.
The tile has no ownership.
Definition: company_type.h:25
uint GetRoadVehDetailsHeight(const Vehicle *v)
Gets the desired height for the road vehicle details panel.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:431
Window manager class for viewing a vehicle.
Scrollbar * hscroll
Only used for long vehicles.
static const uint MAX_LENGTH_VEHICLE_NAME_CHARS
The maximum length of a vehicle name in characters including &#39;\0&#39;.
Definition: vehicle_type.h:73
Offset at bottom of a matrix cell.
Definition: window_gui.h:79
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:289
#define FONT_HEIGHT_SMALL
Height of characters in the small (FS_SMALL) font.
Definition: gfx_func.h:173
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:441
void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
Draw all the vehicle list items.
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:63
byte cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:304
bool operator!=(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Inverse of operator==().
Definition: multimap.hpp:220
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1957
bool IsNewGRFInspectable() const override
Is the data related to this window NewGRF inspectable?
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:208
bool IsWidgetLowered(byte widget_index) const
Gets the lowered state of a widget.
Definition: window_gui.h:493
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Listing GetListing() const
Export current sort conditions.
static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type, CompanyID company_id)
Checks whether service interval is enabled for the vehicle.
Turn this vehicle around.
int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (part) in pixels.
Functions related to engines.
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition: vehicle.cpp:2824
Scrollbar for the refit options.
uint current_y
Current vertical size (after resizing).
Definition: widget_type.h:173
void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
Definition: roadveh_gui.cpp:30
East.
uint32 index
A vehicle list type specific index.
Definition: vehiclelist.h:33
void OnPaint() override
The window must be repainted.
Sort descending.
Definition: window_gui.h:225
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
Show the refit window for a vehicle.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:61
DropDownList BuildActionDropdownList(bool show_autoreplace, bool show_group)
Display the Action dropdown window.
static void ChangeVehicleWindow(WindowClass window_class, VehicleID from_index, VehicleID to_index)
Assign a vehicle window a new vehicle.
Options to refit to.
Viewport widget.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:176
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
T * Next() const
Get next vehicle in the chain.
byte callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:143
Selection widget between &#39;goto depot&#39;, and &#39;clone vehicle&#39; buttons.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:78
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:387
static bool VehicleProfitThisYearSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by this year profit.
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
Definition of base types and functions in a cross-platform compatible way.
Show suffix after cargo name.
static bool VehicleProfitLastYearSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by last year profit.
Decrease the servicing interval.
Tells that it&#39;s a mass send to depot command (type in VLW flag)
Definition: vehicle_type.h:67
the length of the string is counted in characters
Definition: textbuf_gui.h:22
void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip, VehicleID drag_dest)
Draws an image of a whole train.
Definition: train_gui.cpp:92
Force this vehicle to pass a signal at danger.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:890
A number of safeguards to prevent using unsafe methods.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:245
Default zoom level for the ship view.
Definition: zoom_type.h:38
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:102
Geometry functions.
Vehicle refit; Window numbers:
Definition: window_type.h:199
Simple depressed panel.
Definition: widget_type.h:48
Selection widget for the horizontal scrollbar.
void OnPaint() override
The window must be repainted.
void StartStopVehicle(const Vehicle *v, bool texteffect)
Executes CMD_START_STOP_VEHICLE for given vehicle.
bool operator==(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Compare two MultiMap iterators.
Definition: multimap.hpp:203
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:303
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:636
Horizontal scrollbar.
Definition: widget_type.h:81
uint step_height
Step-size of height resize changes.
Definition: window_gui.h:218
Scrollbar for the list.
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:309
uint16 GetRange() const
Get the range of this aircraft.
Definition: aircraft.h:133
Vehicle view; Window numbers:
Definition: window_type.h:332
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:175
Offset at left of a matrix cell.
Definition: window_gui.h:76
VehicleOrderID order
If not INVALID_VEH_ORDER_ID, selection is part of a refit order (rather than execute directly)...
static bool VehicleModelSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by model.
byte subtype
Subcargo to use.
byte misc_flags
Miscellaneous flags.
Definition: engine_type.h:142
Order * GetFirstOrder() const
Get the first order of the order chain.
Definition: order_base.h:288
static VehicleListIdentifier UnPack(uint32 data)
Decode a packed vehicle list identifier into a new one.
Definition: vehiclelist.cpp:53
TileIndex tile
Current tile index.
Definition: vehicle_base.h:228
TrainDetailsWindowTabs tab
For train vehicles: which tab is displayed.
void DrawShipDetails(const Vehicle *v, int left, int right, int y)
Draw the details for the given vehicle at the given position.
Definition: ship_gui.cpp:64
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1112
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:899
Vehicle timetable; Window numbers:
Definition: window_type.h:217
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:63
Baseclass for nested widgets.
Definition: widget_type.h:124
void OnResize() override
Called after the window got resized.
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:498
void ShowVehicleViewWindow(const Vehicle *v)
Shows the vehicle view window of the given vehicle.
int GetVehicleWidth(const Vehicle *v, EngineImageType image_type)
Get the width of a vehicle (including all parts of the consist) in pixels.
Increase the servicing interval.
Service the vehicle and then halt it.
Definition: order_type.h:104
void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
Draws an image of a road vehicle chain.
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:271
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:128
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:532
Default zoom level for the road vehicle view.
Definition: zoom_type.h:40
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
Start all button.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Grid of rows and columns.
Definition: widget_type.h:57
VehicleID follow_vehicle
VehicleID to follow if following a vehicle, INVALID_VEHICLE otherwise.
Definition: window_gui.h:257
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
static const NWidgetPart _nested_train_vehicle_details_widgets[]
Train details widgets.
Right offset of the image in the button.
Definition: window_gui.h:39
void OnGameTick() override
Called once per (game) tick.
byte breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:263
uint16 reliability
Reliability.
Definition: vehicle_base.h:259
void SetSortType(uint8 n_type)
Set the sorttype of the list.
bool Sort(SortFunction *compare)
Sort the list.
static bool VehicleTimeToLiveSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by the time they can still live.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:656
void OnResize() override
Called after the window got resized.
Functions to cache sprites in memory.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:592
Class for managing the vehicle details window.
bool Failed() const
Did this command fail?
Definition: command_type.h:159
Tab with cargo carried by the vehicles.
Definition: vehicle_gui.h:24
Show all parts of the train with their description.
static bool VehicleMaxSpeedSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their max speed.
bool auto_refit
Select cargo for auto-refitting.
static DepotID GetDepotIndex(TileIndex t)
Get the index of which depot is attached to the tile.
Definition: depot_map.h:52
Draw border only, no background.
Definition: window_gui.h:28
static const int WIDGET_LIST_END
indicate the end of widgets&#39; list for vararg functions
Definition: widget_type.h:20
Details for non-trains.
int vehicle_width
Width of the vehicle being drawn.
static bool VehicleCargoSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their cargo.
static const SpriteID SPR_CLONE_TRAIN
Clone vehicles stuff.
Definition: sprites.h:100
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
Functions/classes shared between the different vehicle list GUIs.
static const NWidgetPart _nested_vehicle_view_widgets[]
Vehicle view widgets.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:984
int sprite_left
Left position of the vehicle sprite.
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
&#39;Train&#39; is either a loco or a wagon.
Definition: train.h:85
VehicleDetailsWindow(WindowDesc *desc, WindowNumber window_number)
Initialize a newly created vehicle details window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1162
PalSpriteID sprite_seq[16]
current image of cursor
Definition: gfx_type.h:128
char * name
Name of vehicle.
Definition: base_consist.h:18
Selection widget between &#39;refit&#39; and &#39;turn around&#39; buttons.
Open the refit window.
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:17
The vehicle will leave the depot right after arrival (service only)
Definition: vehicle_type.h:66
static WindowDesc _nontrain_vehicle_details_desc(WDP_AUTO, "view_vehicle_details", 405, 113, WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, 0, _nested_nontrain_vehicle_details_widgets, lengthof(_nested_nontrain_vehicle_details_widgets))
Vehicle details window descriptor for other vehicles than a train.
static int32 ClampToI32(const int64 a)
Reduce a signed 64-bit int to a signed 32-bit one.
Definition: math_func.hpp:201
Functions related to companies.
uint GetUnitNumberDigits(VehicleList &vehicles)
Get the number of digits the biggest unit number of a set of vehicles has.
int GetDisplayImageWidth(Point *offset=nullptr) const
Get the width of a train vehicle image in the GUI.
Definition: train_cmd.cpp:432
Window for the (old) vehicle listing.
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:28
Vehicle drawn in vehicle list, group list, ...
Definition: vehicle_type.h:89
bool IsNewGRFInspectable(GrfSpecFeature feature, uint index)
Can we inspect the data given a certain feature and index.
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:3290
bool ScrollMainWindowTo(int x, int y, int z, bool instant)
Scrolls the main window to given coordinates.
TrainDetailsWindowTabs
The tabs in the train details window.
Definition: vehicle_gui.h:23
static bool VehicleTimetableDelaySorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by the timetable delay.
Functions related to articulated vehicles.
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Class for storing amounts of cargo.
Definition: cargo_type.h:81
Automatic refitting is allowed.
Definition: engine_type.h:158
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
StringID GetCapacityString(RefitOption *option) const
Gets the StringID to use for displaying capacity.
Display &#39;turn around&#39; button in WID_VV_SELECT_REFIT_TURN stacked widget.
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:469
Train can&#39;t get a path reservation.
Definition: train.h:32
GUISettings gui
settings related to the GUI
void SetSelection(uint click_row)
Select a row.
void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
Set the mouse cursor to look like a vehicle.
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:94
void ShowTimetableWindow(const Vehicle *v)
Show the timetable for a given vehicle.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:59
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:578
VehicleCommandTranslation
Command indices for the _vehicle_command_translation_table.
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
Center the main view on this vehicle.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1531
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:117
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1587
uint32 Pack() const
Pack a VehicleListIdentifier in a single uint32.
Definition: vehiclelist.cpp:21
RefitOption * cargo
Refit option selected by sel.
Available vehicles.
uint16 servint_trains
service interval for trains
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:579
static WindowDesc _train_view_desc(WDP_AUTO, "view_vehicle_train", 250, 134, WC_VEHICLE_VIEW, WC_NONE, 0, _nested_vehicle_view_widgets, lengthof(_nested_vehicle_view_widgets))
Vehicle view window descriptor for trains.
Date date_of_last_service
Last date the vehicle had a service at a depot.
Definition: vehicle_base.h:258
bool include(std::vector< T > &vec, const T &item)
Helper function to append an item to a vector if it is not already contained Consider using std::set...
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:48
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here...
List of details for trains.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
virtual void ShowNewGRFInspectWindow() const
Show the NewGRF inspection window.
Definition: window_gui.h:809
Sort ascending.
Definition: window_gui.h:224
Panel with generic details.
static bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:2887
Send the vehicle to the nearest depot.
Definition: order_type.h:105
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:104
Caption of window.
Tab with sum of total cargo transported.
Definition: vehicle_gui.h:27
Display &#39;refit&#39; button in WID_VV_SELECT_REFIT_TURN stacked widget.
Order this vehicle to go to the depot.
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Next destination is too far away.
Definition: aircraft.h:39
Top offset of image in the button.
Definition: window_gui.h:40
VehicleListType type
The type of vehicle list.
Definition: vehiclelist.h:30
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
Vertical container.
Definition: widget_type.h:75
turn a train around
Definition: command_type.h:222
Vehicle * GetNextArticulatedPart() const
Get the next part of an articulated engine.
Definition: vehicle_base.h:909
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:997
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint16 cached_total_length
Length of the whole vehicle (valid only for the first engine).
Trains list; Window numbers:
Definition: window_type.h:301
Functions related to zooming.
uint information_width
Width required for correctly displaying all cargoes in the information panel.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:52
VehicleListType
Vehicle List type flags.
Definition: vehiclelist.h:19
Information about the servicing interval.
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:418
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:172
static void ShowVehicleDetailsWindow(const Vehicle *v)
Shows the vehicle details window of the given vehicle.
int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab)
Determines the number of lines in the train details window.
Definition: train_gui.cpp:318
void OnPaint() override
Repaint vehicle details window.
static const Money VEHICLE_PROFIT_THRESHOLD
Threshold for a vehicle to be considered making good profit.
Definition: vehicle_func.h:28
change the refit information of an order (for "goto depot" )
Definition: command_type.h:269
void OnResize() override
Called after the window got resized.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
uint16 _returned_mail_refit_capacity
Stores the mail capacity after a refit operation (Aircraft only).
Definition: vehicle.cpp:86
uint16 servint_aircraft
service interval for aircraft
Refit cargo window.
Show the capacity and carried cargo amounts aggregated per cargo of the train.
static uint GetVehicleHeight(VehicleType type)
Get the height of a single vehicle in the GUIs.
Definition: vehicle_gui.h:68
static uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:298
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
static const NWidgetPart _nested_nontrain_vehicle_details_widgets[]
Vehicle details widgets (other than train).
int32 z_pos
z coordinate.
Definition: vehicle_base.h:268
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2396
VehicleListIdentifier vli
Identifier of the vehicle list we want to currently show.
Vehicle details; Window numbers:
Definition: window_type.h:193
Scrollbar for train details.
static uint CountBits(T value)
Counts the number of set bits in a variable.
Bottom offset of the dropdown widget string.
Definition: window_gui.h:135
Functions/definitions that have something to do with groups.
Functions related to commands.
Caption of window.
Coordinates of a point in 2D.
clone a vehicle
Definition: command_type.h:310
int click_x
Position of the first click while dragging.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:770
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:88
void SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition: widget.cpp:1082
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:280
uint32 GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:761
void OnQueryTextFinished(char *str) override
The query window opened from this window has closed.
uint8 train_acceleration_model
realistic acceleration for trains
Make the text effect slowly go upwards.
Definition: texteff.hpp:21
Drop down list.
Definition: widget_type.h:68
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:104
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:620
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:91
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
start/stop all vehicles (in a depot)
Definition: command_type.h:312
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Window does not do autoscroll,.
Definition: window_gui.h:239
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or nullptr when it doesn&#39;t exists.
Definition: vehicle_base.h:858
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable...
Definition: window_gui.h:324
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
uint8 num_vehicles
Number of selected vehicles.
Aircraft vehicle type.
Definition: vehicle_type.h:27
uint8 roadveh_acceleration_model
realistic acceleration for road vehicles
vehicle is accepted as target as well (bitmask)
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:286
ZoomLevel zoom
The zoom level of the viewport.
Definition: viewport_type.h:33
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:64
void BuildRefitList()
Collects all (cargo, subcargo) refit options of a vehicle chain.
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:319
uint GetVehicleListHeight(VehicleType type, uint divisor)
Get the height of a vehicle in the vehicle list GUIs.
static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
Draw the list of available refit options for a consist and highlight the selected refit option (if an...
int32 x_pos
x coordinate.
Definition: vehicle_base.h:266
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:15
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:981
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Show the capacity of all train parts.
Information about the currently selected refit option.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:19
Perform the refit.
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:751
bool IsDescSortOrder() const
Check if the sort order is descending.
#define CMD_MSG(x)
Used to combine a StringID with the command.
Definition: command_type.h:368
static bool IsVehicleRefitable(const Vehicle *v)
Checks whether the vehicle may be refitted at the moment.
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:705
virtual int GetDisplaySpeed() const
Gets the speed in km-ish/h that can be sent into SetDParam for string processing. ...
Definition: vehicle_base.h:478
WindowClass window_class
Window class.
Definition: window_gui.h:311
uint16 servint_roadveh
service interval for road vehicles
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:67
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1971
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:82
WindowClass window_class
The WindowClass of the window that is responsible for the selection mode.
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
int32 y_pos
y coordinate.
Definition: vehicle_base.h:267
byte unitnumber_digits
The number of digits of the highest unit number.
Text is written right-to-left by default.
Definition: strings_type.h:24
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:312
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
ButtonPlanes
Enumeration of planes of the button row at the bottom.
uint32 cached_max_te
Maximum tractive effort of consist (valid only for the first engine).
Functions related to tile highlights.
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:508
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
Display list of cargo types of the engine, for the purchase information window.
StringID GetCargoSubtypeText(const Vehicle *v)
Get the cargo subtype text from NewGRF for the vehicle details window.
static const uint MAX_REFIT_CYCLE
Maximum number of refit cycles we try, to prevent infinite loops.
Find a place automatically.
Definition: window_gui.h:154
void OnDragDrop(Point pt, int widget) override
A dragged &#39;object&#39; has been released.
Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group)
Compute the size for the Action dropdown.
static bool VehicleNumberSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their number.
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition: vehiclelist.h:53
void OnResize() override
Called after the window got resized.
SpriteID sprite
The &#39;real&#39; sprite.
Definition: gfx_type.h:23
Dropdown to select default/days/percent service interval.
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:78
void OnPaint() override
The window must be repainted.
ViewportData * viewport
Pointer to viewport data, if present.
Definition: window_gui.h:326
GUI functions that shouldn&#39;t be here.
bool SortFunction(const T &, const T &)
Signature of sort function.
Definition: sortlist_type.h:49
Listing * sorting
Pointer to the vehicle type related sorting.
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
Definition: sprites.h:1367
Base classes/functions for stations.
Zoomed 4 times out.
Definition: zoom_type.h:24
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:328
void CcCloneVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd)
This is the Callback method after the cloning attempt of a vehicle.
Definition: depot_gui.cpp:120
Default zoom level for the train view.
Definition: zoom_type.h:39
Caption of window.
virtual void SetDirty(const Window *w) const
Mark the widget as &#39;dirty&#39; (in need of repaint).
Definition: widget.cpp:773
static bool VehicleReliabilitySorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their reliability.
Left offset of the image in the button.
Definition: window_gui.h:38
VehicleType vtype
The vehicle type associated with this list.
Definition: vehiclelist.h:31
Date age
Age in days.
Definition: vehicle_base.h:256
RefitOption * GetRefitOption()
Gets the RefitOption placed in the selected index.
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1093
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:27
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:92
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:62
uint32 cached_weight
Total weight of the consist (valid only for the first engine).
void InvalidateNewGRFCache()
Invalidates cached NewGRF variables.
Definition: vehicle_base.h:449
Money GetDisplayProfitLastYear() const
Gets the profit vehicle had last year.
Definition: vehicle_base.h:570
Road vehicle type.
Definition: vehicle_type.h:25
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:98
uint vehicle_margin
Margin to use while selecting vehicles when the vehicle image is centered.
static bool VehicleAgeSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their age.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:835
turn a road vehicle around
Definition: command_type.h:252
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:316
void OnInit() override
Notification that the nested widget tree gets initialized.
VehicleID selected_vehicle
First vehicle in the current selection.
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window&#39;s data as invalid (in need of re-computing)
Definition: window.cpp:3256
Top offset of the dropdown widget string.
Definition: window_gui.h:134
Selection to hide the buttons.
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:324
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:30
static bool VehicleNameSorter(const Vehicle *const &a, const Vehicle *const &b)
Sort vehicles by their name.
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:320
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:621
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition: window_gui.h:743
(Toggle) Button with text
Definition: widget_type.h:53
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:691
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:629
Tab with name and value of the vehicles.
Definition: vehicle_gui.h:25
uint8 SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:94
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:282
static void DrawVehicleDetails(const Vehicle *v, int left, int right, int y, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
Draw the details for the given vehicle at the position of the Details windows.
static const GroupID ALL_GROUP
All vehicles are in this group.
Definition: group_type.h:16
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:24
Stop all button.