@@ -29,13 +29,13 @@ enum AircraftSubType {
enum VehicleAirFlags {
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
};
void HandleAircraftEnterHangar(Aircraft *v);
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type);
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
void UpdateAirplanesOnNewStation(const Station *st);
void UpdateAircraftCache(Aircraft *v, bool update_range = false);
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir);
void AircraftNextAirportPos_and_Order(Aircraft *v);
void SetAircraftPosition(Aircraft *v, int x, int y, int z);
@@ -199,23 +199,28 @@ void DrawAircraftEngine(int left, int ri
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
DrawSprite(rotor_sprite, PAL_NONE, preferred_x, y - 5);
}
/**
* Get the size of the sprite of an aircraft sprite heading west (used for lists)
* @param engine The engine to get the sprite from
* @param width The width of the sprite
* @param height The height of the sprite
* Get the size of the sprite of an aircraft sprite heading west (used for lists).
* @param engine The engine to get the sprite from.
* @param[out] width The width of the sprite.
* @param[out] height The height of the sprite.
* @param[out] xoffs Number of pixels to shift the sprite to the right.
* @param[out] yoffs Number of pixels to shift the sprite downwards.
* @param image_type Context the sprite is used in.
*/
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type)
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type), ST_NORMAL);
width = UnScaleByZoom(spr->width, ZOOM_LVL_GUI);
height = UnScaleByZoom(spr->height, ZOOM_LVL_GUI);
xoffs = UnScaleByZoom(spr->x_offs, ZOOM_LVL_GUI);
yoffs = UnScaleByZoom(spr->y_offs, ZOOM_LVL_GUI);
* Build an aircraft.
* @param tile tile of the depot where aircraft is built.
* @param flags type of operation.
@@ -40,13 +40,13 @@
* Get the height of a single 'entry' in the engine lists.
* @param type the vehicle type to get the height of
* @return the height for the entry
uint GetEngineListHeight(VehicleType type)
return max<uint>(FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM, GetVehicleHeight(type));
return max<uint>(FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM, GetVehicleImageCellSize(type, EIT_PURCHASE).height);
static const NWidgetPart _nested_build_vehicle_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_BV_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
@@ -868,37 +868,36 @@ int DrawVehiclePurchaseInfo(int left, in
* @param selected_id what engine to highlight as selected, if any
* @param show_count Whether to show the amount of engines or not
* @param selected_group the group to list the engines of
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)
static const int sprite_widths[] = { 60, 60, 76, 67 };
static const int sprite_y_offsets[] = { -1, -1, -2, -2 };
/* Obligatory sanity checks! */
assert((uint)type < lengthof(sprite_widths));
assert_compile(lengthof(sprite_y_offsets) == lengthof(sprite_widths));
assert(max <= eng_list->Length());
bool rtl = _current_text_dir == TD_RTL;
int step_size = GetEngineListHeight(type);
int sprite_width = sprite_widths[type];
int sprite_left = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left;
int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
int sprite_width = sprite_left + sprite_right;
int sprite_x = (rtl ? r - sprite_width / 2 : l + sprite_width / 2) - 1;
int sprite_x = rtl ? r - sprite_right - 1 : l + sprite_left + 1;
int sprite_y_offset = sprite_y_offsets[type] + step_size / 2;
Dimension replace_icon = {0, 0};
int count_width = 0;
if (show_count) {
replace_icon = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
SetDParamMaxDigits(0, 3);
count_width = GetStringBoundingBox(STR_TINY_BLACK_COMA).width;
int text_left = l + (rtl ? WD_FRAMERECT_LEFT + replace_icon.width + 8 + count_width : sprite_width);
int text_right = r - (rtl ? sprite_width : WD_FRAMERECT_RIGHT + replace_icon.width + 8 + count_width);
int text_left = l + (rtl ? WD_FRAMERECT_LEFT + replace_icon.width + 8 + count_width : sprite_width + WD_FRAMETEXT_LEFT);
int text_right = r - (rtl ? sprite_width + WD_FRAMETEXT_RIGHT : WD_FRAMERECT_RIGHT + replace_icon.width + 8 + count_width);
int replace_icon_left = rtl ? l + WD_FRAMERECT_LEFT : r - WD_FRAMERECT_RIGHT - replace_icon.width;
int count_left = l;
int count_right = rtl ? text_left : r - WD_FRAMERECT_RIGHT - replace_icon.width - 8;
int normal_text_y_offset = (step_size - FONT_HEIGHT_NORMAL) / 2;
int small_text_y_offset = step_size - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1;
@@ -907,13 +906,13 @@ void DrawEngineList(VehicleType type, in
for (; min < max; min++, y += step_size) {
const EngineID engine = (*eng_list)[min];
/* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */
const uint num_engines = GetGroupNumEngines(_local_company, selected_group, engine);
SetDParam(0, engine);
DrawString(text_left, text_right, y + normal_text_y_offset, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK);
DrawString(text_left, text_right, y + normal_text_y_offset, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK, SA_STRIP | (rtl ? SA_RIGHT : SA_LEFT));
DrawVehicleEngine(l, r, sprite_x, y + sprite_y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_company), EIT_PURCHASE);
SetDParam(0, num_engines);
DrawString(count_left, count_right, y + small_text_y_offset, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE);
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);
@@ -8,12 +8,13 @@
/** @file depot_gui.cpp The GUI for depots. */
#include "stdafx.h"
#include "train.h"
#include "roadveh.h"
#include "ship.h"
#include "aircraft.h"
#include "gui.h"
#include "textbuf_gui.h"
#include "viewport_func.h"
#include "command_func.h"
@@ -138,63 +139,81 @@ static void TrainDepotMoveVehicle(const
if (wagon == v) return;
DoCommandP(v->tile, v->index | (_ctrl_pressed ? 1 : 0) << 20, wagon == NULL ? INVALID_VEHICLE : wagon->index, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_MOVE_VEHICLE));
static VehicleCellSize _base_block_sizes_depot[VEH_COMPANY_END]; ///< Cell size for vehicle images in the depot view.
static VehicleCellSize _base_block_sizes_purchase[VEH_COMPANY_END]; ///< Cell size for vehicle images in the purchase list.
* Array containing the cell size in pixels of the #WID_D_MATRIX widget for each vehicle type.
* @note The train vehicle type uses the entire row for each train.
* Get the GUI cell size for a vehicle image.
* @param type Vehicle type to get the size for.
* @param image_type Image type to get size for.
* @pre image_type == EIT_IN_DEPOT || image_type == EIT_PURCHASE
* @return Cell dimensions for the vehicle and image type.
static Dimension _base_block_sizes[4];
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type)
switch (image_type) {
case EIT_IN_DEPOT: return _base_block_sizes_depot[type];
case EIT_PURCHASE: return _base_block_sizes_purchase[type];
default: NOT_REACHED();
static void InitBlocksizeForShipAircraft(VehicleType type)
static void InitBlocksizeForVehicles(VehicleType type, EngineImageType image_type)
uint max_width = 0;
int max_extend_left = 0;
int max_extend_right = 0;
uint max_height = 0;
const Engine *e;
FOR_ALL_ENGINES_OF_TYPE(e, type) {
EngineID eid = e->index;
uint x, y;
int x_offs, y_offs;
switch (type) {
case VEH_SHIP: GetShipSpriteSize( eid, x, y, EIT_IN_DEPOT); break;
case VEH_AIRCRAFT: GetAircraftSpriteSize(eid, x, y, EIT_IN_DEPOT); break;
case VEH_TRAIN: GetTrainSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
case VEH_ROAD: GetRoadVehSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
case VEH_SHIP: GetShipSpriteSize( eid, x, y, x_offs, y_offs, image_type); break;
case VEH_AIRCRAFT: GetAircraftSpriteSize(eid, x, y, x_offs, y_offs, image_type); break;
if (x > max_width) max_width = x;
if (y > max_height) max_height = y;
if (-x_offs > max_extend_left) max_extend_left = -x_offs;
if ((int)x + x_offs > max_extend_right) max_extend_right = x + x_offs;
case VEH_SHIP:
_base_block_sizes[VEH_SHIP].width = max(76U, max_width);
case EIT_IN_DEPOT:
_base_block_sizes_depot[type].height = max(GetVehicleHeight(type), max_height);
_base_block_sizes_depot[type].extend_left = Clamp(max_extend_left, 16, 98);
_base_block_sizes_depot[type].extend_right = Clamp(max_extend_right, 16, 98);
break;
case VEH_AIRCRAFT:
_base_block_sizes[VEH_AIRCRAFT].width = max(67U, max_width);
case EIT_PURCHASE:
_base_block_sizes_purchase[type].height = max(GetVehicleHeight(type), max_height);
_base_block_sizes_purchase[type].extend_left = Clamp(max_extend_left, 16, 98);
_base_block_sizes_purchase[type].extend_right = Clamp(max_extend_right, 16, 98);
_base_block_sizes[type].height = max(GetVehicleHeight(type), max_height);
* Set the size of the blocks in the window so we can be sure that they are big enough for the vehicle sprites in the current game.
* @note Calling this function once for each game is enough.
void InitDepotWindowBlockSizes()
_base_block_sizes[VEH_TRAIN].width = 0;
_base_block_sizes[VEH_TRAIN].height = GetVehicleHeight(VEH_TRAIN);
_base_block_sizes[VEH_ROAD].width = 32;
_base_block_sizes[VEH_ROAD].height = GetVehicleHeight(VEH_ROAD);
InitBlocksizeForShipAircraft(VEH_SHIP);
InitBlocksizeForShipAircraft(VEH_AIRCRAFT);
for (VehicleType vt = VEH_BEGIN; vt < VEH_COMPANY_END; vt++) {
InitBlocksizeForVehicles(vt, EIT_IN_DEPOT);
InitBlocksizeForVehicles(vt, EIT_PURCHASE);
static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
const Sprite *GetAircraftSprite(EngineID engine);
struct DepotWindow : Window {
@@ -597,19 +616,19 @@ struct DepotWindow : Window {
} else {
min_height = unumber.height + UnScaleByZoom(spr->height, ZOOM_LVL_GUI) + WD_MATRIX_TOP + WD_PAR_VSEP_NORMAL + WD_MATRIX_BOTTOM;
this->header_width = max<uint>(unumber.width, this->flag_width) + WD_FRAMERECT_RIGHT;
int base_width = this->count_width + this->header_width;
resize->height = max(_base_block_sizes[this->type].height, min_height);
resize->height = max<uint>(GetVehicleImageCellSize(this->type, EIT_IN_DEPOT).height, min_height);
if (this->type == VEH_TRAIN) {
resize->width = 1;
size->width = base_width + 2 * 29; // about 2 parts
size->height = resize->height * 6;
resize->width = base_width + _base_block_sizes[this->type].width;
resize->width = base_width + GetVehicleImageCellSize(this->type, EIT_IN_DEPOT).extend_left + GetVehicleImageCellSize(this->type, EIT_IN_DEPOT).extend_right;
size->width = resize->width * (this->type == VEH_ROAD ? 5 : 3);
size->height = resize->height * (this->type == VEH_ROAD ? 5 : 3);
fill->width = resize->width;
fill->height = resize->height;
@@ -77,12 +77,13 @@ static const uint RVC_DRIVE_THROUGH_STOP
static const uint RVC_DEPOT_STOP_FRAME = 11;
/** The number of ticks a vehicle has for overtaking. */
static const byte RV_OVERTAKE_TIMEOUT = 35;
void RoadVehUpdateCache(RoadVehicle *v, bool same_length = false);
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
* Buses, trucks and trams belong to this class.
struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
byte state; ///< @see RoadVehicleStates
@@ -153,12 +153,31 @@ void DrawRoadVehEngine(int left, int rig
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
preferred_x = Clamp(preferred_x, left - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI), right - UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) - UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI));
DrawSprite(sprite, pal, preferred_x, y);
* Get the size of the sprite of a road vehicle sprite heading west (used for lists).
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
const Sprite *spr = GetSprite(GetRoadVehIcon(engine, image_type), ST_NORMAL);
* Get length of a road vehicle.
* @param v Road vehicle to query length.
* @return Length of the given road vehicle.
static uint GetRoadVehLength(const RoadVehicle *v)
@@ -12,13 +12,13 @@
#ifndef SHIP_H
#define SHIP_H
#include "vehicle_base.h"
#include "water_map.h"
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type);
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
WaterClass GetEffectiveWaterClass(TileIndex tile);
* All ships have this type.
struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
@@ -83,23 +83,28 @@ void DrawShipEngine(int left, int right,
* Get the size of the sprite of a ship sprite heading west (used for lists)
* Get the size of the sprite of a ship sprite heading west (used for lists).
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type)
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
const Sprite *spr = GetSprite(GetShipIcon(engine, image_type), ST_NORMAL);
SpriteID Ship::GetImage(Direction direction, EngineImageType image_type) const
uint8 spritenum = this->spritenum;
@@ -47,12 +47,14 @@ void CheckTrainsLengths();
void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
/** Variables that are cached to improve performance and such */
struct TrainCache {
/* Cached wagon override spritegroup */
const struct SpriteGroup *cached_override;
/* cached values, recalculated on load and each time a vehicle is added to/removed from the consist. */
@@ -525,12 +525,45 @@ void DrawTrainEngine(int left, int right
* Get the size of the sprite of a train sprite heading west, or both heads (used for lists).
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
int y = 0;
SpriteID sprite = GetRailIcon(engine, false, y, image_type);
width = UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI);
height = UnScaleByZoom(real_sprite->height, ZOOM_LVL_GUI);
xoffs = UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI);
yoffs = UnScaleByZoom(real_sprite->y_offs, ZOOM_LVL_GUI);
if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
sprite = GetRailIcon(engine, true, y, image_type);
real_sprite = GetSprite(sprite, ST_NORMAL);
/* Calculate values relative to an imaginary center between the two sprites. */
width = TRAININFO_DEFAULT_VEHICLE_WIDTH + UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI) + UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI) - xoffs;
height = max<uint>(height, UnScaleByZoom(real_sprite->height, ZOOM_LVL_GUI));
xoffs = xoffs - TRAININFO_DEFAULT_VEHICLE_WIDTH / 2;
yoffs = min(yoffs, UnScaleByZoom(real_sprite->y_offs, ZOOM_LVL_GUI));
* Build a railroad wagon.
* @param tile tile of the depot where rail-vehicle is built.
* @param e the engine to build.
* @param ret[out] the vehicle that has been built.
* @return the cost of this operation or an error.
@@ -63,12 +63,21 @@ static inline uint GetVehicleHeight(Vehi
return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24;
int GetVehicleWidth(Vehicle *v, EngineImageType image_type);
/** Dimensions of a cell in the purchase/depot windows. */
struct VehicleCellSize {
uint height; ///< Vehicle cell height.
uint extend_left; ///< Extend of the cell to the left.
uint extend_right; ///< Extend of the cell to the right.
VehicleCellSize GetVehicleImageCellSize(VehicleType type, EngineImageType image_type);
* Get WindowClass for vehicle list of given vehicle type
* @param vt vehicle type to check
* @return corresponding window class
* @note works only for company buildable vehicle types
Status change: