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