OpenTTD Source 20250612-master-gb012d9e3dc
engine_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "window_gui.h"
12#include "engine_base.h"
13#include "command_func.h"
14#include "strings_func.h"
15#include "engine_gui.h"
17#include "vehicle_func.h"
18#include "company_func.h"
19#include "rail.h"
20#include "road.h"
21#include "settings_type.h"
22#include "train.h"
23#include "roadveh.h"
24#include "ship.h"
25#include "aircraft.h"
26#include "engine_cmd.h"
27#include "zoom_func.h"
28
30
31#include "table/strings.h"
32
33#include "safeguards.h"
34
41{
42 const Engine *e = Engine::Get(engine);
43 switch (e->type) {
44 default: NOT_REACHED();
45 case VEH_ROAD:
46 return GetRoadTypeInfo(e->u.road.roadtype)->strings.new_engine;
47 case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
48 case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
49 case VEH_TRAIN:
50 return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
51 }
52}
53
54static constexpr NWidgetPart _nested_engine_preview_widgets[] = {
56 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
57 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
59 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
61 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_EP_QUESTION), SetMinimalSize(300, 0), SetFill(1, 0),
63 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_NO), SetStringTip(STR_QUIT_NO), SetFill(1, 0),
64 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_YES), SetStringTip(STR_QUIT_YES), SetFill(1, 0),
68};
69
71 int vehicle_space = 0; // The space to show the vehicle image
72
74 {
75 this->InitNested(window_number);
76
77 /* There is no way to recover the window; so disallow closure via DEL; unless SHIFT+DEL */
79 }
80
81 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
82 {
83 if (widget != WID_EP_QUESTION) return;
84
85 /* Get size of engine sprite, on loan from depot_gui.cpp */
86 EngineID engine = static_cast<EngineID>(this->window_number);
87 EngineImageType image_type = EIT_PURCHASE;
88 uint x, y;
89 int x_offs, y_offs;
90
91 const Engine *e = Engine::Get(engine);
92 switch (e->type) {
93 default: NOT_REACHED();
94 case VEH_TRAIN: GetTrainSpriteSize( engine, x, y, x_offs, y_offs, image_type); break;
95 case VEH_ROAD: GetRoadVehSpriteSize( engine, x, y, x_offs, y_offs, image_type); break;
96 case VEH_SHIP: GetShipSpriteSize( engine, x, y, x_offs, y_offs, image_type); break;
97 case VEH_AIRCRAFT: GetAircraftSpriteSize(engine, x, y, x_offs, y_offs, image_type); break;
98 }
99 this->vehicle_space = std::max<int>(ScaleSpriteTrad(40), y - y_offs);
100
101 size.width = std::max(size.width, x + std::abs(x_offs));
102 size.height = GetStringHeight(GetString(STR_ENGINE_PREVIEW_MESSAGE, GetEngineCategoryName(engine)), size.width) + WidgetDimensions::scaled.vsep_wide + GetCharacterHeight(FS_NORMAL) + this->vehicle_space;
103 size.height += GetStringHeight(GetEngineInfoString(engine), size.width);
104 }
105
106 void DrawWidget(const Rect &r, WidgetID widget) const override
107 {
108 if (widget != WID_EP_QUESTION) return;
109
110 EngineID engine = static_cast<EngineID>(this->window_number);
111 int y = DrawStringMultiLine(r, GetString(STR_ENGINE_PREVIEW_MESSAGE, GetEngineCategoryName(engine)), TC_FROMSTRING, SA_HOR_CENTER | SA_TOP) + WidgetDimensions::scaled.vsep_wide;
112
113 DrawString(r.left, r.right, y, GetString(STR_ENGINE_NAME, PackEngineNameDParam(engine, EngineNameContext::PreviewNews)), TC_BLACK, SA_HOR_CENTER);
115
116 DrawVehicleEngine(r.left, r.right, this->width >> 1, y + this->vehicle_space / 2, engine, GetEnginePalette(engine, _local_company), EIT_PREVIEW);
117
118 y += this->vehicle_space;
119 DrawStringMultiLine(r.left, r.right, y, r.bottom, GetEngineInfoString(engine), TC_BLACK, SA_CENTER);
120 }
121
122 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
123 {
124 switch (widget) {
125 case WID_EP_YES:
126 Command<CMD_WANT_ENGINE_PREVIEW>::Post(static_cast<EngineID>(this->window_number));
127 [[fallthrough]];
128 case WID_EP_NO:
129 if (!_shift_pressed) this->Close();
130 break;
131 }
132 }
133
134 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
135 {
136 if (!gui_scope) return;
137
138 EngineID engine = static_cast<EngineID>(this->window_number);
139 if (Engine::Get(engine)->preview_company != _local_company) this->Close();
140 }
141};
142
143static WindowDesc _engine_preview_desc(
144 WDP_CENTER, {}, 0, 0,
147 _nested_engine_preview_widgets
148);
149
150
151void ShowEnginePreviewWindow(EngineID engine)
152{
153 AllocateWindowDescFront<EnginePreviewWindow>(_engine_preview_desc, engine);
154}
155
162{
164 return cap.GetSum<uint>();
165}
166
172static std::string GetPreviewRunningCostString(const Engine &e)
173{
174 return GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_ENGINE_PREVIEW_RUNCOST_PERIOD : STR_ENGINE_PREVIEW_RUNCOST_YEAR, e.GetRunningCost());
175}
176
177static std::string GetTrainEngineInfoString(const Engine &e)
178{
179 std::stringstream res;
180
181 res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight());
182 res << '\n';
183
185 res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER_MAX_TE, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower(), e.GetDisplayMaxTractiveEffort());
186 res << '\n';
187 } else {
188 res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower());
189 res << '\n';
190 }
191
193 res << '\n';
194
195 uint capacity = GetTotalCapacityOfArticulatedParts(e.index);
196 res << GetString(STR_ENGINE_PREVIEW_CAPACITY, capacity == 0 ? INVALID_CARGO : e.GetDefaultCargoType(), capacity);
197
198 return res.str();
199}
200
201static std::string GetAircraftEngineInfoString(const Engine &e)
202{
203 std::stringstream res;
204
205 res << GetString(STR_ENGINE_PREVIEW_COST_MAX_SPEED, e.GetCost(), PackVelocity(e.GetDisplayMaxSpeed(), e.type));
206 res << '\n';
207
208 if (uint16_t range = e.GetRange(); range > 0) {
209 res << GetString(STR_ENGINE_PREVIEW_TYPE_RANGE, e.GetAircraftTypeText(), range);
210 res << '\n';
211 } else {
212 res << GetString(STR_ENGINE_PREVIEW_TYPE, e.GetAircraftTypeText());
213 res << '\n';
214 }
215
217 res << '\n';
218
219 CargoType cargo = e.GetDefaultCargoType();
220 uint16_t mail_capacity;
221 uint capacity = e.GetDisplayDefaultCapacity(&mail_capacity);
222 if (mail_capacity > 0) {
223 res << GetString(STR_ENGINE_PREVIEW_CAPACITY_2, cargo, capacity, GetCargoTypeByLabel(CT_MAIL), mail_capacity);
224 } else {
225 res << GetString(STR_ENGINE_PREVIEW_CAPACITY, cargo, capacity);
226 }
227
228 return res.str();
229}
230
231static std::string GetRoadVehEngineInfoString(const Engine &e)
232{
233 std::stringstream res;
234
236 res << GetString(STR_ENGINE_PREVIEW_COST_MAX_SPEED, e.GetCost(), PackVelocity(e.GetDisplayMaxSpeed(), e.type));
237 res << '\n';
238 } else {
239 res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight());
240 res << '\n';
241 res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER_MAX_TE, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower(), e.GetDisplayMaxTractiveEffort());
242 res << '\n';
243 }
244
246 res << '\n';
247
248 uint capacity = GetTotalCapacityOfArticulatedParts(e.index);
249 res << GetString(STR_ENGINE_PREVIEW_CAPACITY, capacity == 0 ? INVALID_CARGO : e.GetDefaultCargoType(), capacity);
250
251 return res.str();
252}
253
254static std::string GetShipEngineInfoString(const Engine &e)
255{
256 std::stringstream res;
257
258 res << GetString(STR_ENGINE_PREVIEW_COST_MAX_SPEED, e.GetCost(), PackVelocity(e.GetDisplayMaxSpeed(), e.type));
259 res << '\n';
260
262 res << '\n';
263
264 res << GetString(STR_ENGINE_PREVIEW_CAPACITY, e.GetDefaultCargoType(), e.GetDisplayDefaultCapacity());
265
266 return res.str();
267}
268
269
276std::string GetEngineInfoString(EngineID engine)
277{
278 const Engine &e = *Engine::Get(engine);
279
280 switch (e.type) {
281 case VEH_TRAIN:
282 return GetTrainEngineInfoString(e);
283
284 case VEH_ROAD:
285 return GetRoadVehEngineInfoString(e);
286
287 case VEH_SHIP:
288 return GetShipEngineInfoString(e);
289
290 case VEH_AIRCRAFT:
291 return GetAircraftEngineInfoString(e);
292
293 default: NOT_REACHED();
294 }
295}
296
306void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
307{
308 const Engine *e = Engine::Get(engine);
309
310 switch (e->type) {
311 case VEH_TRAIN:
312 DrawTrainEngine(left, right, preferred_x, y, engine, pal, image_type);
313 break;
314
315 case VEH_ROAD:
316 DrawRoadVehEngine(left, right, preferred_x, y, engine, pal, image_type);
317 break;
318
319 case VEH_SHIP:
320 DrawShipEngine(left, right, preferred_x, y, engine, pal, image_type);
321 break;
322
323 case VEH_AIRCRAFT:
324 DrawAircraftEngine(left, right, preferred_x, y, engine, pal, image_type);
325 break;
326
327 default: NOT_REACHED();
328 }
329}
330
337{
338 if (el.size() < 2) return;
339 std::sort(el.begin(), el.end(), compare);
340}
341
349void EngList_SortPartial(GUIEngineList &el, EngList_SortTypeFunction compare, size_t begin, size_t num_items)
350{
351 if (num_items < 2) return;
352 assert(begin < el.size());
353 assert(begin + num_items <= el.size());
354 std::sort(el.begin() + begin, el.begin() + begin + num_items, compare);
355}
356
Base for aircraft.
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of an aircraft sprite heading west (used for lists).
CargoArray GetCapacityOfArticulatedParts(EngineID engine)
Get the capacity of the parts of a given engine.
Functions related to articulated vehicles.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
constexpr Timpl & Set()
Set all bits.
struct RailTypeInfo::@23 strings
Strings associated with the rail type.
StringID new_loco
Name of an engine for this type of rail in the engine preview GUI.
Definition rail.h:172
uint8_t acceleration_type
Acceleration type of this rail type.
Definition rail.h:217
StringID new_engine
Name of an engine for this type of road in the engine preview GUI.
Definition road.h:99
struct RoadTypeInfo::@26 strings
Strings associated with the rail type.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
Functions related to commands.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
Base class for engines.
Command definitions related to engines.
std::string GetEngineInfoString(EngineID engine)
Get a multi-line string with some technical data, describing the engine.
void EngList_Sort(GUIEngineList &el, EngList_SortTypeFunction compare)
Sort all items using quick sort and given 'CompareItems' function.
static std::string GetPreviewRunningCostString(const Engine &e)
Get preview running cost string for an engine.
uint GetTotalCapacityOfArticulatedParts(EngineID engine)
Get the capacity of an engine with articulated parts.
StringID GetEngineCategoryName(EngineID engine)
Return the category of an engine.
void EngList_SortPartial(GUIEngineList &el, EngList_SortTypeFunction compare, size_t begin, size_t num_items)
Sort selected range of items (on indices @ <begin, begin+num_items-1>)
void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
Draw an engine.
Engine GUI functions, used by build_vehicle_gui and autoreplace_gui
bool EngList_SortTypeFunction(const GUIEngineListItem &, const GUIEngineListItem &)
argument type for EngList_Sort.
Definition engine_gui.h:33
void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
Draw a road vehicle engine.
uint64_t PackEngineNameDParam(EngineID engine_id, EngineNameContext context, uint32_t extra_data=0)
Combine an engine ID and a name context to an engine name dparam.
@ PreviewNews
Name is shown in exclusive preview or newspaper.
Types related to the engine widgets.
@ WID_EP_QUESTION
The container for the question.
@ WID_EP_NO
No button.
@ WID_EP_YES
Yes button.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:705
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:251
@ SA_TOP
Top align the text.
Definition gfx_type.h:388
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:384
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:393
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Rail specific functions.
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
Road specific functions.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:230
Road vehicle states.
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a road vehicle sprite heading west (used for lists).
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
Types related to global configuration settings.
Base for ships.
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a ship sprite heading west (used for lists).
Definition ship_cmd.cpp:120
Definition of base types and functions in a cross-platform compatible way.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:415
Functions related to OTTD's strings.
int64_t PackVelocity(uint speed, VehicleType type)
Pack velocity and vehicle type for use with SCC_VELOCITY string parameter.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Class for storing amounts of cargo.
Definition cargo_type.h:113
const T GetSum() const
Get the sum of all cargo amounts.
Definition cargo_type.h:119
Dimensions (a width and height) of a rectangle in 2D.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
StringID GetAircraftTypeText() const
Get the name of the aircraft type for display purposes.
Definition engine.cpp:467
uint GetPower() const
Returns the power of the engine for display and sorting purposes.
Definition engine.cpp:390
uint16_t GetRange() const
Get the range of an aircraft type.
Definition engine.cpp:453
Money GetCost() const
Return how much a new engine costs.
Definition engine.cpp:318
uint GetDisplayMaxSpeed() const
Returns max speed of the engine for display purposes.
Definition engine.cpp:358
uint GetDisplayWeight() const
Returns the weight of the engine for display purposes.
Definition engine.cpp:408
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition engine_base.h:61
uint GetDisplayDefaultCapacity(uint16_t *mail_capacity=nullptr) const
Determines the default cargo capacity of an engine for display purposes.
CargoType GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition engine_base.h:96
Money GetRunningCost() const
Return how much the running costs of this engine are.
Definition engine.cpp:281
uint GetDisplayMaxTractiveEffort() const
Returns the tractive effort of the engine for display purposes.
Definition engine.cpp:426
VehicleSettings vehicle
options for vehicles
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
RailType railtype
Railtype, mangled if elrail is disabled.
Definition engine_type.h:51
Specification of a rectangle with absolute coordinates of all edges.
RoadType roadtype
Road type.
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
uint8_t train_acceleration_model
realistic acceleration for trains
High level window description.
Definition window_gui.h:167
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:273
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1091
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1791
WindowFlags flags
Window flags.
Definition window_gui.h:300
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Base for the train class.
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of a train sprite heading west, or both heads (used for lists).
PaletteID GetEnginePalette(EngineID engine_type, CompanyID company)
Get the colour map for an engine.
Definition vehicle.cpp:2112
Functions related to vehicles.
EngineImageType
Visualisation contexts of vehicles and engines.
@ EIT_PURCHASE
Vehicle drawn in purchase list, autoreplace gui, ...
@ EIT_PREVIEW
Vehicle drawn in preview window, news, ...
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:67
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:53
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:69
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:61
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ EqualSize
Containers should keep all their (resizing) children equally large.
Functions, definitions and such used only by the GUI.
@ Construction
This window is used for construction; close it whenever changing company.
@ Sticky
Window is made sticky by user.
@ WDP_CENTER
Center the window.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_ENGINE_PREVIEW
Engine preview window; Window numbers:
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107