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
);
54 std::string_view list_separator
= GetListSeparator();
57 for (const CargoSpec
*cs
: _sorted_cargo_specs
) {
58 CargoID cid
= cs
->Index();
59 if (max_cargo
[cid
] > 0) {
60 if (!first
) capacity
+= list_separator
;
63 SetDParam(1, max_cargo
[cid
]);
64 AppendStringInPlace(capacity
, STR_JUST_CARGO
);
66 if (subtype_text
[cid
] != STR_NULL
) {
67 AppendStringInPlace(capacity
, subtype_text
[cid
]);
74 DrawString(r
.left
, r
.right
, y
, capacity
, TC_BLUE
);
75 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
77 for (const Vehicle
*u
= v
; u
!= nullptr; u
= u
->Next()) {
78 if (u
->cargo_cap
== 0) continue;
80 str
= STR_VEHICLE_DETAILS_CARGO_EMPTY
;
81 if (u
->cargo
.StoredCount() > 0) {
82 SetDParam(0, u
->cargo_type
);
83 SetDParam(1, u
->cargo
.StoredCount());
84 SetDParam(2, u
->cargo
.GetFirstStation());
85 str
= STR_VEHICLE_DETAILS_CARGO_FROM
;
86 feeder_share
+= u
->cargo
.GetFeederShare();
88 DrawString(r
.left
, r
.right
, y
, str
);
89 y
+= GetCharacterHeight(FS_NORMAL
);
91 y
+= WidgetDimensions::scaled
.vsep_normal
;
93 SetDParam(0, v
->cargo_type
);
94 SetDParam(1, v
->cargo_cap
);
95 SetDParam(4, GetCargoSubtypeText(v
));
96 DrawString(r
.left
, r
.right
, y
, STR_VEHICLE_INFO_CAPACITY
);
97 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
99 str
= STR_VEHICLE_DETAILS_CARGO_EMPTY
;
100 if (v
->cargo
.StoredCount() > 0) {
101 SetDParam(0, v
->cargo_type
);
102 SetDParam(1, v
->cargo
.StoredCount());
103 SetDParam(2, v
->cargo
.GetFirstStation());
104 str
= STR_VEHICLE_DETAILS_CARGO_FROM
;
105 feeder_share
+= v
->cargo
.GetFeederShare();
107 DrawString(r
.left
, r
.right
, y
, str
);
108 y
+= GetCharacterHeight(FS_NORMAL
) + WidgetDimensions::scaled
.vsep_normal
;
111 /* Draw Transfer credits text */
112 SetDParam(0, feeder_share
);
113 DrawString(r
.left
, r
.right
, y
, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE
);
117 * Draws an image of a road vehicle chain
118 * @param v Front vehicle
119 * @param r Rect to draw at
120 * @param selection Selected vehicle to draw a frame around
121 * @param skip Number of pixels to skip at the front (for scrolling)
123 void DrawRoadVehImage(const Vehicle
*v
, const Rect
&r
, VehicleID selection
, EngineImageType image_type
, int skip
)
125 bool rtl
= _current_text_dir
== TD_RTL
;
126 Direction dir
= rtl
? DIR_E
: DIR_W
;
127 const RoadVehicle
*u
= RoadVehicle::From(v
);
129 DrawPixelInfo tmp_dpi
;
130 int max_width
= r
.Width();
132 if (!FillDrawPixelInfo(&tmp_dpi
, r
)) return;
134 AutoRestoreBackup
dpi_backup(_cur_dpi
, &tmp_dpi
);
136 bool do_overlays
= ShowCargoIconOverlay();
137 /* List of overlays, only used if cargo icon overlays are enabled. */
138 static std::vector
<CargoIconOverlay
> overlays
;
140 int px
= rtl
? max_width
+ skip
: -skip
;
141 int y
= r
.Height() / 2;
142 for (; u
!= nullptr && (rtl
? px
> 0 : px
< max_width
); u
= u
->Next())
145 int width
= u
->GetDisplayImageWidth(&offset
);
147 if (rtl
? px
+ width
> 0 : px
- width
< max_width
) {
148 PaletteID pal
= (u
->vehstatus
& VS_CRASHED
) ? PALETTE_CRASH
: GetVehiclePalette(u
);
149 VehicleSpriteSeq seq
;
150 u
->GetImage(dir
, image_type
, &seq
);
151 seq
.Draw(px
+ (rtl
? -offset
.x
: offset
.x
), y
+ offset
.y
, pal
, (u
->vehstatus
& VS_CRASHED
) != 0);
154 if (do_overlays
) AddCargoIconOverlay(overlays
, px
, width
, u
);
155 px
+= rtl
? -width
: width
;
159 DrawCargoIconOverlays(overlays
, y
);
163 if (v
->index
== selection
) {
164 int height
= ScaleSpriteTrad(12);
165 Rect hr
= {(rtl
? px
: 0), 0, (rtl
? max_width
: px
) - 1, height
- 1};
166 DrawFrameRect(hr
.Translate(r
.left
, CenterBounds(r
.top
, r
.bottom
, height
)).Expand(WidgetDimensions::scaled
.bevel
), COLOUR_WHITE
, FR_BORDERONLY
);