OpenTTD
build_vehicle_gui.cpp
Go to the documentation of this file.
1 /* $Id: build_vehicle_gui.cpp 27799 2017-03-18 20:46:15Z alberth $ */
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 "engine_base.h"
14 #include "engine_func.h"
15 #include "station_base.h"
16 #include "network/network.h"
17 #include "articulated_vehicles.h"
18 #include "textbuf_gui.h"
19 #include "command_func.h"
20 #include "company_func.h"
21 #include "vehicle_gui.h"
22 #include "newgrf_engine.h"
23 #include "newgrf_text.h"
24 #include "group.h"
25 #include "string_func.h"
26 #include "strings_func.h"
27 #include "window_func.h"
28 #include "date_func.h"
29 #include "vehicle_func.h"
30 #include "widgets/dropdown_func.h"
31 #include "engine_gui.h"
32 #include "cargotype.h"
33 #include "core/geometry_func.hpp"
34 #include "autoreplace_func.h"
35 
37 
38 #include "table/strings.h"
39 
40 #include "safeguards.h"
41 
48 {
50 }
51 
52 static const NWidgetPart _nested_build_vehicle_widgets[] = {
54  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
55  NWidget(WWT_CAPTION, COLOUR_GREY, WID_BV_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
56  NWidget(WWT_SHADEBOX, COLOUR_GREY),
57  NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
58  NWidget(WWT_STICKYBOX, COLOUR_GREY),
59  EndContainer(),
60  NWidget(WWT_PANEL, COLOUR_GREY),
63  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
64  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
65  EndContainer(),
68  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_BV_CARGO_FILTER_DROPDOWN), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA),
69  EndContainer(),
70  EndContainer(),
71  EndContainer(),
72  /* Vehicle list. */
74  NWidget(WWT_MATRIX, COLOUR_GREY, WID_BV_LIST), SetResize(1, 1), SetFill(1, 0), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_BV_SCROLLBAR),
76  EndContainer(),
77  /* Panel with details. */
78  NWidget(WWT_PANEL, COLOUR_GREY, WID_BV_PANEL), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
79  /* Build/rename buttons, resize button. */
81  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_BV_BUILD_SEL),
82  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_BUILD), SetResize(1, 0), SetFill(1, 0),
83  EndContainer(),
84  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_SHOW_HIDE), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_NULL),
85  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BV_RENAME), SetResize(1, 0), SetFill(1, 0),
86  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
87  EndContainer(),
88 };
89 
91 static const CargoID CF_ANY = CT_NO_REFIT;
92 static const CargoID CF_NONE = CT_INVALID;
93 
95 byte _engine_sort_last_criteria[] = {0, 0, 0, 0};
96 bool _engine_sort_last_order[] = {false, false, false, false};
97 bool _engine_sort_show_hidden_engines[] = {false, false, false, false};
99 
106 static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b)
107 {
108  int r = Engine::Get(*a)->list_position - Engine::Get(*b)->list_position;
109 
110  return _engine_sort_direction ? -r : r;
111 }
112 
119 static int CDECL EngineIntroDateSorter(const EngineID *a, const EngineID *b)
120 {
121  const int va = Engine::Get(*a)->intro_date;
122  const int vb = Engine::Get(*b)->intro_date;
123  const int r = va - vb;
124 
125  /* Use EngineID to sort instead since we want consistent sorting */
126  if (r == 0) return EngineNumberSorter(a, b);
127  return _engine_sort_direction ? -r : r;
128 }
129 
136 static int CDECL EngineNameSorter(const EngineID *a, const EngineID *b)
137 {
138  static EngineID last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE };
139  static char last_name[2][64] = { "\0", "\0" };
140 
141  const EngineID va = *a;
142  const EngineID vb = *b;
143 
144  if (va != last_engine[0]) {
145  last_engine[0] = va;
146  SetDParam(0, va);
147  GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0]));
148  }
149 
150  if (vb != last_engine[1]) {
151  last_engine[1] = vb;
152  SetDParam(0, vb);
153  GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1]));
154  }
155 
156  int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
157 
158  /* Use EngineID to sort instead since we want consistent sorting */
159  if (r == 0) return EngineNumberSorter(a, b);
160  return _engine_sort_direction ? -r : r;
161 }
162 
169 static int CDECL EngineReliabilitySorter(const EngineID *a, const EngineID *b)
170 {
171  const int va = Engine::Get(*a)->reliability;
172  const int vb = Engine::Get(*b)->reliability;
173  const int r = va - vb;
174 
175  /* Use EngineID to sort instead since we want consistent sorting */
176  if (r == 0) return EngineNumberSorter(a, b);
177  return _engine_sort_direction ? -r : r;
178 }
179 
186 static int CDECL EngineCostSorter(const EngineID *a, const EngineID *b)
187 {
188  Money va = Engine::Get(*a)->GetCost();
189  Money vb = Engine::Get(*b)->GetCost();
190  int r = ClampToI32(va - vb);
191 
192  /* Use EngineID to sort instead since we want consistent sorting */
193  if (r == 0) return EngineNumberSorter(a, b);
194  return _engine_sort_direction ? -r : r;
195 }
196 
203 static int CDECL EngineSpeedSorter(const EngineID *a, const EngineID *b)
204 {
205  int va = Engine::Get(*a)->GetDisplayMaxSpeed();
206  int vb = Engine::Get(*b)->GetDisplayMaxSpeed();
207  int r = va - vb;
208 
209  /* Use EngineID to sort instead since we want consistent sorting */
210  if (r == 0) return EngineNumberSorter(a, b);
211  return _engine_sort_direction ? -r : r;
212 }
213 
220 static int CDECL EnginePowerSorter(const EngineID *a, const EngineID *b)
221 {
222  int va = Engine::Get(*a)->GetPower();
223  int vb = Engine::Get(*b)->GetPower();
224  int r = va - vb;
225 
226  /* Use EngineID to sort instead since we want consistent sorting */
227  if (r == 0) return EngineNumberSorter(a, b);
228  return _engine_sort_direction ? -r : r;
229 }
230 
237 static int CDECL EngineTractiveEffortSorter(const EngineID *a, const EngineID *b)
238 {
239  int va = Engine::Get(*a)->GetDisplayMaxTractiveEffort();
240  int vb = Engine::Get(*b)->GetDisplayMaxTractiveEffort();
241  int r = va - vb;
242 
243  /* Use EngineID to sort instead since we want consistent sorting */
244  if (r == 0) return EngineNumberSorter(a, b);
245  return _engine_sort_direction ? -r : r;
246 }
247 
254 static int CDECL EngineRunningCostSorter(const EngineID *a, const EngineID *b)
255 {
256  Money va = Engine::Get(*a)->GetRunningCost();
257  Money vb = Engine::Get(*b)->GetRunningCost();
258  int r = ClampToI32(va - vb);
259 
260  /* Use EngineID to sort instead since we want consistent sorting */
261  if (r == 0) return EngineNumberSorter(a, b);
262  return _engine_sort_direction ? -r : r;
263 }
264 
271 static int CDECL EnginePowerVsRunningCostSorter(const EngineID *a, const EngineID *b)
272 {
273  const Engine *e_a = Engine::Get(*a);
274  const Engine *e_b = Engine::Get(*b);
275 
276  /* Here we are using a few tricks to get the right sort.
277  * We want power/running cost, but since we usually got higher running cost than power and we store the result in an int,
278  * we will actually calculate cunning cost/power (to make it more than 1).
279  * Because of this, the return value have to be reversed as well and we return b - a instead of a - b.
280  * Another thing is that both power and running costs should be doubled for multiheaded engines.
281  * Since it would be multiplying with 2 in both numerator and denominator, it will even themselves out and we skip checking for multiheaded. */
282  Money va = (e_a->GetRunningCost()) / max(1U, (uint)e_a->GetPower());
283  Money vb = (e_b->GetRunningCost()) / max(1U, (uint)e_b->GetPower());
284  int r = ClampToI32(vb - va);
285 
286  /* Use EngineID to sort instead since we want consistent sorting */
287  if (r == 0) return EngineNumberSorter(a, b);
288  return _engine_sort_direction ? -r : r;
289 }
290 
291 /* Train sorting functions */
292 
299 static int CDECL TrainEngineCapacitySorter(const EngineID *a, const EngineID *b)
300 {
301  const RailVehicleInfo *rvi_a = RailVehInfo(*a);
302  const RailVehicleInfo *rvi_b = RailVehInfo(*b);
303 
304  int va = GetTotalCapacityOfArticulatedParts(*a) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
305  int vb = GetTotalCapacityOfArticulatedParts(*b) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
306  int r = va - vb;
307 
308  /* Use EngineID to sort instead since we want consistent sorting */
309  if (r == 0) return EngineNumberSorter(a, b);
310  return _engine_sort_direction ? -r : r;
311 }
312 
319 static int CDECL TrainEnginesThenWagonsSorter(const EngineID *a, const EngineID *b)
320 {
321  int val_a = (RailVehInfo(*a)->railveh_type == RAILVEH_WAGON ? 1 : 0);
322  int val_b = (RailVehInfo(*b)->railveh_type == RAILVEH_WAGON ? 1 : 0);
323  int r = val_a - val_b;
324 
325  /* Use EngineID to sort instead since we want consistent sorting */
326  if (r == 0) return EngineNumberSorter(a, b);
327  return _engine_sort_direction ? -r : r;
328 }
329 
330 /* Road vehicle sorting functions */
331 
338 static int CDECL RoadVehEngineCapacitySorter(const EngineID *a, const EngineID *b)
339 {
342  int r = va - vb;
343 
344  /* Use EngineID to sort instead since we want consistent sorting */
345  if (r == 0) return EngineNumberSorter(a, b);
346  return _engine_sort_direction ? -r : r;
347 }
348 
349 /* Ship vehicle sorting functions */
350 
357 static int CDECL ShipEngineCapacitySorter(const EngineID *a, const EngineID *b)
358 {
359  const Engine *e_a = Engine::Get(*a);
360  const Engine *e_b = Engine::Get(*b);
361 
362  int va = e_a->GetDisplayDefaultCapacity();
363  int vb = e_b->GetDisplayDefaultCapacity();
364  int r = va - vb;
365 
366  /* Use EngineID to sort instead since we want consistent sorting */
367  if (r == 0) return EngineNumberSorter(a, b);
368  return _engine_sort_direction ? -r : r;
369 }
370 
371 /* Aircraft sorting functions */
372 
379 static int CDECL AircraftEngineCargoSorter(const EngineID *a, const EngineID *b)
380 {
381  const Engine *e_a = Engine::Get(*a);
382  const Engine *e_b = Engine::Get(*b);
383 
384  uint16 mail_a, mail_b;
385  int va = e_a->GetDisplayDefaultCapacity(&mail_a);
386  int vb = e_b->GetDisplayDefaultCapacity(&mail_b);
387  int r = va - vb;
388 
389  if (r == 0) {
390  /* The planes have the same passenger capacity. Check mail capacity instead */
391  r = mail_a - mail_b;
392 
393  if (r == 0) {
394  /* Use EngineID to sort instead since we want consistent sorting */
395  return EngineNumberSorter(a, b);
396  }
397  }
398  return _engine_sort_direction ? -r : r;
399 }
400 
407 static int CDECL AircraftRangeSorter(const EngineID *a, const EngineID *b)
408 {
409  uint16 r_a = Engine::Get(*a)->GetRange();
410  uint16 r_b = Engine::Get(*b)->GetRange();
411 
412  int r = r_a - r_b;
413 
414  /* Use EngineID to sort instead since we want consistent sorting */
415  if (r == 0) return EngineNumberSorter(a, b);
416  return _engine_sort_direction ? -r : r;
417 }
418 
421  /* Trains */
433 }, {
434  /* Road vehicles */
446 }, {
447  /* Ships */
456 }, {
457  /* Aircraft */
467 }};
468 
471  /* Trains */
472  STR_SORT_BY_ENGINE_ID,
473  STR_SORT_BY_COST,
474  STR_SORT_BY_MAX_SPEED,
475  STR_SORT_BY_POWER,
476  STR_SORT_BY_TRACTIVE_EFFORT,
477  STR_SORT_BY_INTRO_DATE,
478  STR_SORT_BY_NAME,
479  STR_SORT_BY_RUNNING_COST,
480  STR_SORT_BY_POWER_VS_RUNNING_COST,
481  STR_SORT_BY_RELIABILITY,
482  STR_SORT_BY_CARGO_CAPACITY,
484 }, {
485  /* Road vehicles */
486  STR_SORT_BY_ENGINE_ID,
487  STR_SORT_BY_COST,
488  STR_SORT_BY_MAX_SPEED,
489  STR_SORT_BY_POWER,
490  STR_SORT_BY_TRACTIVE_EFFORT,
491  STR_SORT_BY_INTRO_DATE,
492  STR_SORT_BY_NAME,
493  STR_SORT_BY_RUNNING_COST,
494  STR_SORT_BY_POWER_VS_RUNNING_COST,
495  STR_SORT_BY_RELIABILITY,
496  STR_SORT_BY_CARGO_CAPACITY,
497  INVALID_STRING_ID
498 }, {
499  /* Ships */
500  STR_SORT_BY_ENGINE_ID,
501  STR_SORT_BY_COST,
502  STR_SORT_BY_MAX_SPEED,
503  STR_SORT_BY_INTRO_DATE,
504  STR_SORT_BY_NAME,
505  STR_SORT_BY_RUNNING_COST,
506  STR_SORT_BY_RELIABILITY,
507  STR_SORT_BY_CARGO_CAPACITY,
508  INVALID_STRING_ID
509 }, {
510  /* Aircraft */
511  STR_SORT_BY_ENGINE_ID,
512  STR_SORT_BY_COST,
513  STR_SORT_BY_MAX_SPEED,
514  STR_SORT_BY_INTRO_DATE,
515  STR_SORT_BY_NAME,
516  STR_SORT_BY_RUNNING_COST,
517  STR_SORT_BY_RELIABILITY,
518  STR_SORT_BY_CARGO_CAPACITY,
519  STR_SORT_BY_RANGE,
520  INVALID_STRING_ID
521 }};
522 
524 static bool CDECL CargoFilter(const EngineID *eid, const CargoID cid)
525 {
526  if (cid == CF_ANY) return true;
527  uint32 refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask;
528  return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid));
529 }
530 
531 static GUIEngineList::FilterFunction * const _filter_funcs[] = {
532  &CargoFilter,
533 };
534 
535 static int DrawCargoCapacityInfo(int left, int right, int y, EngineID engine)
536 {
537  CargoArray cap;
538  uint32 refits;
539  GetArticulatedVehicleCargoesAndRefits(engine, &cap, &refits);
540 
541  for (CargoID c = 0; c < NUM_CARGO; c++) {
542  if (cap[c] == 0) continue;
543 
544  SetDParam(0, c);
545  SetDParam(1, cap[c]);
546  SetDParam(2, HasBit(refits, c) ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
547  DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
548  y += FONT_HEIGHT_NORMAL;
549  }
550 
551  return y;
552 }
553 
554 /* Draw rail wagon specific details */
555 static int DrawRailWagonPurchaseInfo(int left, int right, int y, EngineID engine_number, const RailVehicleInfo *rvi)
556 {
557  const Engine *e = Engine::Get(engine_number);
558 
559  /* Purchase cost */
560  SetDParam(0, e->GetCost());
561  DrawString(left, right, y, STR_PURCHASE_INFO_COST);
562  y += FONT_HEIGHT_NORMAL;
563 
564  /* Wagon weight - (including cargo) */
565  uint weight = e->GetDisplayWeight();
566  SetDParam(0, weight);
567  uint cargo_weight = (e->CanCarryCargo() ? CargoSpec::Get(e->GetDefaultCargoType())->weight * GetTotalCapacityOfArticulatedParts(engine_number) / 16 : 0);
568  SetDParam(1, cargo_weight + weight);
569  DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
570  y += FONT_HEIGHT_NORMAL;
571 
572  /* Wagon speed limit, displayed if above zero */
574  uint max_speed = e->GetDisplayMaxSpeed();
575  if (max_speed > 0) {
576  SetDParam(0, max_speed);
577  DrawString(left, right, y, STR_PURCHASE_INFO_SPEED);
578  y += FONT_HEIGHT_NORMAL;
579  }
580  }
581 
582  /* Running cost */
583  if (rvi->running_cost_class != INVALID_PRICE) {
584  SetDParam(0, e->GetRunningCost());
585  DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
586  y += FONT_HEIGHT_NORMAL;
587  }
588 
589  return y;
590 }
591 
592 /* Draw locomotive specific details */
593 static int DrawRailEnginePurchaseInfo(int left, int right, int y, EngineID engine_number, const RailVehicleInfo *rvi)
594 {
595  const Engine *e = Engine::Get(engine_number);
596 
597  /* Purchase Cost - Engine weight */
598  SetDParam(0, e->GetCost());
599  SetDParam(1, e->GetDisplayWeight());
600  DrawString(left, right, y, STR_PURCHASE_INFO_COST_WEIGHT);
601  y += FONT_HEIGHT_NORMAL;
602 
603  /* Max speed - Engine power */
604  SetDParam(0, e->GetDisplayMaxSpeed());
605  SetDParam(1, e->GetPower());
606  DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_POWER);
607  y += FONT_HEIGHT_NORMAL;
608 
609  /* Max tractive effort - not applicable if old acceleration or maglev */
610  if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(rvi->railtype)->acceleration_type != 2) {
612  DrawString(left, right, y, STR_PURCHASE_INFO_MAX_TE);
613  y += FONT_HEIGHT_NORMAL;
614  }
615 
616  /* Running cost */
617  if (rvi->running_cost_class != INVALID_PRICE) {
618  SetDParam(0, e->GetRunningCost());
619  DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
620  y += FONT_HEIGHT_NORMAL;
621  }
622 
623  /* Powered wagons power - Powered wagons extra weight */
624  if (rvi->pow_wag_power != 0) {
625  SetDParam(0, rvi->pow_wag_power);
626  SetDParam(1, rvi->pow_wag_weight);
627  DrawString(left, right, y, STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT);
628  y += FONT_HEIGHT_NORMAL;
629  }
630 
631  return y;
632 }
633 
634 /* Draw road vehicle specific details */
635 static int DrawRoadVehPurchaseInfo(int left, int right, int y, EngineID engine_number)
636 {
637  const Engine *e = Engine::Get(engine_number);
638 
640  /* Purchase Cost */
641  SetDParam(0, e->GetCost());
642  DrawString(left, right, y, STR_PURCHASE_INFO_COST);
643  y += FONT_HEIGHT_NORMAL;
644 
645  /* Road vehicle weight - (including cargo) */
646  int16 weight = e->GetDisplayWeight();
647  SetDParam(0, weight);
648  uint cargo_weight = (e->CanCarryCargo() ? CargoSpec::Get(e->GetDefaultCargoType())->weight * GetTotalCapacityOfArticulatedParts(engine_number) / 16 : 0);
649  SetDParam(1, cargo_weight + weight);
650  DrawString(left, right, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT);
651  y += FONT_HEIGHT_NORMAL;
652 
653  /* Max speed - Engine power */
654  SetDParam(0, e->GetDisplayMaxSpeed());
655  SetDParam(1, e->GetPower());
656  DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_POWER);
657  y += FONT_HEIGHT_NORMAL;
658 
659  /* Max tractive effort */
661  DrawString(left, right, y, STR_PURCHASE_INFO_MAX_TE);
662  y += FONT_HEIGHT_NORMAL;
663  } else {
664  /* Purchase cost - Max speed */
665  SetDParam(0, e->GetCost());
666  SetDParam(1, e->GetDisplayMaxSpeed());
667  DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED);
668  y += FONT_HEIGHT_NORMAL;
669  }
670 
671  /* Running cost */
672  SetDParam(0, e->GetRunningCost());
673  DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
674  y += FONT_HEIGHT_NORMAL;
675 
676  return y;
677 }
678 
679 /* Draw ship specific details */
680 static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_number, bool refittable)
681 {
682  const Engine *e = Engine::Get(engine_number);
683 
684  /* Purchase cost - Max speed */
685  uint raw_speed = e->GetDisplayMaxSpeed();
686  uint ocean_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, true);
687  uint canal_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, false);
688 
689  SetDParam(0, e->GetCost());
690  if (ocean_speed == canal_speed) {
691  SetDParam(1, ocean_speed);
692  DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED);
693  y += FONT_HEIGHT_NORMAL;
694  } else {
695  DrawString(left, right, y, STR_PURCHASE_INFO_COST);
696  y += FONT_HEIGHT_NORMAL;
697 
698  SetDParam(0, ocean_speed);
699  DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_OCEAN);
700  y += FONT_HEIGHT_NORMAL;
701 
702  SetDParam(0, canal_speed);
703  DrawString(left, right, y, STR_PURCHASE_INFO_SPEED_CANAL);
704  y += FONT_HEIGHT_NORMAL;
705  }
706 
707  /* Cargo type + capacity */
710  SetDParam(2, refittable ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
711  DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
712  y += FONT_HEIGHT_NORMAL;
713 
714  /* Running cost */
715  SetDParam(0, e->GetRunningCost());
716  DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
717  y += FONT_HEIGHT_NORMAL;
718 
719  return y;
720 }
721 
731 static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_number, bool refittable)
732 {
733  const Engine *e = Engine::Get(engine_number);
734  CargoID cargo = e->GetDefaultCargoType();
735 
736  /* Purchase cost - Max speed */
737  SetDParam(0, e->GetCost());
738  SetDParam(1, e->GetDisplayMaxSpeed());
739  DrawString(left, right, y, STR_PURCHASE_INFO_COST_SPEED);
740  y += FONT_HEIGHT_NORMAL;
741 
742  /* Cargo capacity */
743  uint16 mail_capacity;
744  uint capacity = e->GetDisplayDefaultCapacity(&mail_capacity);
745  if (mail_capacity > 0) {
746  SetDParam(0, cargo);
747  SetDParam(1, capacity);
748  SetDParam(2, CT_MAIL);
749  SetDParam(3, mail_capacity);
750  DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY);
751  } else {
752  /* Note, if the default capacity is selected by the refit capacity
753  * callback, then the capacity shown is likely to be incorrect. */
754  SetDParam(0, cargo);
755  SetDParam(1, capacity);
756  SetDParam(2, refittable ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
757  DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
758  }
759  y += FONT_HEIGHT_NORMAL;
760 
761  /* Running cost */
762  SetDParam(0, e->GetRunningCost());
763  DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
764  y += FONT_HEIGHT_NORMAL;
765 
766  /* Aircraft type */
768  DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_TYPE);
769  y += FONT_HEIGHT_NORMAL;
770 
771  /* Aircraft range, if available. */
772  uint16 range = e->GetRange();
773  if (range != 0) {
774  SetDParam(0, range);
775  DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_RANGE);
776  y += FONT_HEIGHT_NORMAL;
777  }
778 
779  return y;
780 }
781 
790 static uint ShowAdditionalText(int left, int right, int y, EngineID engine)
791 {
792  uint16 callback = GetVehicleCallback(CBID_VEHICLE_ADDITIONAL_TEXT, 0, 0, engine, NULL);
793  if (callback == CALLBACK_FAILED || callback == 0x400) return y;
794  const GRFFile *grffile = Engine::Get(engine)->GetGRF();
795  if (callback > 0x400) {
796  ErrorUnknownCallbackResult(grffile->grfid, CBID_VEHICLE_ADDITIONAL_TEXT, callback);
797  return y;
798  }
799 
800  StartTextRefStackUsage(grffile, 6);
801  uint result = DrawStringMultiLine(left, right, y, INT32_MAX, GetGRFStringID(grffile->grfid, 0xD000 + callback), TC_BLACK);
803  return result;
804 }
805 
812 int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number)
813 {
814  const Engine *e = Engine::Get(engine_number);
815  YearMonthDay ymd;
816  ConvertDateToYMD(e->intro_date, &ymd);
817  bool refittable = IsArticulatedVehicleRefittable(engine_number);
818  bool articulated_cargo = false;
819 
820  switch (e->type) {
821  default: NOT_REACHED();
822  case VEH_TRAIN:
823  if (e->u.rail.railveh_type == RAILVEH_WAGON) {
824  y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->u.rail);
825  } else {
826  y = DrawRailEnginePurchaseInfo(left, right, y, engine_number, &e->u.rail);
827  }
828  articulated_cargo = true;
829  break;
830 
831  case VEH_ROAD:
832  y = DrawRoadVehPurchaseInfo(left, right, y, engine_number);
833  articulated_cargo = true;
834  break;
835 
836  case VEH_SHIP:
837  y = DrawShipPurchaseInfo(left, right, y, engine_number, refittable);
838  break;
839 
840  case VEH_AIRCRAFT:
841  y = DrawAircraftPurchaseInfo(left, right, y, engine_number, refittable);
842  break;
843  }
844 
845  if (articulated_cargo) {
846  /* Cargo type + capacity, or N/A */
847  int new_y = DrawCargoCapacityInfo(left, right, y, engine_number);
848 
849  if (new_y == y) {
850  SetDParam(0, CT_INVALID);
851  SetDParam(2, STR_EMPTY);
852  DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
853  y += FONT_HEIGHT_NORMAL;
854  } else {
855  y = new_y;
856  }
857  }
858 
859  /* Draw details that apply to all types except rail wagons. */
860  if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
861  /* Design date - Life length */
862  SetDParam(0, ymd.year);
864  DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE);
865  y += FONT_HEIGHT_NORMAL;
866 
867  /* Reliability */
869  DrawString(left, right, y, STR_PURCHASE_INFO_RELIABILITY);
870  y += FONT_HEIGHT_NORMAL;
871  }
872 
873  if (refittable) y = ShowRefitOptionsList(left, right, y, engine_number);
874 
875  /* Additional text from NewGRF */
876  y = ShowAdditionalText(left, right, y, engine_number);
877 
878  return y;
879 }
880 
894 void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
895 {
896  static const int sprite_y_offsets[] = { -1, -1, -2, -2 };
897 
898  /* Obligatory sanity checks! */
899  assert(max <= eng_list->Length());
900 
901  bool rtl = _current_text_dir == TD_RTL;
902  int step_size = GetEngineListHeight(type);
903  int sprite_left = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left;
904  int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
905  int sprite_width = sprite_left + sprite_right;
906 
907  int sprite_x = rtl ? r - sprite_right - 1 : l + sprite_left + 1;
908  int sprite_y_offset = sprite_y_offsets[type] + step_size / 2;
909 
910  Dimension replace_icon = {0, 0};
911  int count_width = 0;
912  if (show_count) {
913  replace_icon = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
915  count_width = GetStringBoundingBox(STR_TINY_BLACK_COMA).width;
916  }
917 
918  int text_left = l + (rtl ? WD_FRAMERECT_LEFT + replace_icon.width + 8 + count_width : sprite_width + WD_FRAMETEXT_LEFT);
919  int text_right = r - (rtl ? sprite_width + WD_FRAMETEXT_RIGHT : WD_FRAMERECT_RIGHT + replace_icon.width + 8 + count_width);
920  int replace_icon_left = rtl ? l + WD_FRAMERECT_LEFT : r - WD_FRAMERECT_RIGHT - replace_icon.width;
921  int count_left = l;
922  int count_right = rtl ? text_left : r - WD_FRAMERECT_RIGHT - replace_icon.width - 8;
923 
924  int normal_text_y_offset = (step_size - FONT_HEIGHT_NORMAL) / 2;
925  int small_text_y_offset = step_size - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1;
926  int replace_icon_y_offset = (step_size - replace_icon.height) / 2 - 1;
927 
928  for (; min < max; min++, y += step_size) {
929  const EngineID engine = (*eng_list)[min];
930  /* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */
931  const uint num_engines = GetGroupNumEngines(_local_company, selected_group, engine);
932 
933  const Engine *e = Engine::Get(engine);
934  bool hidden = HasBit(e->company_hidden, _local_company);
935  StringID str = hidden ? STR_HIDDEN_ENGINE_NAME : STR_ENGINE_NAME;
936  TextColour tc = (engine == selected_id) ? TC_WHITE : (TC_NO_SHADE | (hidden ? TC_GREY : TC_BLACK));
937 
938  SetDParam(0, engine);
939  DrawString(text_left, text_right, y + normal_text_y_offset, str, tc);
940  DrawVehicleEngine(l, r, sprite_x, y + sprite_y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_company), EIT_PURCHASE);
941  if (show_count) {
942  SetDParam(0, num_engines);
943  DrawString(count_left, count_right, y + small_text_y_offset, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
944  if (EngineHasReplacementForCompany(Company::Get(_local_company), engine, selected_group)) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, replace_icon_left, y + replace_icon_y_offset);
945  }
946  }
947 }
948 
956 void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button)
957 {
958  uint32 hidden_mask = 0;
959  /* Disable sorting by power or tractive effort when the original acceleration model for road vehicles is being used. */
960  if (vehicle_type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) {
961  SetBit(hidden_mask, 3); // power
962  SetBit(hidden_mask, 4); // tractive effort
963  SetBit(hidden_mask, 8); // power by running costs
964  }
965  /* Disable sorting by tractive effort when the original acceleration model for trains is being used. */
966  if (vehicle_type == VEH_TRAIN && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
967  SetBit(hidden_mask, 4); // tractive effort
968  }
969  ShowDropDownMenu(w, _engine_sort_listing[vehicle_type], selected, button, 0, hidden_mask);
970 }
971 
975  union {
978  } filter;
985  GUIEngineList eng_list;
990  Scrollbar *vscroll;
991 
992  BuildVehicleWindow(WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc)
993  {
994  this->vehicle_type = type;
995  this->window_number = tile == INVALID_TILE ? (int)type : tile;
996 
997  this->sel_engine = INVALID_ENGINE;
998 
999  this->sort_criteria = _engine_sort_last_criteria[type];
1000  this->descending_sort_order = _engine_sort_last_order[type];
1001  this->show_hidden_engines = _engine_sort_show_hidden_engines[type];
1002 
1003  switch (type) {
1004  default: NOT_REACHED();
1005  case VEH_TRAIN:
1006  this->filter.railtype = (tile == INVALID_TILE) ? RAILTYPE_END : GetRailType(tile);
1007  break;
1008  case VEH_ROAD:
1009  this->filter.roadtypes = (tile == INVALID_TILE) ? ROADTYPES_ALL : GetRoadTypes(tile);
1010  case VEH_SHIP:
1011  case VEH_AIRCRAFT:
1012  break;
1013  }
1014 
1015  this->listview_mode = (this->window_number <= VEH_END);
1016 
1017  this->CreateNestedTree();
1018 
1019  this->vscroll = this->GetScrollbar(WID_BV_SCROLLBAR);
1020 
1021  /* If we are just viewing the list of vehicles, we do not need the Build button.
1022  * So we just hide it, and enlarge the Rename button by the now vacant place. */
1023  if (this->listview_mode) this->GetWidget<NWidgetStacked>(WID_BV_BUILD_SEL)->SetDisplayedPlane(SZSP_NONE);
1024 
1025  /* disable renaming engines in network games if you are not the server */
1027 
1028  NWidgetCore *widget = this->GetWidget<NWidgetCore>(WID_BV_LIST);
1029  widget->tool_tip = STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP + type;
1030 
1031  widget = this->GetWidget<NWidgetCore>(WID_BV_SHOW_HIDE);
1032  widget->tool_tip = STR_BUY_VEHICLE_TRAIN_HIDE_SHOW_TOGGLE_TOOLTIP + type;
1033 
1034  widget = this->GetWidget<NWidgetCore>(WID_BV_BUILD);
1035  widget->widget_data = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_BUTTON + type;
1036  widget->tool_tip = STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP + type;
1037 
1038  widget = this->GetWidget<NWidgetCore>(WID_BV_RENAME);
1039  widget->widget_data = STR_BUY_VEHICLE_TRAIN_RENAME_BUTTON + type;
1040  widget->tool_tip = STR_BUY_VEHICLE_TRAIN_RENAME_TOOLTIP + type;
1041 
1042  widget = this->GetWidget<NWidgetCore>(WID_BV_SHOW_HIDDEN_ENGINES);
1043  widget->widget_data = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN + type;
1044  widget->tool_tip = STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + type;
1045  widget->SetLowered(this->show_hidden_engines);
1046 
1047  this->details_height = ((this->vehicle_type == VEH_TRAIN) ? 10 : 9) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1048 
1049  this->FinishInitNested(tile == INVALID_TILE ? (int)type : tile);
1050 
1051  this->owner = (tile != INVALID_TILE) ? GetTileOwner(tile) : _local_company;
1052 
1053  this->eng_list.ForceRebuild();
1054  this->GenerateBuildList(); // generate the list, since we need it in the next line
1055  /* Select the first engine in the list as default when opening the window */
1056  if (this->eng_list.Length() > 0) this->sel_engine = this->eng_list[0];
1057  }
1058 
1061  {
1062  uint filter_items = 0;
1063 
1064  /* Add item for disabling filtering. */
1065  this->cargo_filter[filter_items] = CF_ANY;
1066  this->cargo_filter_texts[filter_items] = STR_PURCHASE_INFO_ALL_TYPES;
1067  filter_items++;
1068 
1069  /* Add item for vehicles not carrying anything, e.g. train engines.
1070  * This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */
1071  if (this->vehicle_type == VEH_TRAIN) {
1072  this->cargo_filter[filter_items] = CF_NONE;
1073  this->cargo_filter_texts[filter_items] = STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE;
1074  filter_items++;
1075  }
1076 
1077  /* Collect available cargo types for filtering. */
1078  const CargoSpec *cs;
1080  this->cargo_filter[filter_items] = cs->Index();
1081  this->cargo_filter_texts[filter_items] = cs->name;
1082  filter_items++;
1083  }
1084 
1085  /* Terminate the filter list. */
1086  this->cargo_filter_texts[filter_items] = INVALID_STRING_ID;
1087 
1088  /* If not found, the cargo criteria will be set to all cargoes. */
1089  this->cargo_filter_criteria = 0;
1090 
1091  /* Find the last cargo filter criteria. */
1092  for (uint i = 0; i < filter_items; i++) {
1093  if (this->cargo_filter[i] == _engine_sort_last_cargo_criteria[this->vehicle_type]) {
1094  this->cargo_filter_criteria = i;
1095  break;
1096  }
1097  }
1098 
1099  this->eng_list.SetFilterFuncs(_filter_funcs);
1100  this->eng_list.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
1101  }
1102 
1103  void OnInit()
1104  {
1105  this->SetCargoFilterArray();
1106  }
1107 
1110  {
1111  this->eng_list.Filter(this->cargo_filter[this->cargo_filter_criteria]);
1112  if (0 == this->eng_list.Length()) { // no engine passed through the filter, invalidate the previously selected engine
1113  this->sel_engine = INVALID_ENGINE;
1114  } else if (!this->eng_list.Contains(this->sel_engine)) { // previously selected engine didn't pass the filter, select the first engine of the list
1115  this->sel_engine = this->eng_list[0];
1116  }
1117  }
1118 
1121  {
1122  CargoID filter_type = this->cargo_filter[this->cargo_filter_criteria];
1123  return (filter_type == CF_ANY || CargoFilter(&eid, filter_type));
1124  }
1125 
1126  /* Figure out what train EngineIDs to put in the list */
1127  void GenerateBuildTrainList()
1128  {
1129  EngineID sel_id = INVALID_ENGINE;
1130  int num_engines = 0;
1131  int num_wagons = 0;
1132 
1133  this->filter.railtype = (this->listview_mode) ? RAILTYPE_END : GetRailType(this->window_number);
1134 
1135  this->eng_list.Clear();
1136 
1137  /* Make list of all available train engines and wagons.
1138  * Also check to see if the previously selected engine is still available,
1139  * and if not, reset selection to INVALID_ENGINE. This could be the case
1140  * when engines become obsolete and are removed */
1141  const Engine *e;
1142  FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
1143  if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
1144  EngineID eid = e->index;
1145  const RailVehicleInfo *rvi = &e->u.rail;
1146 
1147  if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
1148  if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue;
1149 
1150  /* Filter now! So num_engines and num_wagons is valid */
1151  if (!FilterSingleEngine(eid)) continue;
1152 
1153  *this->eng_list.Append() = eid;
1154 
1155  if (rvi->railveh_type != RAILVEH_WAGON) {
1156  num_engines++;
1157  } else {
1158  num_wagons++;
1159  }
1160 
1161  if (eid == this->sel_engine) sel_id = eid;
1162  }
1163 
1164  this->sel_engine = sel_id;
1165 
1166  /* make engines first, and then wagons, sorted by selected sort_criteria */
1167  _engine_sort_direction = false;
1168  EngList_Sort(&this->eng_list, TrainEnginesThenWagonsSorter);
1169 
1170  /* and then sort engines */
1172  EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], 0, num_engines);
1173 
1174  /* and finally sort wagons */
1175  EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], num_engines, num_wagons);
1176  }
1177 
1178  /* Figure out what road vehicle EngineIDs to put in the list */
1179  void GenerateBuildRoadVehList()
1180  {
1181  EngineID sel_id = INVALID_ENGINE;
1182 
1183  this->eng_list.Clear();
1184 
1185  const Engine *e;
1186  FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
1187  if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
1188  EngineID eid = e->index;
1189  if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue;
1190  if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
1191  *this->eng_list.Append() = eid;
1192 
1193  if (eid == this->sel_engine) sel_id = eid;
1194  }
1195  this->sel_engine = sel_id;
1196  }
1197 
1198  /* Figure out what ship EngineIDs to put in the list */
1199  void GenerateBuildShipList()
1200  {
1201  EngineID sel_id = INVALID_ENGINE;
1202  this->eng_list.Clear();
1203 
1204  const Engine *e;
1205  FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) {
1206  if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
1207  EngineID eid = e->index;
1208  if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue;
1209  *this->eng_list.Append() = eid;
1210 
1211  if (eid == this->sel_engine) sel_id = eid;
1212  }
1213  this->sel_engine = sel_id;
1214  }
1215 
1216  /* Figure out what aircraft EngineIDs to put in the list */
1217  void GenerateBuildAircraftList()
1218  {
1219  EngineID sel_id = INVALID_ENGINE;
1220 
1221  this->eng_list.Clear();
1222 
1223  const Station *st = this->listview_mode ? NULL : Station::GetByTile(this->window_number);
1224 
1225  /* Make list of all available planes.
1226  * Also check to see if the previously selected plane is still available,
1227  * and if not, reset selection to INVALID_ENGINE. This could be the case
1228  * when planes become obsolete and are removed */
1229  const Engine *e;
1230  FOR_ALL_ENGINES_OF_TYPE(e, VEH_AIRCRAFT) {
1231  if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
1232  EngineID eid = e->index;
1233  if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_company)) continue;
1234  /* First VEH_END window_numbers are fake to allow a window open for all different types at once */
1235  if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue;
1236 
1237  *this->eng_list.Append() = eid;
1238  if (eid == this->sel_engine) sel_id = eid;
1239  }
1240 
1241  this->sel_engine = sel_id;
1242  }
1243 
1244  /* Generate the list of vehicles */
1245  void GenerateBuildList()
1246  {
1247  if (!this->eng_list.NeedRebuild()) return;
1248  switch (this->vehicle_type) {
1249  default: NOT_REACHED();
1250  case VEH_TRAIN:
1251  this->GenerateBuildTrainList();
1252  this->eng_list.Compact();
1253  this->eng_list.RebuildDone();
1254  return; // trains should not reach the last sorting
1255  case VEH_ROAD:
1256  this->GenerateBuildRoadVehList();
1257  break;
1258  case VEH_SHIP:
1259  this->GenerateBuildShipList();
1260  break;
1261  case VEH_AIRCRAFT:
1262  this->GenerateBuildAircraftList();
1263  break;
1264  }
1265 
1266  this->FilterEngineList();
1267 
1269  EngList_Sort(&this->eng_list, _engine_sort_functions[this->vehicle_type][this->sort_criteria]);
1270 
1271  this->eng_list.Compact();
1272  this->eng_list.RebuildDone();
1273  }
1274 
1275  void OnClick(Point pt, int widget, int click_count)
1276  {
1277  switch (widget) {
1279  this->descending_sort_order ^= true;
1281  this->eng_list.ForceRebuild();
1282  this->SetDirty();
1283  break;
1284 
1286  this->show_hidden_engines ^= true;
1288  this->eng_list.ForceRebuild();
1289  this->SetWidgetLoweredState(widget, this->show_hidden_engines);
1290  this->SetDirty();
1291  break;
1292 
1293  case WID_BV_LIST: {
1294  uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST);
1295  size_t num_items = this->eng_list.Length();
1296  this->sel_engine = (i < num_items) ? this->eng_list[i] : INVALID_ENGINE;
1297  this->SetDirty();
1298  if (_ctrl_pressed) {
1299  this->OnClick(pt, WID_BV_SHOW_HIDE, 1);
1300  } else if (click_count > 1 && !this->listview_mode) {
1301  this->OnClick(pt, WID_BV_BUILD, 1);
1302  }
1303  break;
1304  }
1305 
1306  case WID_BV_SORT_DROPDOWN: // Select sorting criteria dropdown menu
1307  DisplayVehicleSortDropDown(this, this->vehicle_type, this->sort_criteria, WID_BV_SORT_DROPDOWN);
1308  break;
1309 
1310  case WID_BV_CARGO_FILTER_DROPDOWN: // Select cargo filtering criteria dropdown menu
1311  ShowDropDownMenu(this, this->cargo_filter_texts, this->cargo_filter_criteria, WID_BV_CARGO_FILTER_DROPDOWN, 0, 0);
1312  break;
1313 
1314  case WID_BV_SHOW_HIDE: {
1315  const Engine *e = (this->sel_engine == INVALID_ENGINE) ? NULL : Engine::Get(this->sel_engine);
1316  if (e != NULL) {
1317  DoCommandP(0, 0, this->sel_engine | (e->IsHidden(_current_company) ? 0 : (1u << 31)), CMD_SET_VEHICLE_VISIBILITY);
1318  }
1319  break;
1320  }
1321 
1322  case WID_BV_BUILD: {
1323  EngineID sel_eng = this->sel_engine;
1324  if (sel_eng != INVALID_ENGINE) {
1325  CommandCallback *callback = (this->vehicle_type == VEH_TRAIN && RailVehInfo(sel_eng)->railveh_type == RAILVEH_WAGON) ? CcBuildWagon : CcBuildPrimaryVehicle;
1326  DoCommandP(this->window_number, sel_eng, 0, GetCmdBuildVeh(this->vehicle_type), callback);
1327  }
1328  break;
1329  }
1330 
1331  case WID_BV_RENAME: {
1332  EngineID sel_eng = this->sel_engine;
1333  if (sel_eng != INVALID_ENGINE) {
1334  this->rename_engine = sel_eng;
1335  SetDParam(0, sel_eng);
1336  ShowQueryString(STR_ENGINE_NAME, STR_QUERY_RENAME_TRAIN_TYPE_CAPTION + this->vehicle_type, MAX_LENGTH_ENGINE_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
1337  }
1338  break;
1339  }
1340  }
1341  }
1342 
1348  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1349  {
1350  if (!gui_scope) return;
1351  /* When switching to original acceleration model for road vehicles, clear the selected sort criteria if it is not available now. */
1352  if (this->vehicle_type == VEH_ROAD &&
1354  this->sort_criteria > 7) {
1355  this->sort_criteria = 0;
1357  }
1358  this->eng_list.ForceRebuild();
1359  }
1360 
1361  virtual void SetStringParameters(int widget) const
1362  {
1363  switch (widget) {
1364  case WID_BV_CAPTION:
1365  if (this->vehicle_type == VEH_TRAIN && !this->listview_mode) {
1366  const RailtypeInfo *rti = GetRailTypeInfo(this->filter.railtype);
1367  SetDParam(0, rti->strings.build_caption);
1368  } else {
1369  SetDParam(0, (this->listview_mode ? STR_VEHICLE_LIST_AVAILABLE_TRAINS : STR_BUY_VEHICLE_TRAIN_ALL_CAPTION) + this->vehicle_type);
1370  }
1371  break;
1372 
1373  case WID_BV_SORT_DROPDOWN:
1374  SetDParam(0, _engine_sort_listing[this->vehicle_type][this->sort_criteria]);
1375  break;
1376 
1378  SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]);
1379  break;
1380 
1381  case WID_BV_SHOW_HIDE: {
1382  const Engine *e = (this->sel_engine == INVALID_ENGINE) ? NULL : Engine::Get(this->sel_engine);
1383  if (e != NULL && e->IsHidden(_local_company)) {
1384  SetDParam(0, STR_BUY_VEHICLE_TRAIN_SHOW_TOGGLE_BUTTON + this->vehicle_type);
1385  } else {
1386  SetDParam(0, STR_BUY_VEHICLE_TRAIN_HIDE_TOGGLE_BUTTON + this->vehicle_type);
1387  }
1388  break;
1389  }
1390  }
1391  }
1392 
1393  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1394  {
1395  switch (widget) {
1396  case WID_BV_LIST:
1397  resize->height = GetEngineListHeight(this->vehicle_type);
1398  size->height = 3 * resize->height;
1399  size->width = max(size->width, GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_left + GetVehicleImageCellSize(this->vehicle_type, EIT_PURCHASE).extend_right + 165);
1400  break;
1401 
1402  case WID_BV_PANEL:
1403  size->height = this->details_height;
1404  break;
1405 
1407  Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->widget_data);
1408  d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
1409  d.height += padding.height;
1410  *size = maxdim(*size, d);
1411  break;
1412  }
1413 
1414  case WID_BV_SHOW_HIDE:
1415  *size = GetStringBoundingBox(STR_BUY_VEHICLE_TRAIN_HIDE_TOGGLE_BUTTON + this->vehicle_type);
1416  *size = maxdim(*size, GetStringBoundingBox(STR_BUY_VEHICLE_TRAIN_SHOW_TOGGLE_BUTTON + this->vehicle_type));
1417  size->width += padding.width;
1418  size->height += padding.height;
1419  break;
1420  }
1421  }
1422 
1423  virtual void DrawWidget(const Rect &r, int widget) const
1424  {
1425  switch (widget) {
1426  case WID_BV_LIST:
1427  DrawEngineList(this->vehicle_type, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, &this->eng_list, this->vscroll->GetPosition(), min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->eng_list.Length()), this->sel_engine, false, DEFAULT_GROUP);
1428  break;
1429 
1431  this->DrawSortButtonState(WID_BV_SORT_ASCENDING_DESCENDING, this->descending_sort_order ? SBS_DOWN : SBS_UP);
1432  break;
1433  }
1434  }
1435 
1436  virtual void OnPaint()
1437  {
1438  this->GenerateBuildList();
1439  this->vscroll->SetCount(this->eng_list.Length());
1440 
1441  this->SetWidgetDisabledState(WID_BV_SHOW_HIDE, this->sel_engine == INVALID_ENGINE);
1442 
1443  this->DrawWidgets();
1444 
1445  if (!this->IsShaded()) {
1446  int needed_height = this->details_height;
1447  /* Draw details panels. */
1448  if (this->sel_engine != INVALID_ENGINE) {
1449  NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_BV_PANEL);
1451  nwi->pos_y + WD_FRAMERECT_TOP, this->sel_engine);
1452  needed_height = max(needed_height, text_end - (int)nwi->pos_y + WD_FRAMERECT_BOTTOM);
1453  }
1454  if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
1455  int resize = needed_height - this->details_height;
1456  this->details_height = needed_height;
1457  this->ReInit(0, resize);
1458  return;
1459  }
1460  }
1461  }
1462 
1463  virtual void OnQueryTextFinished(char *str)
1464  {
1465  if (str == NULL) return;
1466 
1467  DoCommandP(0, this->rename_engine, 0, CMD_RENAME_ENGINE | CMD_MSG(STR_ERROR_CAN_T_RENAME_TRAIN_TYPE + this->vehicle_type), NULL, str);
1468  }
1469 
1470  virtual void OnDropdownSelect(int widget, int index)
1471  {
1472  switch (widget) {
1473  case WID_BV_SORT_DROPDOWN:
1474  if (this->sort_criteria != index) {
1475  this->sort_criteria = index;
1477  this->eng_list.ForceRebuild();
1478  }
1479  break;
1480 
1481  case WID_BV_CARGO_FILTER_DROPDOWN: // Select a cargo filter criteria
1482  if (this->cargo_filter_criteria != index) {
1483  this->cargo_filter_criteria = index;
1484  _engine_sort_last_cargo_criteria[this->vehicle_type] = this->cargo_filter[this->cargo_filter_criteria];
1485  /* deactivate filter if criteria is 'Show All', activate it otherwise */
1486  this->eng_list.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
1487  this->eng_list.ForceRebuild();
1488  }
1489  break;
1490  }
1491  this->SetDirty();
1492  }
1493 
1494  virtual void OnResize()
1495  {
1496  this->vscroll->SetCapacityFromWidget(this, WID_BV_LIST);
1497  }
1498 };
1499 
1500 static WindowDesc _build_vehicle_desc(
1501  WDP_AUTO, "build_vehicle", 240, 268,
1504  _nested_build_vehicle_widgets, lengthof(_nested_build_vehicle_widgets)
1505 );
1506 
1507 void ShowBuildVehicleWindow(TileIndex tile, VehicleType type)
1508 {
1509  /* We want to be able to open both Available Train as Available Ships,
1510  * so if tile == INVALID_TILE (Available XXX Window), use 'type' as unique number.
1511  * As it always is a low value, it won't collide with any real tile
1512  * number. */
1513  uint num = (tile == INVALID_TILE) ? (int)type : tile;
1514 
1515  assert(IsCompanyBuildableVehicleType(type));
1516 
1518 
1519  new BuildVehicleWindow(&_build_vehicle_desc, tile, type);
1520 }
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
Check if an engine is buildable.
Definition: engine.cpp:1066
void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
Draw an engine.
Definition: engine_gui.cpp:296
Used for iterations.
Definition: rail_type.h:35
Functions related to OTTD&#39;s strings.
VehicleSettings vehicle
options for vehicles
static bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition: rail.h:324
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:27
void RebuildDone()
Notify the sortlist that the rebuild is done.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
bool _networking
are we in networking mode?
Definition: network.cpp:56
Functions for NewGRF engines.
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:296
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
ResizeInfo resize
Resize information.
Definition: window_gui.h:317
void DrawEngineList(VehicleType type, int l, int r, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
Engine drawing loop.
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
virtual void OnPaint()
The window must be repainted.
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:387
static int CDECL EnginePowerSorter(const EngineID *a, const EngineID *b)
Determines order of engines by power.
CargoID cargo_filter[NUM_CARGO+2]
Available cargo filters; CargoID or CF_ANY or CF_NONE.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:448
uint GetDisplayDefaultCapacity(uint16 *mail_capacity=NULL) const
Determines the default cargo capacity of an engine for display purposes.
Definition: engine_base.h:101
Road + trams.
Definition: road_type.h:40
GUI for building vehicles.
High level window description.
Definition: window_gui.h:168
void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
static int CDECL TrainEngineCapacitySorter(const EngineID *a, const EngineID *b)
Determines order of train engines by capacity.
StringID tool_tip
Tooltip of the widget.
Definition: widget_type.h:306
StringID GetAircraftTypeText() const
Get the name of the aircraft type for display purposes.
Definition: engine.cpp:470
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
Get the number of engines with EngineID id_e in the group with GroupID id_g and its sub-groups...
Definition: group_cmd.cpp:693
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number)
Draw the purchase info details of a vehicle at a given location.
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
union BuildVehicleWindow::@0 filter
Filter to apply.
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition: engine.cpp:173
bool IsHidden(CompanyByte c) const
Check whether the engine is hidden in the GUI for the given company.
Definition: engine_base.h:121
Functions related to dates.
Scrollbar data structure.
Definition: widget_type.h:589
Basic road type.
Definition: road_type.h:24
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
uint16 GetRange() const
Get the range of an aircraft type.
Definition: engine.cpp:456
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, int button)
Display the dropdown for the vehicle sort criteria.
Horizontal container.
Definition: widget_type.h:75
byte sort_criteria
Current sort criterium.
byte _engine_sort_last_criteria[]
Last set sort criteria, for each vehicle type.
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:1065
Base class for groups and group functions.
Date intro_date
Date of introduction of the engine.
Definition: engine_base.h:25
Rename button.
uint ApplyWaterClassSpeedFrac(uint raw_speed, bool is_ocean) const
Apply ocean/canal speed fraction to a velocity.
Definition: engine_type.h:79
Specification of a cargo type.
Definition: cargotype.h:56
static int CDECL EnginePowerVsRunningCostSorter(const EngineID *a, const EngineID *b)
Determines order of engines by running costs.
uint extend_right
Extend of the cell to the right.
Definition: vehicle_gui.h:74
Functions related to vehicles.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
Build panel.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
static bool CDECL CargoFilter(const EngineID *eid, const CargoID cid)
Cargo filter functions.
CompanyMask company_hidden
Bit for each company whether the engine is normally hidden in the build gui for that company...
Definition: engine_base.h:40
EngineID sel_engine
Currently selected engine, or INVALID_ENGINE.
Build vehicle; Window numbers:
Definition: window_type.h:378
void Clear()
Remove all items from the list.
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type)
Get the GUI cell size for a vehicle image.
Definition: depot_gui.cpp:159
void Compact()
Compact the list down to the smallest block size boundary.
uint height
Vehicle cell height.
Definition: vehicle_gui.h:72
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Close box (at top-left of a window)
Definition: widget_type.h:69
static int CDECL EngineIntroDateSorter(const EngineID *a, const EngineID *b)
Determines order of engines by introduction date.
static int CDECL EngineRunningCostSorter(const EngineID *a, const EngineID *b)
Determines order of engines by running costs.
Offset at top of a matrix cell.
Definition: window_gui.h:80
void SetCargoFilterArray()
Populate the filter list and set the cargo filter criteria.
uint GetEngineListHeight(VehicleType type)
Get the height of a single &#39;entry&#39; in the engine lists.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
void ReInit(int rx=0, int ry=0)
Re-initialize a window, and optionally change its size.
Definition: window.cpp:970
StringID GetGRFStringID(uint32 grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Stuff related to the text buffer GUI.
void SetFilterFuncs(FilterFunction *const *n_funcs)
Hand the array of filter function pointers to the sort list.
EngList_SortTypeFunction *const _engine_sort_functions[][11]
Sort functions for the vehicle sort criteria, for each vehicle type.
Vehicle drawn in purchase list, autoreplace gui, ...
Definition: vehicle_type.h:92
byte pow_wag_weight
Extra weight applied to consist if wagon should be powered.
Definition: engine_type.h:57
static int CDECL EngineCostSorter(const EngineID *a, const EngineID *b)
Determines order of engines by purchase cost.
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
struct RailtypeInfo::@39 strings
Strings associated with the rail type.
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1804
Functions related to the vehicle&#39;s GUIs.
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:81
StringID name
Name of this type of cargo.
Definition: cargotype.h:71
bool NeedRebuild() const
Check if a rebuild is needed.
StringID build_caption
Caption of the build vehicle GUI for this rail type.
Definition: rail.h:168
This struct contains all the info that is needed to draw and construct tracks.
Definition: rail.h:116
bool _engine_sort_last_order[]
Last set direction of the sort order, for each vehicle type.
T * Append(uint to_add=1)
Append an item and return it.
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
Force the alignment, i.e. don&#39;t swap for RTL languages.
Definition: gfx_func.h:110
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
virtual void OnResize()
Called after the window got resized.
static int CDECL AircraftRangeSorter(const EngineID *a, const EngineID *b)
Determines order of aircraft by range.
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
void ForceRebuild()
Force that a rebuild is needed.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Data structure for an opened window.
Definition: window_gui.h:271
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1820
Scrollbar of list.
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
hide or unhide a vehicle in the build vehicle and autoreplace GUIs
Definition: command_type.h:219
Header of Action 04 "universal holder" structure and functions.
bool show_hidden_engines
State of the &#39;show hidden engines&#39; button.
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
Aircraft vehicle type.
Definition: vehicle_type.h:27
Functions related to low-level strings.
This callback is called from vehicle purchase lists.
Money GetCost() const
Return how much a new engine costs.
Definition: engine.cpp:321
void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
Callback for building wagons.
Definition: train_gui.cpp:31
Offset at bottom of a matrix cell.
Definition: window_gui.h:81
#define FONT_HEIGHT_SMALL
Height of characters in the small (FS_SMALL) font.
Definition: gfx_func.h:177
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint Length() const
Get the number of items in the list.
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
static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_number, bool refittable)
Draw aircraft specific details in the buy window.
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:210
void SetLowered(bool lowered)
Lower or raise the widget.
Definition: widget_type.h:337
bool Contains(const T &item) const
Tests whether a item is present in the vector.
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new).
Definition: cargo_type.h:69
Functions related to engines.
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
Sort descending.
Definition: window_gui.h:227
uint16 pow_wag_power
Extra power applied to consist if wagon should be powered.
Definition: engine_type.h:56
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:171
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
simple wagon, not motorized
Definition: engine_type.h:30
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
bool descending_sort_order
Sort direction,.
Definition of base types and functions in a cross-platform compatible way.
PaletteID GetEnginePalette(EngineID engine_type, CompanyID company)
Get the colour map for an engine.
Definition: vehicle.cpp:1944
Data structure to convert between Date and triplet (year, month, and day).
Definition: date_type.h:103
the length of the string is counted in characters
Definition: textbuf_gui.h:24
static CargoID _engine_sort_last_cargo_criteria[]
Last set filter criteria, for each vehicle type.
void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items)
Sort selected range of items (on indices @ <begin, begin+num_items-1>)
Definition: engine_gui.cpp:342
static int CDECL AircraftEngineCargoSorter(const EngineID *a, const EngineID *b)
Determines order of aircraft by cargo.
A number of safeguards to prevent using unsafe methods.
Trams.
Definition: road_type.h:25
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition: gfx_type.h:247
uint8 acceleration_type
Acceleration type of this rail type.
Definition: rail.h:215
bool listview_mode
If set, only display the available vehicles and do not show a &#39;build&#39; button.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
Geometry functions.
Simple depressed panel.
Definition: widget_type.h:50
Toggle whether to display the hidden vehicles.
uint16 GroupID
Type for all group identifiers.
Definition: group_type.h:15
Engine GUI functions, used by build_vehicle_gui and autoreplace_gui
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition: engine_base.h:42
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:638
VehicleType vehicle_type
Type of vehicles shown in the window.
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:307
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Button to hide or show the selected engine.
void SetDParamMaxDigits(uint n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:121
static int CDECL ShipEngineCapacitySorter(const EngineID *a, const EngineID *b)
Determines order of ships by capacity.
const StringID _engine_sort_listing[][12]
Dropdown menu strings for the vehicle sort criteria.
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
Year year
Year (0...)
Definition: date_type.h:104
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:2752
Baseclass for nested widgets.
Definition: widget_type.h:126
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
Basic functions/variables used all over the place.
Right offset of the text of the frame.
Definition: window_gui.h:73
bool DoCommandP(const CommandContainer *container, bool my_cmd)
Shortcut for the long DoCommandP when having a container with the data.
Definition: command.cpp:527
void OnInit()
Notification that the nested widget tree gets initialized.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
Road vehicle type.
Definition: vehicle_type.h:25
Invalid cargo type.
Definition: cargo_type.h:70
Grid of rows and columns.
Definition: widget_type.h:59
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:390
#define FOR_ALL_SORTED_STANDARD_CARGOSPECS(var)
Loop header for iterating over &#39;real&#39; cargoes, sorted by name.
Definition: cargotype.h:173
Left offset of the text of the frame.
Definition: window_gui.h:72
void FilterEngineList()
Filter the engine list against the currently selected cargo filter.
void StartTextRefStackUsage(const GRFFile *grffile, byte numEntries, const uint32 *values)
Start using the TTDP compatible string code parsing.
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition: widget.cpp:658
StringID cargo_filter_texts[NUM_CARGO+3]
Texts for filter_cargo, terminated by INVALID_STRING_ID.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
int details_height
Minimal needed height of the details panels (found so far).
RoadTypes roadtypes
Road type to show, or ROADTYPES_ALL.
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition: road_type.h:36
Information about a rail vehicle.
Definition: engine_type.h:43
static int CDECL EngineSpeedSorter(const EngineID *a, const EngineID *b)
Determines order of engines by speed.
uint GetDisplayMaxSpeed() const
Returns max speed of the engine for display purposes.
Definition: engine.cpp:361
Ship vehicle type.
Definition: vehicle_type.h:26
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:959
static const CargoID CF_ANY
Special cargo filter criteria.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:699
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
bool _engine_sort_direction
false = descending, true = ascending.
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:1137
uint GetPower() const
Returns the power of the engine for display and sorting purposes.
Definition: engine.cpp:393
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:174
static int CDECL EngineNumberSorter(const EngineID *a, const EngineID *b)
Determines order of engines by engineID.
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:19
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 GetTotalCapacityOfArticulatedParts(EngineID engine)
Get the capacity of an engine with articulated parts.
Definition: engine_gui.cpp:163
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:74
Base class for engines.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
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:569
EngineID rename_engine
Engine being renamed.
bool FilterSingleEngine(EngineID eid)
Filter a single engine.
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:22
void SetFilterState(bool state)
Enable or disable the filter.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:118
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
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:1569
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
bool CDECL FilterFunction(const EngineID *, CargoID)
Signature of filter function.
Definition: sortlist_type.h:53
Sort ascending.
Definition: window_gui.h:226
bool wagon_speed_limits
enable wagon speed limits
Vertical container.
Definition: widget_type.h:77
indicates a combination of two locomotives
Definition: engine_type.h:29
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
This is the Callback method after the construction attempt of a primary vehicle.
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
Do not add shading to this text colour.
Definition: gfx_type.h:271
static int CDECL EngineNameSorter(const EngineID *a, const EngineID *b)
Determines order of engines by name.
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
byte cargo_filter_criteria
Selected cargo filter.
static uint ShowAdditionalText(int left, int right, int y, EngineID engine)
Display additional text from NewGRF in the purchase information window.
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
static uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:300
void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
Sort all items using quick sort and given &#39;CompareItems&#39; function.
Definition: engine_gui.cpp:326
Functions related to commands.
Types/functions related to cargoes.
bool _network_server
network-server is active
Definition: network.cpp:57
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:768
CargoID Index() const
Determines index of this cargospec.
Definition: cargotype.h:89
rename a engine (in the engine list)
Definition: command_type.h:244
uint8 train_acceleration_model
realistic acceleration for trains
Drop down list.
Definition: widget_type.h:70
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:622
Index of the small font in the font tables.
Definition: gfx_type.h:205
Button panel.
static int CDECL RoadVehEngineCapacitySorter(const EngineID *a, const EngineID *b)
Determines order of road vehicles by capacity.
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, uint32 *refits)
Get the default cargoes and refits of an articulated vehicle.
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:319
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
void CommandCallback(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
Define a callback function for the client, after the command is finished.
Definition: command_type.h:467
static RoadTypes GetRoadTypes(TileIndex t)
Get the present road types of a tile.
Definition: road_map.h:166
uint32 _standard_cargo_mask
Bitmask of real cargo types available.
Definition: cargotype.cpp:36
uint8 roadveh_acceleration_model
realistic acceleration for road vehicles
static bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
Money GetRunningCost() const
Return how much the running costs of this engine are.
Definition: engine.cpp:284
static int CDECL EngineReliabilitySorter(const EngineID *a, const EngineID *b)
Determines order of engines by reliability.
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:66
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.
static int CDECL EngineTractiveEffortSorter(const EngineID *a, const EngineID *b)
Determines order of engines by tractive effort.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
#define CMD_MSG(x)
Used to combine a StringID with the command.
Definition: command_type.h:366
RailTypeByte railtype
Rail type to show, or RAILTYPE_END.
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
int CDECL EngList_SortTypeFunction(const EngineID *, const EngineID *)
argument type for EngList_Sort.
Definition: engine_gui.h:22
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
bool IsShaded() const
Is window shaded currently?
Definition: window_gui.h:519
Text is written right-to-left by default.
Definition: strings_type.h:26
Right align the text (must be a single bit).
Definition: gfx_func.h:100
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:307
uint extend_left
Extend of the cell to the left.
Definition: vehicle_gui.h:73
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:154
static const uint MAX_LENGTH_ENGINE_NAME_CHARS
The maximum length of an engine name in characters including &#39;\0&#39;.
Definition: engine_type.h:172
bool _engine_sort_show_hidden_engines[]
Last set &#39;show hidden engines&#39; setting for each vehicle type.
Window functions not directly related to making/drawing windows.
List of vehicles.
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
Display list of cargo types of the engine, for the purchase information window.
Caption of window.
Find a place automatically.
Definition: window_gui.h:156
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
uint GetDisplayWeight() const
Returns the weight of the engine for display purposes.
Definition: engine.cpp:411
Criteria of sorting dropdown.
Base classes/functions for stations.
uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
static int CDECL TrainEnginesThenWagonsSorter(const EngineID *a, const EngineID *b)
Determines order of train engines by engine / wagon.
Types related to the build_vehicle widgets.
Functions related to autoreplacing.
void ConvertDateToYMD(Date date, YearMonthDay *ymd)
Converts a Date to a Year, Month & Day.
Definition: date.cpp:94
uint GetDisplayMaxTractiveEffort() const
Returns the tractive effort of the engine for display purposes.
Definition: engine.cpp:429
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
static bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:91
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
Station data structure.
Definition: station_base.h:446
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:64
Date GetLifeLengthInDays() const
Returns the vehicle&#39;s (not model&#39;s!) life length in days.
Definition: engine.cpp:446
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:833
static RailType GetRailType(TileIndex t)
Gets the rail type of the given tile.
Definition: rail_map.h:116
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:32
void StopTextRefStackUsage()
Stop using the TTDP compatible string code parsing.
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
(Toggle) Button with text
Definition: widget_type.h:55
bool IsArticulatedVehicleRefittable(EngineID engine)
Checks whether any of the articulated parts is refittable.
Dynamic data of a loaded NewGRF.
Definition: newgrf.h:104
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
Train vehicle type.
Definition: vehicle_type.h:24
static const CargoID CF_NONE
Show only vehicles which do not carry cargo (e.g. train engines)
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