(svn r23005) -Fix (r23004): Of course there's still the 16-sprite version for shore...
[openttd/fttd.git] / src / engine_gui.cpp
blob1c89d3a36a5a662d8a5196895d585819dc112ebf
1 /* $Id$ */
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 */
10 /** @file engine_gui.cpp GUI to show engine related information. */
12 #include "stdafx.h"
13 #include "window_gui.h"
14 #include "gfx_func.h"
15 #include "engine_base.h"
16 #include "command_func.h"
17 #include "strings_func.h"
18 #include "engine_gui.h"
19 #include "articulated_vehicles.h"
20 #include "vehicle_func.h"
21 #include "company_func.h"
22 #include "rail.h"
23 #include "settings_type.h"
25 #include "table/strings.h"
27 /**
28 * Return the category of an engine.
29 * @param engine Engine to examine.
30 * @return String describing the category ("road veh", "train". "airplane", or "ship") of the engine.
32 StringID GetEngineCategoryName(EngineID engine)
34 const Engine *e = Engine::Get(engine);
35 switch (e->type) {
36 default: NOT_REACHED();
37 case VEH_ROAD: return STR_ENGINE_PREVIEW_ROAD_VEHICLE;
38 case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
39 case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
40 case VEH_TRAIN:
41 return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
45 /** Widgets used for the engine preview window */
46 enum EnginePreviewWidgets {
47 EPW_QUESTION, ///< The container for the question
48 EPW_NO, ///< No button
49 EPW_YES, ///< Yes button
52 static const NWidgetPart _nested_engine_preview_widgets[] = {
53 NWidget(NWID_HORIZONTAL),
54 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
55 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
56 EndContainer(),
57 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
58 NWidget(WWT_EMPTY, INVALID_COLOUR, EPW_QUESTION), SetMinimalSize(300, 0), SetPadding(8, 8, 8, 8), SetFill(1, 0),
59 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(85, 10, 85),
60 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, EPW_NO), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
61 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, EPW_YES), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
62 EndContainer(),
63 NWidget(NWID_SPACER), SetMinimalSize(0, 8),
64 EndContainer(),
67 struct EnginePreviewWindow : Window {
68 static const int VEHICLE_SPACE = 40; // The space to show the vehicle image
70 EnginePreviewWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
72 this->InitNested(desc, window_number);
75 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
77 if (widget != EPW_QUESTION) return;
79 EngineID engine = this->window_number;
80 SetDParam(0, GetEngineCategoryName(engine));
81 size->height = GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, size->width) + WD_PAR_VSEP_WIDE + FONT_HEIGHT_NORMAL + VEHICLE_SPACE;
82 SetDParam(0, engine);
83 size->height += GetStringHeight(GetEngineInfoString(engine), size->width);
86 virtual void DrawWidget(const Rect &r, int widget) const
88 if (widget != EPW_QUESTION) return;
90 EngineID engine = this->window_number;
91 SetDParam(0, GetEngineCategoryName(engine));
92 int y = r.top + GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, r.right - r.top + 1);
93 y = DrawStringMultiLine(r.left, r.right, r.top, y, STR_ENGINE_PREVIEW_MESSAGE, TC_FROMSTRING, SA_CENTER) + WD_PAR_VSEP_WIDE;
95 SetDParam(0, engine);
96 DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_ENGINE_NAME, TC_BLACK, SA_HOR_CENTER);
97 y += FONT_HEIGHT_NORMAL;
99 DrawVehicleEngine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, this->width >> 1, y + VEHICLE_SPACE / 2, engine, GetEnginePalette(engine, _local_company));
101 y += VEHICLE_SPACE;
102 DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, r.bottom, GetEngineInfoString(engine), TC_FROMSTRING, SA_CENTER);
105 virtual void OnClick(Point pt, int widget, int click_count)
107 switch (widget) {
108 case EPW_YES:
109 DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
110 /* FALL THROUGH */
111 case EPW_NO:
112 delete this;
113 break;
118 static const WindowDesc _engine_preview_desc(
119 WDP_CENTER, 0, 0,
120 WC_ENGINE_PREVIEW, WC_NONE,
121 WDF_CONSTRUCTION,
122 _nested_engine_preview_widgets, lengthof(_nested_engine_preview_widgets)
126 void ShowEnginePreviewWindow(EngineID engine)
128 AllocateWindowDescFront<EnginePreviewWindow>(&_engine_preview_desc, engine);
132 * Get the capacity of an engine with articulated parts.
133 * @param engine The engine to get the capacity of.
134 * @return The capacity.
136 uint GetTotalCapacityOfArticulatedParts(EngineID engine)
138 uint total = 0;
140 CargoArray cap = GetCapacityOfArticulatedParts(engine);
141 for (CargoID c = 0; c < NUM_CARGO; c++) {
142 total += cap[c];
145 return total;
148 static StringID GetTrainEngineInfoString(const Engine *e)
150 SetDParam(0, e->GetCost());
151 SetDParam(2, e->GetDisplayMaxSpeed());
152 SetDParam(3, e->GetPower());
153 SetDParam(1, e->GetDisplayWeight());
154 SetDParam(7, e->GetDisplayMaxTractiveEffort());
156 SetDParam(4, e->GetRunningCost());
158 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
159 if (capacity != 0) {
160 SetDParam(5, e->GetDefaultCargoType());
161 SetDParam(6, capacity);
162 } else {
163 SetDParam(5, CT_INVALID);
165 return (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(e->u.rail.railtype)->acceleration_type != 2) ? STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE : STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER;
168 static StringID GetAircraftEngineInfoString(const Engine *e)
170 CargoID cargo = e->GetDefaultCargoType();
171 uint16 mail_capacity;
172 uint capacity = e->GetDisplayDefaultCapacity(&mail_capacity);
174 SetDParam(0, e->GetCost());
175 SetDParam(1, e->GetDisplayMaxSpeed());
176 SetDParam(2, cargo);
177 SetDParam(3, capacity);
179 if (mail_capacity > 0) {
180 SetDParam(4, CT_MAIL);
181 SetDParam(5, mail_capacity);
182 SetDParam(6, e->GetRunningCost());
183 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST;
184 } else {
185 SetDParam(4, e->GetRunningCost());
186 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
190 static StringID GetRoadVehEngineInfoString(const Engine *e)
192 if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) {
193 SetDParam(0, e->GetCost());
194 SetDParam(1, e->GetDisplayMaxSpeed());
195 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
196 if (capacity != 0) {
197 SetDParam(2, e->GetDefaultCargoType());
198 SetDParam(3, capacity);
199 } else {
200 SetDParam(2, CT_INVALID);
202 SetDParam(4, e->GetRunningCost());
203 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
204 } else {
205 SetDParam(0, e->GetCost());
206 SetDParam(2, e->GetDisplayMaxSpeed());
207 SetDParam(3, e->GetPower());
208 SetDParam(1, e->GetDisplayWeight());
209 SetDParam(7, e->GetDisplayMaxTractiveEffort());
211 SetDParam(4, e->GetRunningCost());
213 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
214 if (capacity != 0) {
215 SetDParam(5, e->GetDefaultCargoType());
216 SetDParam(6, capacity);
217 } else {
218 SetDParam(5, CT_INVALID);
220 return STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE;
224 static StringID GetShipEngineInfoString(const Engine *e)
226 SetDParam(0, e->GetCost());
227 SetDParam(1, e->GetDisplayMaxSpeed());
228 SetDParam(2, e->GetDefaultCargoType());
229 SetDParam(3, e->GetDisplayDefaultCapacity());
230 SetDParam(4, e->GetRunningCost());
231 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
236 * Get a multi-line string with some technical data, describing the engine.
237 * @param engine Engine to describe.
238 * @return String describing the engine.
239 * @post \c DParam array is set up for printing the string.
241 StringID GetEngineInfoString(EngineID engine)
243 const Engine *e = Engine::Get(engine);
245 switch (e->type) {
246 case VEH_TRAIN:
247 return GetTrainEngineInfoString(e);
249 case VEH_ROAD:
250 return GetRoadVehEngineInfoString(e);
252 case VEH_SHIP:
253 return GetShipEngineInfoString(e);
255 case VEH_AIRCRAFT:
256 return GetAircraftEngineInfoString(e);
258 default: NOT_REACHED();
263 * Draw an engine.
264 * @param left Minimum horizontal position to use for drawing the engine
265 * @param right Maximum horizontal position to use for drawing the engine
266 * @param preferred_x Horizontal position to use for drawing the engine.
267 * @param y Vertical position to use for drawing the engine.
268 * @param engine Engine to draw.
269 * @param pal Palette to use for drawing.
271 void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal)
273 const Engine *e = Engine::Get(engine);
275 switch (e->type) {
276 case VEH_TRAIN:
277 DrawTrainEngine(left, right, preferred_x, y, engine, pal);
278 break;
280 case VEH_ROAD:
281 DrawRoadVehEngine(left, right, preferred_x, y, engine, pal);
282 break;
284 case VEH_SHIP:
285 DrawShipEngine(left, right, preferred_x, y, engine, pal);
286 break;
288 case VEH_AIRCRAFT:
289 DrawAircraftEngine(left, right, preferred_x, y, engine, pal);
290 break;
292 default: NOT_REACHED();
297 * Sort all items using quick sort and given 'CompareItems' function
298 * @param el list to be sorted
299 * @param compare function for evaluation of the quicksort
301 void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
303 uint size = el->Length();
304 /* out-of-bounds access at the next line for size == 0 (even with operator[] at some systems)
305 * generally, do not sort if there are less than 2 items */
306 if (size < 2) return;
307 QSortT(el->Begin(), size, compare);
311 * Sort selected range of items (on indices @ <begin, begin+num_items-1>)
312 * @param el list to be sorted
313 * @param compare function for evaluation of the quicksort
314 * @param begin start of sorting
315 * @param num_items count of items to be sorted
317 void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items)
319 if (num_items < 2) return;
320 assert(begin < el->Length());
321 assert(begin + num_items <= el->Length());
322 QSortT(el->Get(begin), num_items, compare);