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/>.
8 /** @file roadveh_gui.cpp GUI for road vehicles. */
11 #include "core/backup_type.hpp"
13 #include "window_gui.h"
14 #include "strings_func.h"
15 #include "vehicle_func.h"
16 #include "string_func.h"
17 #include "zoom_func.h"
19 #include "table/strings.h"
21 #include "safeguards.h"
24 * Draw the details for the given vehicle at the given position
26 * @param v current vehicle
27 * @param r the Rect to draw within
29 void DrawRoadVehDetails(const Vehicle
*v
, const Rect
&r
)
31 int y
= r
.top
+ (v
->HasArticulatedPart() ? ScaleSpriteTrad(15) : 0); // Draw the first line below the sprite of an articulated RV instead of after it.
33 Money feeder_share
= 0;
35 SetDParam(0, PackEngineNameDParam(v
->engine_type
, EngineNameContext::VehicleDetails
));
36 SetDParam(1, v
->build_year
);
37 SetDParam(2, v
->value
);
38 DrawString(r
.left
, r
.right
, y
, STR_VEHICLE_INFO_BUILT_VALUE
);
39 y
+= GetCharacterHeight(FS_NORMAL
);
41 if (v
->HasArticulatedPart()) {
42 CargoArray max_cargo
{};
43 std::array
<StringID
, NUM_CARGO
> subtype_text
{};
45 for (const Vehicle
*u
= v
; u
!= nullptr; u
= u
->Next()) {
46 max_cargo
[u
->cargo_type
] += u
->cargo_cap
;
47 if (u
->cargo_cap
> 0) {
48 StringID text
= GetCargoSubtypeText(u
);
49 if (text
!= STR_EMPTY
) subtype_text
[u
->cargo_type
] = text
;
53 std::string capacity
= GetString(STR_VEHICLE_DETAILS_TRAIN_ARTICULATED_RV_CAPACITY
);
56 for (const CargoSpec
*cs
: _sorted_cargo_specs
) {
57 CargoID cid
= cs
->Index();
58 if (max_cargo
[cid
] > 0) {
59 if (!first
) capacity
+= ", ";
62 SetDParam(1, max_cargo
[cid
]);
63 AppendStringInPlace(capacity
, STR_JUST_CARGO
);
65 if (subtype_text
[cid
] != STR_NULL
) {
66 AppendStringInPlace(capacity
, subtype_text
[cid
]);
73 DrawString(r
.left
, r
.right
, y
, capacity
, TC_BLUE
);
74 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
76 for (const Vehicle
*u
= v
; u
!= nullptr; u
= u
->Next()) {
77 if (u
->cargo_cap
== 0) continue;
79 str
= STR_VEHICLE_DETAILS_CARGO_EMPTY
;
80 if (u
->cargo
.StoredCount() > 0) {
81 SetDParam(0, u
->cargo_type
);
82 SetDParam(1, u
->cargo
.StoredCount());
83 SetDParam(2, u
->cargo
.GetFirstStation());
84 str
= STR_VEHICLE_DETAILS_CARGO_FROM
;
85 feeder_share
+= u
->cargo
.GetFeederShare();
87 DrawString(r
.left
, r
.right
, y
, str
);
88 y
+= GetCharacterHeight(FS_NORMAL
);
90 y
+= WidgetDimensions::scaled
.vsep_normal
;
92 SetDParam(0, v
->cargo_type
);
93 SetDParam(1, v
->cargo_cap
);
94 SetDParam(4, GetCargoSubtypeText(v
));
95 DrawString(r
.left
, r
.right
, y
, STR_VEHICLE_INFO_CAPACITY
);
96 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
98 str
= STR_VEHICLE_DETAILS_CARGO_EMPTY
;
99 if (v
->cargo
.StoredCount() > 0) {
100 SetDParam(0, v
->cargo_type
);
101 SetDParam(1, v
->cargo
.StoredCount());
102 SetDParam(2, v
->cargo
.GetFirstStation());
103 str
= STR_VEHICLE_DETAILS_CARGO_FROM
;
104 feeder_share
+= v
->cargo
.GetFeederShare();
106 DrawString(r
.left
, r
.right
, y
, str
);
107 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
110 /* Draw Transfer credits text */
111 SetDParam(0, feeder_share
);
112 DrawString(r
.left
, r
.right
, y
, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE
);
116 * Draws an image of a road vehicle chain
117 * @param v Front vehicle
118 * @param r Rect to draw at
119 * @param selection Selected vehicle to draw a frame around
120 * @param skip Number of pixels to skip at the front (for scrolling)
122 void DrawRoadVehImage(const Vehicle
*v
, const Rect
&r
, VehicleID selection
, EngineImageType image_type
, int skip
)
124 bool rtl
= _current_text_dir
== TD_RTL
;
125 Direction dir
= rtl
? DIR_E
: DIR_W
;
126 const RoadVehicle
*u
= RoadVehicle::From(v
);
128 DrawPixelInfo tmp_dpi
;
129 int max_width
= r
.Width();
131 if (!FillDrawPixelInfo(&tmp_dpi
, r
)) return;
133 AutoRestoreBackup
dpi_backup(_cur_dpi
, &tmp_dpi
);
135 bool do_overlays
= ShowCargoIconOverlay();
136 /* List of overlays, only used if cargo icon overlays are enabled. */
137 static std::vector
<CargoIconOverlay
> overlays
;
139 int px
= rtl
? max_width
+ skip
: -skip
;
140 int y
= r
.Height() / 2;
141 for (; u
!= nullptr && (rtl
? px
> 0 : px
< max_width
); u
= u
->Next())
144 int width
= u
->GetDisplayImageWidth(&offset
);
146 if (rtl
? px
+ width
> 0 : px
- width
< max_width
) {
147 PaletteID pal
= (u
->vehstatus
& VS_CRASHED
) ? PALETTE_CRASH
: GetVehiclePalette(u
);
148 VehicleSpriteSeq seq
;
149 u
->GetImage(dir
, image_type
, &seq
);
150 seq
.Draw(px
+ (rtl
? -offset
.x
: offset
.x
), y
+ offset
.y
, pal
, (u
->vehstatus
& VS_CRASHED
) != 0);
153 if (do_overlays
) AddCargoIconOverlay(overlays
, px
, width
, u
);
154 px
+= rtl
? -width
: width
;
158 DrawCargoIconOverlays(overlays
, y
);
162 if (v
->index
== selection
) {
163 int height
= ScaleSpriteTrad(12);
164 Rect hr
= {(rtl
? px
: 0), 0, (rtl
? max_width
: px
) - 1, height
- 1};
165 DrawFrameRect(hr
.Translate(r
.left
, CenterBounds(r
.top
, r
.bottom
, height
)).Expand(WidgetDimensions::scaled
.bevel
), COLOUR_WHITE
, FR_BORDERONLY
);