mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
8 Commits
557001ca83
...
f0aab44078
Author | SHA1 | Date |
---|---|---|
|
f0aab44078 | |
|
9ce2aca949 | |
|
55098a2f2e | |
|
7ff0c67f77 | |
|
b2de1ff66f | |
|
fc924161ab | |
|
61a299bc99 | |
|
18dfad871a |
|
@ -48,10 +48,7 @@
|
||||||
|
|
||||||
void Aircraft::UpdateDeltaXY()
|
void Aircraft::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
this->x_offs = -1;
|
this->bounds = {{-1, -1, 0}, {2, 2, 0}, {}};
|
||||||
this->y_offs = -1;
|
|
||||||
this->x_extent = 2;
|
|
||||||
this->y_extent = 2;
|
|
||||||
|
|
||||||
switch (this->subtype) {
|
switch (this->subtype) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
@ -64,21 +61,21 @@ void Aircraft::UpdateDeltaXY()
|
||||||
case LANDING:
|
case LANDING:
|
||||||
case HELILANDING:
|
case HELILANDING:
|
||||||
case FLYING:
|
case FLYING:
|
||||||
this->x_extent = 24;
|
/* Bounds are not centred on the aircraft. */
|
||||||
this->y_extent = 24;
|
this->bounds.extent.x = 24;
|
||||||
|
this->bounds.extent.y = 24;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->z_extent = 5;
|
this->bounds.extent.z = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AIR_SHADOW:
|
case AIR_SHADOW:
|
||||||
this->z_extent = 1;
|
this->bounds.extent.z = 1;
|
||||||
this->x_offs = 0;
|
this->bounds.origin = {};
|
||||||
this->y_offs = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AIR_ROTOR:
|
case AIR_ROTOR:
|
||||||
this->z_extent = 1;
|
this->bounds.extent.z = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,36 +69,45 @@ static void DrawClearLandFence(const TileInfo *ti)
|
||||||
/* combine fences into one sprite object */
|
/* combine fences into one sprite object */
|
||||||
StartSpriteCombine();
|
StartSpriteCombine();
|
||||||
|
|
||||||
int maxz = GetSlopeMaxPixelZ(ti->tileh);
|
SpriteBounds bounds = {{}, {TILE_SIZE, TILE_SIZE, 4}, {}};
|
||||||
|
|
||||||
|
bounds.extent.z += GetSlopeMaxPixelZ(ti->tileh);
|
||||||
|
|
||||||
uint fence_nw = GetFence(ti->tile, DIAGDIR_NW);
|
uint fence_nw = GetFence(ti->tile, DIAGDIR_NW);
|
||||||
if (fence_nw != 0) {
|
if (fence_nw != 0) {
|
||||||
int z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
|
bounds.offset.x = 0;
|
||||||
|
bounds.offset.y = -static_cast<int>(TILE_SIZE);
|
||||||
|
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
|
||||||
SpriteID sprite = _clear_land_fence_sprites[fence_nw - 1] + _fence_mod_by_tileh_nw[ti->tileh];
|
SpriteID sprite = _clear_land_fence_sprites[fence_nw - 1] + _fence_mod_by_tileh_nw[ti->tileh];
|
||||||
AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y - 16, 16, 32, maxz - z + 4, ti->z + z, false, 0, 16, -z);
|
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint fence_ne = GetFence(ti->tile, DIAGDIR_NE);
|
uint fence_ne = GetFence(ti->tile, DIAGDIR_NE);
|
||||||
if (fence_ne != 0) {
|
if (fence_ne != 0) {
|
||||||
int z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
|
bounds.offset.x = -static_cast<int>(TILE_SIZE);
|
||||||
|
bounds.offset.y = 0;
|
||||||
|
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
|
||||||
SpriteID sprite = _clear_land_fence_sprites[fence_ne - 1] + _fence_mod_by_tileh_ne[ti->tileh];
|
SpriteID sprite = _clear_land_fence_sprites[fence_ne - 1] + _fence_mod_by_tileh_ne[ti->tileh];
|
||||||
AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x - 16, ti->y, 32, 16, maxz - z + 4, ti->z + z, false, 16, 0, -z);
|
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint fence_sw = GetFence(ti->tile, DIAGDIR_SW);
|
uint fence_sw = GetFence(ti->tile, DIAGDIR_SW);
|
||||||
uint fence_se = GetFence(ti->tile, DIAGDIR_SE);
|
uint fence_se = GetFence(ti->tile, DIAGDIR_SE);
|
||||||
|
|
||||||
if (fence_sw != 0 || fence_se != 0) {
|
if (fence_sw != 0 || fence_se != 0) {
|
||||||
int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
|
bounds.offset.x = 0;
|
||||||
|
bounds.offset.y = 0;
|
||||||
|
bounds.offset.z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
|
||||||
|
|
||||||
if (fence_sw != 0) {
|
if (fence_sw != 0) {
|
||||||
SpriteID sprite = _clear_land_fence_sprites[fence_sw - 1] + _fence_mod_by_tileh_sw[ti->tileh];
|
SpriteID sprite = _clear_land_fence_sprites[fence_sw - 1] + _fence_mod_by_tileh_sw[ti->tileh];
|
||||||
AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
|
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fence_se != 0) {
|
if (fence_se != 0) {
|
||||||
SpriteID sprite = _clear_land_fence_sprites[fence_se - 1] + _fence_mod_by_tileh_se[ti->tileh];
|
SpriteID sprite = _clear_land_fence_sprites[fence_se - 1] + _fence_mod_by_tileh_se[ti->tileh];
|
||||||
AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
|
AddSortableSpriteToDraw(sprite, PAL_NONE, *ti, bounds, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndSpriteCombine();
|
EndSpriteCombine();
|
||||||
|
|
|
@ -28,15 +28,30 @@ inline int CentreBounds(int min, int max, int size)
|
||||||
return (min + max - size + 1) / 2;
|
return (min + max - size + 1) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Coordinates of a point in 2D */
|
/** Coordinates of a point in 2D. */
|
||||||
struct Point {
|
template <typename T>
|
||||||
int x;
|
struct PointXy {
|
||||||
int y;
|
T x = 0; ///< X coordinate of point.
|
||||||
|
T y = 0; ///< Y coordinate of point.
|
||||||
|
|
||||||
constexpr Point() : x(0), y(0) {}
|
constexpr PointXy() = default;
|
||||||
constexpr Point(int x, int y) : x(x), y(y) {}
|
constexpr PointXy(T x, T y) : x(x), y(y) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Coordinates of a point in 3D. */
|
||||||
|
template <typename T>
|
||||||
|
struct PointXyz {
|
||||||
|
T x = 0; ///< X coordinate of point.
|
||||||
|
T y = 0; ///< Y coordinate of point.
|
||||||
|
T z = 0; ///< Z coordinate of point.
|
||||||
|
|
||||||
|
constexpr PointXyz() = default;
|
||||||
|
constexpr PointXyz(T x, T y, T z) : x(x), y(y), z(z) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Coordinates of a point in 2D */
|
||||||
|
using Point = PointXy<int>;
|
||||||
|
|
||||||
/** Dimensions (a width and height) of a rectangle in 2D */
|
/** Dimensions (a width and height) of a rectangle in 2D */
|
||||||
struct Dimension {
|
struct Dimension {
|
||||||
uint width;
|
uint width;
|
||||||
|
|
|
@ -992,9 +992,5 @@ void ReleaseDisasterVehicle(VehicleID vehicle)
|
||||||
|
|
||||||
void DisasterVehicle::UpdateDeltaXY()
|
void DisasterVehicle::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
this->x_offs = -1;
|
this->bounds = {{-1, -1, 0}, {2, 2, 5}, {}};
|
||||||
this->y_offs = -1;
|
|
||||||
this->x_extent = 2;
|
|
||||||
this->y_extent = 2;
|
|
||||||
this->z_extent = 5;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -619,11 +619,7 @@ bool EffectVehicle::Tick()
|
||||||
|
|
||||||
void EffectVehicle::UpdateDeltaXY()
|
void EffectVehicle::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
this->x_offs = 0;
|
this->bounds = {{}, {1, 1, 1}, {}};
|
||||||
this->y_offs = 0;
|
|
||||||
this->x_extent = 1;
|
|
||||||
this->y_extent = 1;
|
|
||||||
this->z_extent = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -248,27 +248,12 @@ static int GetPCPElevation(TileIndex tile, DiagDirection pcp_pos)
|
||||||
*/
|
*/
|
||||||
void DrawRailCatenaryOnTunnel(const TileInfo *ti)
|
void DrawRailCatenaryOnTunnel(const TileInfo *ti)
|
||||||
{
|
{
|
||||||
/* xmin, ymin, xmax + 1, ymax + 1 of BB */
|
|
||||||
static const int tunnel_wire_bb[4][4] = {
|
|
||||||
{ 0, 1, 16, 15 }, // NE
|
|
||||||
{ 1, 0, 15, 16 }, // SE
|
|
||||||
{ 0, 1, 16, 15 }, // SW
|
|
||||||
{ 1, 0, 15, 16 }, // NW
|
|
||||||
};
|
|
||||||
|
|
||||||
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
|
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
|
||||||
|
|
||||||
SpriteID wire_base = GetWireBase(ti->tile);
|
SpriteID wire_base = GetWireBase(ti->tile);
|
||||||
|
|
||||||
const SortableSpriteStruct *sss = &_rail_catenary_sprite_data_tunnel[dir];
|
const SortableSpriteStruct &sss = _rail_catenary_sprite_data_tunnel[dir];
|
||||||
const int *bb_data = tunnel_wire_bb[dir];
|
AddSortableSpriteToDraw(wire_base + sss.image_offset, PAL_NONE, ti->x, ti->y, GetTilePixelZ(ti->tile), sss, IsTransparencySet(TO_CATENARY));
|
||||||
AddSortableSpriteToDraw(
|
|
||||||
wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
|
||||||
bb_data[2] - sss->x_offset, bb_data[3] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset + 1,
|
|
||||||
GetTilePixelZ(ti->tile) + sss->z_offset,
|
|
||||||
IsTransparencySet(TO_CATENARY),
|
|
||||||
bb_data[0] - sss->x_offset, bb_data[1] - sss->y_offset, BB_Z_SEPARATOR - sss->z_offset
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -440,8 +425,8 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||||
continue; // No neighbour, go looking for a better position
|
continue; // No neighbour, go looking for a better position
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[temp], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE,
|
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[temp], PAL_NONE, x, y, elevation,
|
||||||
elevation, IsTransparencySet(TO_CATENARY), -1, -1);
|
{{-1, -1, 0}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {1, 1, 0}}, IsTransparencySet(TO_CATENARY));
|
||||||
|
|
||||||
break; // We already have drawn a pylon, bail out
|
break; // We already have drawn a pylon, bail out
|
||||||
}
|
}
|
||||||
|
@ -482,7 +467,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||||
|
|
||||||
assert(pcp_config != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that)
|
assert(pcp_config != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that)
|
||||||
assert(!IsSteepSlope(tileh[TS_HOME]));
|
assert(!IsSteepSlope(tileh[TS_HOME]));
|
||||||
const SortableSpriteStruct *sss = &_rail_catenary_sprite_data[_rail_wires[tileh_selector][t][pcp_config]];
|
const SortableSpriteStruct &sss = _rail_catenary_sprite_data[_rail_wires[tileh_selector][t][pcp_config]];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
|
* The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
|
||||||
|
@ -490,9 +475,8 @@ static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||||
* Also note that the result of GetSlopePixelZ() is very special for bridge-ramps, so we round the result up or
|
* Also note that the result of GetSlopePixelZ() is very special for bridge-ramps, so we round the result up or
|
||||||
* down to the nearest full height change.
|
* down to the nearest full height change.
|
||||||
*/
|
*/
|
||||||
AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
int z = (GetSlopePixelZ(ti->x + sss.origin.x, ti->y + sss.origin.y, true) + 4) / 8 * 8;
|
||||||
sss->x_size, sss->y_size, sss->z_size, (GetSlopePixelZ(ti->x + sss->x_offset, ti->y + sss->y_offset, true) + 4) / 8 * 8 + sss->z_offset,
|
AddSortableSpriteToDraw(wire_base + sss.image_offset, PAL_NONE, ti->x, ti->y, z, sss, IsTransparencySet(TO_CATENARY));
|
||||||
IsTransparencySet(TO_CATENARY));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,13 +514,12 @@ void DrawRailCatenaryOnBridge(const TileInfo *ti)
|
||||||
|
|
||||||
SpriteID wire_base = GetWireBase(end, TCX_ON_BRIDGE);
|
SpriteID wire_base = GetWireBase(end, TCX_ON_BRIDGE);
|
||||||
|
|
||||||
AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
AddSortableSpriteToDraw(wire_base + sss->image_offset, PAL_NONE, ti->x, ti->y, height, *sss, IsTransparencySet(TO_CATENARY));
|
||||||
sss->x_size, sss->y_size, sss->z_size, height + sss->z_offset,
|
|
||||||
IsTransparencySet(TO_CATENARY)
|
|
||||||
);
|
|
||||||
|
|
||||||
SpriteID pylon_base = GetPylonBase(end, TCX_ON_BRIDGE);
|
SpriteID pylon_base = GetPylonBase(end, TCX_ON_BRIDGE);
|
||||||
|
|
||||||
|
static constexpr SpriteBounds pylon_bounds{{-1, -1, 0}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {1, 1, 0}};
|
||||||
|
|
||||||
/* Finished with wires, draw pylons
|
/* Finished with wires, draw pylons
|
||||||
* every other tile needs a pylon on the northern end */
|
* every other tile needs a pylon on the northern end */
|
||||||
if (num % 2) {
|
if (num % 2) {
|
||||||
|
@ -545,7 +528,7 @@ void DrawRailCatenaryOnBridge(const TileInfo *ti)
|
||||||
if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) ppp_pos = ReverseDir(ppp_pos);
|
if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) ppp_pos = ReverseDir(ppp_pos);
|
||||||
uint x = ti->x + _x_pcp_offsets[pcp_pos] + _x_ppp_offsets[ppp_pos];
|
uint x = ti->x + _x_pcp_offsets[pcp_pos] + _x_ppp_offsets[ppp_pos];
|
||||||
uint y = ti->y + _y_pcp_offsets[pcp_pos] + _y_ppp_offsets[ppp_pos];
|
uint y = ti->y + _y_pcp_offsets[pcp_pos] + _y_ppp_offsets[ppp_pos];
|
||||||
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[ppp_pos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
|
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[ppp_pos], PAL_NONE, x, y, height, pylon_bounds, IsTransparencySet(TO_CATENARY));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need a pylon on the southern end of the bridge */
|
/* need a pylon on the southern end of the bridge */
|
||||||
|
@ -555,7 +538,7 @@ void DrawRailCatenaryOnBridge(const TileInfo *ti)
|
||||||
if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) ppp_pos = ReverseDir(ppp_pos);
|
if (HasBit(tlg, (axis == AXIS_X ? 0 : 1))) ppp_pos = ReverseDir(ppp_pos);
|
||||||
uint x = ti->x + _x_pcp_offsets[pcp_pos] + _x_ppp_offsets[ppp_pos];
|
uint x = ti->x + _x_pcp_offsets[pcp_pos] + _x_ppp_offsets[ppp_pos];
|
||||||
uint y = ti->y + _y_pcp_offsets[pcp_pos] + _y_ppp_offsets[ppp_pos];
|
uint y = ti->y + _y_pcp_offsets[pcp_pos] + _y_ppp_offsets[ppp_pos];
|
||||||
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[ppp_pos], PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, height, IsTransparencySet(TO_CATENARY), -1, -1);
|
AddSortableSpriteToDraw(pylon_base + _pylon_sprites[ppp_pos], PAL_NONE, x, y, height, pylon_bounds, IsTransparencySet(TO_CATENARY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,17 +552,12 @@ void DrawRailCatenary(const TileInfo *ti)
|
||||||
switch (GetTileType(ti->tile)) {
|
switch (GetTileType(ti->tile)) {
|
||||||
case MP_RAILWAY:
|
case MP_RAILWAY:
|
||||||
if (IsRailDepot(ti->tile)) {
|
if (IsRailDepot(ti->tile)) {
|
||||||
const SortableSpriteStruct *sss = &_rail_catenary_sprite_data_depot[GetRailDepotDirection(ti->tile)];
|
const SortableSpriteStruct &sss = _rail_catenary_sprite_data_depot[GetRailDepotDirection(ti->tile)];
|
||||||
|
|
||||||
SpriteID wire_base = GetWireBase(ti->tile);
|
SpriteID wire_base = GetWireBase(ti->tile);
|
||||||
|
|
||||||
/* This wire is not visible with the default depot sprites */
|
/* This wire is not visible with the default depot sprites */
|
||||||
AddSortableSpriteToDraw(
|
AddSortableSpriteToDraw(wire_base + sss.image_offset, PAL_NONE, ti->x, ti->y, GetTileMaxPixelZ(ti->tile), sss, IsTransparencySet(TO_CATENARY));
|
||||||
wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
|
||||||
sss->x_size, sss->y_size, sss->z_size,
|
|
||||||
GetTileMaxPixelZ(ti->tile) + sss->z_offset,
|
|
||||||
IsTransparencySet(TO_CATENARY)
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -103,14 +103,14 @@ void SpriteFontCache::ClearFontCache()
|
||||||
|
|
||||||
const Sprite *SpriteFontCache::GetGlyph(GlyphID key)
|
const Sprite *SpriteFontCache::GetGlyph(GlyphID key)
|
||||||
{
|
{
|
||||||
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH));
|
SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
|
||||||
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
||||||
return GetSprite(sprite, SpriteType::Font);
|
return GetSprite(sprite, SpriteType::Font);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint SpriteFontCache::GetGlyphWidth(GlyphID key)
|
uint SpriteFontCache::GetGlyphWidth(GlyphID key)
|
||||||
{
|
{
|
||||||
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH));
|
SpriteID sprite = static_cast<SpriteID>(key & ~SPRITE_GLYPH);
|
||||||
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
||||||
return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0;
|
return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ GlyphID SpriteFontCache::MapCharToGlyph(char32_t key, [[maybe_unused]] bool allo
|
||||||
assert(IsPrintable(key));
|
assert(IsPrintable(key));
|
||||||
SpriteID sprite = this->GetUnicodeGlyph(key);
|
SpriteID sprite = this->GetUnicodeGlyph(key);
|
||||||
if (sprite == 0) return 0;
|
if (sprite == 0) return 0;
|
||||||
return SPRITE_GLYPH | key;
|
return SPRITE_GLYPH | sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpriteFontCache::GetDrawGlyphShadow()
|
bool SpriteFontCache::GetDrawGlyphShadow()
|
||||||
|
|
|
@ -374,13 +374,7 @@ static void DrawTile_Industry(TileInfo *ti)
|
||||||
image = dits->building.sprite;
|
image = dits->building.sprite;
|
||||||
if (image != 0) {
|
if (image != 0) {
|
||||||
AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GetColourPalette(ind->random_colour)),
|
AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GetColourPalette(ind->random_colour)),
|
||||||
ti->x + dits->subtile_x,
|
*ti, *dits, IsTransparencySet(TO_INDUSTRIES));
|
||||||
ti->y + dits->subtile_y,
|
|
||||||
dits->width,
|
|
||||||
dits->height,
|
|
||||||
dits->dz,
|
|
||||||
ti->z,
|
|
||||||
IsTransparencySet(TO_INDUSTRIES));
|
|
||||||
|
|
||||||
if (IsTransparencySet(TO_INDUSTRIES)) return;
|
if (IsTransparencySet(TO_INDUSTRIES)) return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -450,9 +450,8 @@ void DrawFoundation(TileInfo *ti, Foundation f)
|
||||||
if (IsSteepSlope(ti->tileh)) {
|
if (IsSteepSlope(ti->tileh)) {
|
||||||
if (!IsNonContinuousFoundation(f)) {
|
if (!IsNonContinuousFoundation(f)) {
|
||||||
/* Lower part of foundation */
|
/* Lower part of foundation */
|
||||||
AddSortableSpriteToDraw(
|
static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
|
||||||
leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z
|
AddSortableSpriteToDraw(leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, *ti, bounds);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
|
Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
|
||||||
|
@ -462,24 +461,25 @@ void DrawFoundation(TileInfo *ti, Foundation f)
|
||||||
/* inclined foundation */
|
/* inclined foundation */
|
||||||
uint8_t inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
|
uint8_t inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
|
||||||
|
|
||||||
AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
|
SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
|
||||||
f == FOUNDATION_INCLINED_X ? TILE_SIZE : 1,
|
if (f == FOUNDATION_INCLINED_X) bounds.extent.x = TILE_SIZE;
|
||||||
f == FOUNDATION_INCLINED_Y ? TILE_SIZE : 1,
|
if (f == FOUNDATION_INCLINED_Y) bounds.extent.y = TILE_SIZE;
|
||||||
TILE_HEIGHT, ti->z
|
AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
|
||||||
);
|
|
||||||
OffsetGroundSprite(0, 0);
|
OffsetGroundSprite(0, 0);
|
||||||
} else if (IsLeveledFoundation(f)) {
|
} else if (IsLeveledFoundation(f)) {
|
||||||
AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z - TILE_HEIGHT);
|
static constexpr SpriteBounds bounds{{0, 0, -(int)TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
|
||||||
|
AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, *ti, bounds);
|
||||||
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
||||||
} else if (f == FOUNDATION_STEEP_LOWER) {
|
} else if (f == FOUNDATION_STEEP_LOWER) {
|
||||||
/* one corner raised */
|
/* one corner raised */
|
||||||
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
||||||
} else {
|
} else {
|
||||||
/* halftile foundation */
|
/* halftile foundation */
|
||||||
int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
|
int8_t x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
|
||||||
int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
|
int8_t y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
|
||||||
|
|
||||||
AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1, ti->z + TILE_HEIGHT);
|
SpriteBounds bounds{{x_bb, y_bb, TILE_HEIGHT}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
|
||||||
|
AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, *ti, bounds);
|
||||||
/* Reposition ground sprite back to original position after bounding box change above. This is similar to
|
/* Reposition ground sprite back to original position after bounding box change above. This is similar to
|
||||||
* RemapCoords() but without zoom scaling. */
|
* RemapCoords() but without zoom scaling. */
|
||||||
Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
|
Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
|
||||||
|
@ -488,15 +488,17 @@ void DrawFoundation(TileInfo *ti, Foundation f)
|
||||||
} else {
|
} else {
|
||||||
if (IsLeveledFoundation(f)) {
|
if (IsLeveledFoundation(f)) {
|
||||||
/* leveled foundation */
|
/* leveled foundation */
|
||||||
AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z);
|
static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
|
||||||
|
AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, *ti, bounds);
|
||||||
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
OffsetGroundSprite(0, -(int)TILE_HEIGHT);
|
||||||
} else if (IsNonContinuousFoundation(f)) {
|
} else if (IsNonContinuousFoundation(f)) {
|
||||||
/* halftile foundation */
|
/* halftile foundation */
|
||||||
Corner halftile_corner = GetHalftileFoundationCorner(f);
|
Corner halftile_corner = GetHalftileFoundationCorner(f);
|
||||||
int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
|
int8_t x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? TILE_SIZE / 2 : 0);
|
||||||
int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
|
int8_t y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? TILE_SIZE / 2 : 0);
|
||||||
|
|
||||||
AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1, ti->z);
|
SpriteBounds bounds{{x_bb, y_bb, 0}, {TILE_SIZE / 2, TILE_SIZE / 2, TILE_HEIGHT - 1}, {}};
|
||||||
|
AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, *ti, bounds);
|
||||||
/* Reposition ground sprite back to original position after bounding box change above. This is similar to
|
/* Reposition ground sprite back to original position after bounding box change above. This is similar to
|
||||||
* RemapCoords() but without zoom scaling. */
|
* RemapCoords() but without zoom scaling. */
|
||||||
Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
|
Point pt = {(y_bb - x_bb) * 2, y_bb + x_bb};
|
||||||
|
@ -511,17 +513,17 @@ void DrawFoundation(TileInfo *ti, Foundation f)
|
||||||
/* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
|
/* tile-slope = sloped along X/Y, foundation-slope = three corners raised */
|
||||||
spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
|
spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
|
||||||
}
|
}
|
||||||
AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1, ti->z);
|
static constexpr SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}};
|
||||||
|
AddSortableSpriteToDraw(spr, PAL_NONE, *ti, bounds);
|
||||||
OffsetGroundSprite(0, 0);
|
OffsetGroundSprite(0, 0);
|
||||||
} else {
|
} else {
|
||||||
/* inclined foundation */
|
/* inclined foundation */
|
||||||
uint8_t inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
|
uint8_t inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
|
||||||
|
|
||||||
AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y,
|
SpriteBounds bounds{{}, {1, 1, TILE_HEIGHT}, {}};
|
||||||
f == FOUNDATION_INCLINED_X ? TILE_SIZE : 1,
|
if (f == FOUNDATION_INCLINED_X) bounds.extent.x = TILE_SIZE;
|
||||||
f == FOUNDATION_INCLINED_Y ? TILE_SIZE : 1,
|
if (f == FOUNDATION_INCLINED_Y) bounds.extent.y = TILE_SIZE;
|
||||||
TILE_HEIGHT, ti->z
|
AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, *ti, bounds);
|
||||||
);
|
|
||||||
OffsetGroundSprite(0, 0);
|
OffsetGroundSprite(0, 0);
|
||||||
}
|
}
|
||||||
ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
|
ti->z += ApplyPixelFoundationToSlope(f, ti->tileh);
|
||||||
|
|
|
@ -105,8 +105,8 @@ static ChangeInfoResult RoadStopChangeInfo(uint first, uint last, int prop, Byte
|
||||||
AddStringForMapping(GRFStringID{buf.ReadWord()}, [rs = rs.get()](StringID str) { RoadStopClass::Get(rs->class_index)->name = str; });
|
AddStringForMapping(GRFStringID{buf.ReadWord()}, [rs = rs.get()](StringID str) { RoadStopClass::Get(rs->class_index)->name = str; });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0C: // The draw mode
|
case 0x0C: // The draw modes
|
||||||
rs->draw_mode = static_cast<RoadStopDrawMode>(buf.ReadByte());
|
rs->draw_mode = static_cast<RoadStopDrawModes>(buf.ReadByte());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0D: // Cargo types for random triggers
|
case 0x0D: // Cargo types for random triggers
|
||||||
|
|
|
@ -90,12 +90,12 @@ static ChangeInfoResult StationChangeInfo(uint first, uint last, int prop, ByteR
|
||||||
|
|
||||||
/* no relative bounding box support */
|
/* no relative bounding box support */
|
||||||
DrawTileSeqStruct &dtss = tmp_layout.emplace_back();
|
DrawTileSeqStruct &dtss = tmp_layout.emplace_back();
|
||||||
dtss.delta_x = delta_x;
|
dtss.origin.x = delta_x;
|
||||||
dtss.delta_y = buf.ReadByte();
|
dtss.origin.y = buf.ReadByte();
|
||||||
dtss.delta_z = buf.ReadByte();
|
dtss.origin.z = buf.ReadByte();
|
||||||
dtss.size_x = buf.ReadByte();
|
dtss.extent.x = buf.ReadByte();
|
||||||
dtss.size_y = buf.ReadByte();
|
dtss.extent.y = buf.ReadByte();
|
||||||
dtss.size_z = buf.ReadByte();
|
dtss.extent.z = buf.ReadByte();
|
||||||
|
|
||||||
ReadSpriteLayoutSprite(buf, false, true, false, GSF_STATIONS, &dtss.image);
|
ReadSpriteLayoutSprite(buf, false, true, false, GSF_STATIONS, &dtss.image);
|
||||||
/* On error, bail out immediately. Temporary GRF data was already freed */
|
/* On error, bail out immediately. Temporary GRF data was already freed */
|
||||||
|
|
|
@ -207,15 +207,15 @@ bool ReadSpriteLayout(ByteReader &buf, uint num_building_sprites, bool use_cur_s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq->delta_x = buf.ReadByte();
|
seq->origin.x = buf.ReadByte();
|
||||||
seq->delta_y = buf.ReadByte();
|
seq->origin.y = buf.ReadByte();
|
||||||
|
|
||||||
if (!no_z_position) seq->delta_z = buf.ReadByte();
|
if (!no_z_position) seq->origin.z = buf.ReadByte();
|
||||||
|
|
||||||
if (seq->IsParentSprite()) {
|
if (seq->IsParentSprite()) {
|
||||||
seq->size_x = buf.ReadByte();
|
seq->extent.x = buf.ReadByte();
|
||||||
seq->size_y = buf.ReadByte();
|
seq->extent.y = buf.ReadByte();
|
||||||
seq->size_z = buf.ReadByte();
|
seq->extent.z = buf.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadSpriteLayoutRegisters(buf, flags, seq->IsParentSprite(), dts, i + 1);
|
ReadSpriteLayoutRegisters(buf, flags, seq->IsParentSprite(), dts, i + 1);
|
||||||
|
|
|
@ -609,7 +609,7 @@ SpriteLayoutProcessor::SpriteLayoutProcessor(const NewGRFSpriteLayout &raw_layou
|
||||||
* Also include the groundsprite into the sequence for easier processing. */
|
* Also include the groundsprite into the sequence for easier processing. */
|
||||||
DrawTileSeqStruct © = this->result_seq.emplace_back();
|
DrawTileSeqStruct © = this->result_seq.emplace_back();
|
||||||
copy.image = this->raw_layout->ground;
|
copy.image = this->raw_layout->ground;
|
||||||
copy.delta_z = static_cast<int8_t>(0x80);
|
copy.origin.z = static_cast<int8_t>(0x80);
|
||||||
|
|
||||||
this->result_seq.insert(this->result_seq.end(), this->raw_layout->seq.begin(), this->raw_layout->seq.end());
|
this->result_seq.insert(this->result_seq.end(), this->raw_layout->seq.begin(), this->raw_layout->seq.end());
|
||||||
|
|
||||||
|
@ -692,13 +692,13 @@ void SpriteLayoutProcessor::ProcessRegisters(const ResolverObject &object, uint8
|
||||||
|
|
||||||
if (result.IsParentSprite()) {
|
if (result.IsParentSprite()) {
|
||||||
if (flags & TLF_BB_XY_OFFSET) {
|
if (flags & TLF_BB_XY_OFFSET) {
|
||||||
result.delta_x += object.GetRegister(regs->delta.parent[0]);
|
result.origin.x += object.GetRegister(regs->delta.parent[0]);
|
||||||
result.delta_y += object.GetRegister(regs->delta.parent[1]);
|
result.origin.y += object.GetRegister(regs->delta.parent[1]);
|
||||||
}
|
}
|
||||||
if (flags & TLF_BB_Z_OFFSET) result.delta_z += object.GetRegister(regs->delta.parent[2]);
|
if (flags & TLF_BB_Z_OFFSET) result.origin.z += object.GetRegister(regs->delta.parent[2]);
|
||||||
} else {
|
} else {
|
||||||
if (flags & TLF_CHILD_X_OFFSET) result.delta_x += object.GetRegister(regs->delta.child[0]);
|
if (flags & TLF_CHILD_X_OFFSET) result.origin.x += object.GetRegister(regs->delta.child[0]);
|
||||||
if (flags & TLF_CHILD_Y_OFFSET) result.delta_y += object.GetRegister(regs->delta.child[1]);
|
if (flags & TLF_CHILD_Y_OFFSET) result.origin.y += object.GetRegister(regs->delta.child[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,7 +298,7 @@ void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec,
|
||||||
|
|
||||||
RoadStopDrawModes draw_mode;
|
RoadStopDrawModes draw_mode;
|
||||||
if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
|
if (spec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
|
||||||
draw_mode = static_cast<RoadStopDrawMode>(object.GetRegister(0x100));
|
draw_mode = static_cast<RoadStopDrawModes>(object.GetRegister(0x100));
|
||||||
} else {
|
} else {
|
||||||
draw_mode = spec->draw_mode;
|
draw_mode = spec->draw_mode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,13 +476,7 @@ static void DrawTile_Object(TileInfo *ti)
|
||||||
|
|
||||||
if (!IsInvisibilitySet(TO_STRUCTURES)) {
|
if (!IsInvisibilitySet(TO_STRUCTURES)) {
|
||||||
for (const DrawTileSeqStruct &dtss : dts->GetSequence()) {
|
for (const DrawTileSeqStruct &dtss : dts->GetSequence()) {
|
||||||
AddSortableSpriteToDraw(
|
AddSortableSpriteToDraw(dtss.image.sprite, palette, *ti, dtss, IsTransparencySet(TO_STRUCTURES));
|
||||||
dtss.image.sprite, palette,
|
|
||||||
ti->x + dtss.delta_x, ti->y + dtss.delta_y,
|
|
||||||
dtss.size_x, dtss.size_y,
|
|
||||||
dtss.size_z, ti->z + dtss.delta_z,
|
|
||||||
IsTransparencySet(TO_STRUCTURES)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1899,7 +1899,7 @@ static void DrawSingleSignal(TileIndex tile, const RailTypeInfo *rti, Track trac
|
||||||
sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0);
|
sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
|
AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, GetSaveSlopeZ(x, y, track), {{}, {1, 1, BB_HEIGHT_UNDER_BRIDGE}, {}});
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t _drawtile_track_palette;
|
static uint32_t _drawtile_track_palette;
|
||||||
|
@ -1907,12 +1907,11 @@ static uint32_t _drawtile_track_palette;
|
||||||
|
|
||||||
|
|
||||||
/** Offsets for drawing fences */
|
/** Offsets for drawing fences */
|
||||||
struct FenceOffset {
|
struct FenceOffset : SpriteBounds {
|
||||||
Corner height_ref; //!< Corner to use height offset from.
|
Corner height_ref; ///< Corner to use height offset from.
|
||||||
int x_offs; //!< Bounding box X offset.
|
|
||||||
int y_offs; //!< Bounding box Y offset.
|
constexpr FenceOffset(Corner height_ref, int8_t origin_x, int8_t origin_y, uint8_t extent_x, uint8_t extent_y) :
|
||||||
int x_size; //!< Bounding box X size.
|
SpriteBounds({origin_x, origin_y, 0}, {extent_x, extent_y, 4}, {}), height_ref(height_ref) {}
|
||||||
int y_size; //!< Bounding box Y size.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Offsets for drawing fences */
|
/** Offsets for drawing fences */
|
||||||
|
@ -1948,12 +1947,7 @@ static void DrawTrackFence(const TileInfo *ti, SpriteID base_image, uint num_spr
|
||||||
if (_fence_offsets[rfo].height_ref != CORNER_INVALID) {
|
if (_fence_offsets[rfo].height_ref != CORNER_INVALID) {
|
||||||
z += GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), _fence_offsets[rfo].height_ref);
|
z += GetSlopePixelZInCorner(RemoveHalftileSlope(ti->tileh), _fence_offsets[rfo].height_ref);
|
||||||
}
|
}
|
||||||
AddSortableSpriteToDraw(base_image + (rfo % num_sprites), _drawtile_track_palette,
|
AddSortableSpriteToDraw(base_image + (rfo % num_sprites), _drawtile_track_palette, ti->x, ti->y, z, _fence_offsets[rfo]);
|
||||||
ti->x + _fence_offsets[rfo].x_offs,
|
|
||||||
ti->y + _fence_offsets[rfo].y_offs,
|
|
||||||
_fence_offsets[rfo].x_size,
|
|
||||||
_fence_offsets[rfo].y_size,
|
|
||||||
4, z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1418,7 +1418,7 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
|
||||||
* For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
|
* For tiles with OWNER_TOWN or OWNER_NONE, recolour CC to grey as a neutral colour. */
|
||||||
Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
|
Owner owner = GetRoadOwner(ti->tile, GetRoadTramType(rt));
|
||||||
PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
|
PaletteID pal = (owner == OWNER_NONE || owner == OWNER_TOWN ? GetColourPalette(COLOUR_GREY) : GetCompanyPalette(owner));
|
||||||
int z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
|
uint8_t z_wires = (ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT) + BB_HEIGHT_UNDER_BRIDGE;
|
||||||
if (back != 0) {
|
if (back != 0) {
|
||||||
/* The "back" sprite contains the west, north and east pillars.
|
/* The "back" sprite contains the west, north and east pillars.
|
||||||
* We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
|
* We cut the sprite at 3/8 of the west/east edges to create 3 sprites.
|
||||||
|
@ -1427,13 +1427,16 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb)
|
||||||
static const SubSprite west = { -INF, -INF, -12, INF };
|
static const SubSprite west = { -INF, -INF, -12, INF };
|
||||||
static const SubSprite north = { -12, -INF, 12, INF };
|
static const SubSprite north = { -12, -INF, 12, INF };
|
||||||
static const SubSprite east = { 12, -INF, INF, INF };
|
static const SubSprite east = { 12, -INF, INF, INF };
|
||||||
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 16, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 15, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_W), &west);
|
int8_t west_z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
|
||||||
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 1, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, GetSlopePixelZInCorner(ti->tileh, CORNER_N), &north);
|
int8_t north_z = GetSlopePixelZInCorner(ti->tileh, CORNER_N);
|
||||||
AddSortableSpriteToDraw(back, pal, ti->x, ti->y, 1, 16, z_wires, ti->z, IsTransparencySet(TO_CATENARY), 0, 15, GetSlopePixelZInCorner(ti->tileh, CORNER_E), &east);
|
int8_t east_z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
|
||||||
|
AddSortableSpriteToDraw(back, pal, *ti, {{15, 0, west_z}, {1, 1, z_wires}, {-15, 0, static_cast<int8_t>(-west_z)}}, IsTransparencySet(TO_CATENARY), &west);
|
||||||
|
AddSortableSpriteToDraw(back, pal, *ti, {{0, 0, north_z}, {1, 1, z_wires}, {0, 0, static_cast<int8_t>(-north_z)}}, IsTransparencySet(TO_CATENARY), &north);
|
||||||
|
AddSortableSpriteToDraw(back, pal, *ti, {{0, 15, east_z}, {1, 1, z_wires}, {0, -15, static_cast<int8_t>(-east_z)}}, IsTransparencySet(TO_CATENARY), &east);
|
||||||
}
|
}
|
||||||
if (front != 0) {
|
if (front != 0) {
|
||||||
/* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
|
/* Draw the "front" sprite (containing south pillar and wires) at a Z height that is both above the vehicles and above the "back" pillars. */
|
||||||
AddSortableSpriteToDraw(front, pal, ti->x, ti->y, 16, 16, z_wires + 1, ti->z, IsTransparencySet(TO_CATENARY), 0, 0, z_wires);
|
AddSortableSpriteToDraw(front, pal, *ti, {{0, 0, static_cast<int8_t>(z_wires)}, {TILE_SIZE, TILE_SIZE, 1}, {0, 0, static_cast<int8_t>(-z_wires)}}, IsTransparencySet(TO_CATENARY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1487,13 +1490,13 @@ void DrawRoadCatenary(const TileInfo *ti)
|
||||||
* @param h the height of the sprite to draw
|
* @param h the height of the sprite to draw
|
||||||
* @param transparent whether the sprite should be transparent (used for roadside trees)
|
* @param transparent whether the sprite should be transparent (used for roadside trees)
|
||||||
*/
|
*/
|
||||||
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h, bool transparent)
|
static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int8_t dx, int8_t dy, uint8_t h, bool transparent)
|
||||||
{
|
{
|
||||||
int x = ti->x | dx;
|
int x = ti->x | dx;
|
||||||
int y = ti->y | dy;
|
int y = ti->y | dy;
|
||||||
int z = ti->z;
|
int z = ti->z;
|
||||||
if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
|
if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
|
||||||
AddSortableSpriteToDraw(img, PAL_NONE, x, y, 2, 2, h, z, transparent);
|
AddSortableSpriteToDraw(img, PAL_NONE, ti->x, ti->y, z, {{dx, dy, 0}, {2, 2, h}, {}}, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -405,29 +405,56 @@ void RoadVehicle::MarkDirty()
|
||||||
|
|
||||||
void RoadVehicle::UpdateDeltaXY()
|
void RoadVehicle::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
static const int8_t _delta_xy_table[8][10] = {
|
/* Set common defaults. */
|
||||||
/* y_extent, x_extent, y_offs, x_offs, y_bb_offs, x_bb_offs, y_extent_shorten, x_extent_shorten, y_bb_offs_shorten, x_bb_offs_shorten */
|
this->bounds = {{-1, -1, 0}, {3, 3, 6}, {}};
|
||||||
{3, 3, -1, -1, 0, 0, -1, -1, -1, -1}, // N
|
|
||||||
{3, 7, -1, -3, 0, -1, 0, -1, 0, 0}, // NE
|
if (!IsDiagonalDirection(this->direction)) {
|
||||||
{3, 3, -1, -1, 0, 0, 1, -1, 1, -1}, // E
|
static const Point _sign_table[] = {
|
||||||
{7, 3, -3, -1, -1, 0, 0, 0, 1, 0}, // SE
|
/* x, y */
|
||||||
{3, 3, -1, -1, 0, 0, 1, 1, 1, 1}, // S
|
{-1, -1}, // DIR_N
|
||||||
{3, 7, -1, -3, 0, -1, 0, 0, 0, 1}, // SW
|
{-1, 1}, // DIR_E
|
||||||
{3, 3, -1, -1, 0, 0, -1, 1, -1, 1}, // W
|
{ 1, 1}, // DIR_S
|
||||||
{7, 3, -3, -1, -1, 0, -1, 0, 0, 0}, // NW
|
{ 1, -1}, // DIR_W
|
||||||
};
|
};
|
||||||
|
|
||||||
int shorten = VEHICLE_LENGTH - this->gcache.cached_veh_length;
|
int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2;
|
||||||
if (!IsDiagonalDirection(this->direction)) shorten >>= 1;
|
|
||||||
|
|
||||||
const int8_t *bb = _delta_xy_table[this->direction];
|
/* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
|
||||||
this->x_bb_offs = bb[5] + bb[9] * shorten;
|
this->bounds.offset.x -= half_shorten * _sign_table[DirToDiagDir(this->direction)].x;
|
||||||
this->y_bb_offs = bb[4] + bb[8] * shorten;;
|
this->bounds.offset.y -= half_shorten * _sign_table[DirToDiagDir(this->direction)].y;
|
||||||
this->x_offs = bb[3];
|
} else {
|
||||||
this->y_offs = bb[2];
|
/* Unlike trains, road vehicles do not have their offsets moved to the centre. */
|
||||||
this->x_extent = bb[1] + bb[7] * shorten;
|
switch (this->direction) {
|
||||||
this->y_extent = bb[0] + bb[6] * shorten;
|
/* Shorten southern corner of the bounding box according the vehicle length. */
|
||||||
this->z_extent = 6;
|
case DIR_NE:
|
||||||
|
this->bounds.origin.x = -3;
|
||||||
|
this->bounds.extent.x = this->gcache.cached_veh_length;
|
||||||
|
this->bounds.offset.x = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIR_NW:
|
||||||
|
this->bounds.origin.y = -3;
|
||||||
|
this->bounds.extent.y = this->gcache.cached_veh_length;
|
||||||
|
this->bounds.offset.y = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Move northern corner of the bounding box down according to vehicle length. */
|
||||||
|
case DIR_SW:
|
||||||
|
this->bounds.origin.x = -3 + (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
|
this->bounds.extent.x = this->gcache.cached_veh_length;
|
||||||
|
this->bounds.offset.x = 1 - (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIR_SE:
|
||||||
|
this->bounds.origin.y = -3 + (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
|
this->bounds.extent.y = this->gcache.cached_veh_length;
|
||||||
|
this->bounds.offset.y = 1 - (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -76,7 +76,7 @@ ScriptController::ScriptController(::CompanyID company) :
|
||||||
|
|
||||||
/* static */ uint ScriptController::GetTick()
|
/* static */ uint ScriptController::GetTick()
|
||||||
{
|
{
|
||||||
return ScriptObject::GetActiveInstance().GetController()->ticks;
|
return ScriptObject::GetActiveInstance().GetController().ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ int ScriptController::GetOpsTillSuspend()
|
/* static */ int ScriptController::GetOpsTillSuspend()
|
||||||
|
@ -96,9 +96,9 @@ ScriptController::ScriptController(::CompanyID company) :
|
||||||
|
|
||||||
/* static */ HSQOBJECT ScriptController::Import(const std::string &library, const std::string &class_name, int version)
|
/* static */ HSQOBJECT ScriptController::Import(const std::string &library, const std::string &class_name, int version)
|
||||||
{
|
{
|
||||||
ScriptController *controller = ScriptObject::GetActiveInstance().GetController();
|
ScriptController &controller = ScriptObject::GetActiveInstance().GetController();
|
||||||
Squirrel *engine = ScriptObject::GetActiveInstance().engine;
|
Squirrel &engine = *ScriptObject::GetActiveInstance().engine;
|
||||||
HSQUIRRELVM vm = engine->GetVM();
|
HSQUIRRELVM vm = engine.GetVM();
|
||||||
|
|
||||||
ScriptInfo *lib = ScriptObject::GetActiveInstance().FindLibrary(library, version);
|
ScriptInfo *lib = ScriptObject::GetActiveInstance().FindLibrary(library, version);
|
||||||
if (lib == nullptr) {
|
if (lib == nullptr) {
|
||||||
|
@ -114,11 +114,11 @@ ScriptController::ScriptController(::CompanyID company) :
|
||||||
|
|
||||||
std::string fake_class;
|
std::string fake_class;
|
||||||
|
|
||||||
LoadedLibraryList::iterator it = controller->loaded_library.find(library_name);
|
LoadedLibraryList::iterator it = controller.loaded_library.find(library_name);
|
||||||
if (it != controller->loaded_library.end()) {
|
if (it != controller.loaded_library.end()) {
|
||||||
fake_class = (*it).second;
|
fake_class = (*it).second;
|
||||||
} else {
|
} else {
|
||||||
int next_number = ++controller->loaded_library_count;
|
int next_number = ++controller.loaded_library_count;
|
||||||
|
|
||||||
/* Create a new fake internal name */
|
/* Create a new fake internal name */
|
||||||
fake_class = fmt::format("_internalNA{}", next_number);
|
fake_class = fmt::format("_internalNA{}", next_number);
|
||||||
|
@ -128,14 +128,14 @@ ScriptController::ScriptController(::CompanyID company) :
|
||||||
sq_pushstring(vm, fake_class);
|
sq_pushstring(vm, fake_class);
|
||||||
sq_newclass(vm, SQFalse);
|
sq_newclass(vm, SQFalse);
|
||||||
/* Load the library */
|
/* Load the library */
|
||||||
if (!engine->LoadScript(vm, lib->GetMainScript(), false)) {
|
if (!engine.LoadScript(vm, lib->GetMainScript(), false)) {
|
||||||
throw sq_throwerror(vm, fmt::format("there was a compile error when importing '{}' version {}", library, version));
|
throw sq_throwerror(vm, fmt::format("there was a compile error when importing '{}' version {}", library, version));
|
||||||
}
|
}
|
||||||
/* Create the fake class */
|
/* Create the fake class */
|
||||||
sq_newslot(vm, -3, SQFalse);
|
sq_newslot(vm, -3, SQFalse);
|
||||||
sq_pop(vm, 1);
|
sq_pop(vm, 1);
|
||||||
|
|
||||||
controller->loaded_library[library_name] = fake_class;
|
controller.loaded_library[library_name] = fake_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the real class inside the fake class (like 'sets.Vector') */
|
/* Find the real class inside the fake class (like 'sets.Vector') */
|
||||||
|
|
|
@ -45,7 +45,7 @@ void SimpleCountedObject::Release()
|
||||||
* Get the storage associated with the current ScriptInstance.
|
* Get the storage associated with the current ScriptInstance.
|
||||||
* @return The storage.
|
* @return The storage.
|
||||||
*/
|
*/
|
||||||
static ScriptStorage *GetStorage()
|
static ScriptStorage &GetStorage()
|
||||||
{
|
{
|
||||||
return ScriptObject::GetActiveInstance().GetStorage();
|
return ScriptObject::GetActiveInstance().GetStorage();
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
|
ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
|
||||||
: AutoRestoreBackup(GetStorage()->allow_do_command, false)
|
: AutoRestoreBackup(GetStorage().allow_do_command, false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/* static */ ScriptInstance &ScriptObject::GetActiveInstance()
|
/* static */ ScriptInstance &ScriptObject::GetActiveInstance()
|
||||||
|
@ -78,181 +78,181 @@ ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
|
||||||
/* static */ void ScriptObject::SetDoCommandDelay(uint ticks)
|
/* static */ void ScriptObject::SetDoCommandDelay(uint ticks)
|
||||||
{
|
{
|
||||||
assert(ticks > 0);
|
assert(ticks > 0);
|
||||||
GetStorage()->delay = ticks;
|
GetStorage().delay = ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ uint ScriptObject::GetDoCommandDelay()
|
/* static */ uint ScriptObject::GetDoCommandDelay()
|
||||||
{
|
{
|
||||||
return GetStorage()->delay;
|
return GetStorage().delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetDoCommandMode(ScriptModeProc *proc, ScriptObject *instance)
|
/* static */ void ScriptObject::SetDoCommandMode(ScriptModeProc *proc, ScriptObject *instance)
|
||||||
{
|
{
|
||||||
GetStorage()->mode = proc;
|
GetStorage().mode = proc;
|
||||||
GetStorage()->mode_instance = instance;
|
GetStorage().mode_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptModeProc *ScriptObject::GetDoCommandMode()
|
/* static */ ScriptModeProc *ScriptObject::GetDoCommandMode()
|
||||||
{
|
{
|
||||||
return GetStorage()->mode;
|
return GetStorage().mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptObject *ScriptObject::GetDoCommandModeInstance()
|
/* static */ ScriptObject *ScriptObject::GetDoCommandModeInstance()
|
||||||
{
|
{
|
||||||
return GetStorage()->mode_instance;
|
return GetStorage().mode_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetDoCommandAsyncMode(ScriptAsyncModeProc *proc, ScriptObject *instance)
|
/* static */ void ScriptObject::SetDoCommandAsyncMode(ScriptAsyncModeProc *proc, ScriptObject *instance)
|
||||||
{
|
{
|
||||||
GetStorage()->async_mode = proc;
|
GetStorage().async_mode = proc;
|
||||||
GetStorage()->async_mode_instance = instance;
|
GetStorage().async_mode_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptAsyncModeProc *ScriptObject::GetDoCommandAsyncMode()
|
/* static */ ScriptAsyncModeProc *ScriptObject::GetDoCommandAsyncMode()
|
||||||
{
|
{
|
||||||
return GetStorage()->async_mode;
|
return GetStorage().async_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptObject *ScriptObject::GetDoCommandAsyncModeInstance()
|
/* static */ ScriptObject *ScriptObject::GetDoCommandAsyncModeInstance()
|
||||||
{
|
{
|
||||||
return GetStorage()->async_mode_instance;
|
return GetStorage().async_mode_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd)
|
/* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd)
|
||||||
{
|
{
|
||||||
ScriptStorage *s = GetStorage();
|
ScriptStorage &s = GetStorage();
|
||||||
Debug(script, 6, "SetLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data));
|
Debug(script, 6, "SetLastCommand company={:02d} cmd={} data={}", s.root_company, cmd, FormatArrayAsHex(data));
|
||||||
s->last_data = data;
|
s.last_data = data;
|
||||||
s->last_cmd = cmd;
|
s.last_cmd = cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptObject::CheckLastCommand(const CommandDataBuffer &data, Commands cmd)
|
/* static */ bool ScriptObject::CheckLastCommand(const CommandDataBuffer &data, Commands cmd)
|
||||||
{
|
{
|
||||||
ScriptStorage *s = GetStorage();
|
ScriptStorage &s = GetStorage();
|
||||||
Debug(script, 6, "CheckLastCommand company={:02d} cmd={} data={}", s->root_company, cmd, FormatArrayAsHex(data));
|
Debug(script, 6, "CheckLastCommand company={:02d} cmd={} data={}", s.root_company, cmd, FormatArrayAsHex(data));
|
||||||
if (s->last_cmd != cmd) return false;
|
if (s.last_cmd != cmd) return false;
|
||||||
if (s->last_data != data) return false;
|
if (s.last_data != data) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetDoCommandCosts(Money value)
|
/* static */ void ScriptObject::SetDoCommandCosts(Money value)
|
||||||
{
|
{
|
||||||
GetStorage()->costs = CommandCost(INVALID_EXPENSES, value); // Expense type is never read.
|
GetStorage().costs = CommandCost(INVALID_EXPENSES, value); // Expense type is never read.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::IncreaseDoCommandCosts(Money value)
|
/* static */ void ScriptObject::IncreaseDoCommandCosts(Money value)
|
||||||
{
|
{
|
||||||
GetStorage()->costs.AddCost(value);
|
GetStorage().costs.AddCost(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Money ScriptObject::GetDoCommandCosts()
|
/* static */ Money ScriptObject::GetDoCommandCosts()
|
||||||
{
|
{
|
||||||
return GetStorage()->costs.GetCost();
|
return GetStorage().costs.GetCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetLastError(ScriptErrorType last_error)
|
/* static */ void ScriptObject::SetLastError(ScriptErrorType last_error)
|
||||||
{
|
{
|
||||||
GetStorage()->last_error = last_error;
|
GetStorage().last_error = last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptErrorType ScriptObject::GetLastError()
|
/* static */ ScriptErrorType ScriptObject::GetLastError()
|
||||||
{
|
{
|
||||||
return GetStorage()->last_error;
|
return GetStorage().last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetLastCost(Money last_cost)
|
/* static */ void ScriptObject::SetLastCost(Money last_cost)
|
||||||
{
|
{
|
||||||
GetStorage()->last_cost = last_cost;
|
GetStorage().last_cost = last_cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Money ScriptObject::GetLastCost()
|
/* static */ Money ScriptObject::GetLastCost()
|
||||||
{
|
{
|
||||||
return GetStorage()->last_cost;
|
return GetStorage().last_cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetRoadType(RoadType road_type)
|
/* static */ void ScriptObject::SetRoadType(RoadType road_type)
|
||||||
{
|
{
|
||||||
GetStorage()->road_type = road_type;
|
GetStorage().road_type = road_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ RoadType ScriptObject::GetRoadType()
|
/* static */ RoadType ScriptObject::GetRoadType()
|
||||||
{
|
{
|
||||||
return GetStorage()->road_type;
|
return GetStorage().road_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetRailType(RailType rail_type)
|
/* static */ void ScriptObject::SetRailType(RailType rail_type)
|
||||||
{
|
{
|
||||||
GetStorage()->rail_type = rail_type;
|
GetStorage().rail_type = rail_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ RailType ScriptObject::GetRailType()
|
/* static */ RailType ScriptObject::GetRailType()
|
||||||
{
|
{
|
||||||
return GetStorage()->rail_type;
|
return GetStorage().rail_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetLastCommandRes(bool res)
|
/* static */ void ScriptObject::SetLastCommandRes(bool res)
|
||||||
{
|
{
|
||||||
GetStorage()->last_command_res = res;
|
GetStorage().last_command_res = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptObject::GetLastCommandRes()
|
/* static */ bool ScriptObject::GetLastCommandRes()
|
||||||
{
|
{
|
||||||
return GetStorage()->last_command_res;
|
return GetStorage().last_command_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetLastCommandResData(CommandDataBuffer data)
|
/* static */ void ScriptObject::SetLastCommandResData(CommandDataBuffer data)
|
||||||
{
|
{
|
||||||
GetStorage()->last_cmd_ret = std::move(data);
|
GetStorage().last_cmd_ret = std::move(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ const CommandDataBuffer &ScriptObject::GetLastCommandResData()
|
/* static */ const CommandDataBuffer &ScriptObject::GetLastCommandResData()
|
||||||
{
|
{
|
||||||
return GetStorage()->last_cmd_ret;
|
return GetStorage().last_cmd_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetCompany(::CompanyID company)
|
/* static */ void ScriptObject::SetCompany(::CompanyID company)
|
||||||
{
|
{
|
||||||
if (GetStorage()->root_company == INVALID_OWNER) GetStorage()->root_company = company;
|
if (GetStorage().root_company == INVALID_OWNER) GetStorage().root_company = company;
|
||||||
GetStorage()->company = company;
|
GetStorage().company = company;
|
||||||
|
|
||||||
_current_company = company;
|
_current_company = company;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ::CompanyID ScriptObject::GetCompany()
|
/* static */ ::CompanyID ScriptObject::GetCompany()
|
||||||
{
|
{
|
||||||
return GetStorage()->company;
|
return GetStorage().company;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ::CompanyID ScriptObject::GetRootCompany()
|
/* static */ ::CompanyID ScriptObject::GetRootCompany()
|
||||||
{
|
{
|
||||||
return GetStorage()->root_company;
|
return GetStorage().root_company;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptObject::CanSuspend()
|
/* static */ bool ScriptObject::CanSuspend()
|
||||||
{
|
{
|
||||||
Squirrel *squirrel = ScriptObject::GetActiveInstance().engine;
|
Squirrel *squirrel = ScriptObject::GetActiveInstance().engine;
|
||||||
return GetStorage()->allow_do_command && squirrel->CanSuspend();
|
return GetStorage().allow_do_command && squirrel->CanSuspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptEventQueue &ScriptObject::GetEventQueue()
|
/* static */ ScriptEventQueue &ScriptObject::GetEventQueue()
|
||||||
{
|
{
|
||||||
return GetStorage()->event_queue;
|
return GetStorage().event_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ ScriptLogTypes::LogData &ScriptObject::GetLogData()
|
/* static */ ScriptLogTypes::LogData &ScriptObject::GetLogData()
|
||||||
{
|
{
|
||||||
return GetStorage()->log_data;
|
return GetStorage().log_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ScriptObject::SetCallbackVariable(int index, int value)
|
/* static */ void ScriptObject::SetCallbackVariable(int index, int value)
|
||||||
{
|
{
|
||||||
if (static_cast<size_t>(index) >= GetStorage()->callback_value.size()) GetStorage()->callback_value.resize(index + 1);
|
if (static_cast<size_t>(index) >= GetStorage().callback_value.size()) GetStorage().callback_value.resize(index + 1);
|
||||||
GetStorage()->callback_value[index] = value;
|
GetStorage().callback_value[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ int ScriptObject::GetCallbackVariable(int index)
|
/* static */ int ScriptObject::GetCallbackVariable(int index)
|
||||||
{
|
{
|
||||||
return GetStorage()->callback_value[index];
|
return GetStorage().callback_value[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ CommandCallbackData *ScriptObject::GetDoCommandCallback()
|
/* static */ CommandCallbackData *ScriptObject::GetDoCommandCallback()
|
||||||
|
@ -310,8 +310,8 @@ ScriptObject::DisableDoCommandScope::DisableDoCommandScope()
|
||||||
IncreaseDoCommandCosts(res.GetCost());
|
IncreaseDoCommandCosts(res.GetCost());
|
||||||
if (!_generating_world) {
|
if (!_generating_world) {
|
||||||
/* Charge a nominal fee for asynchronously executed commands */
|
/* Charge a nominal fee for asynchronously executed commands */
|
||||||
Squirrel *engine = ScriptObject::GetActiveInstance().engine;
|
Squirrel &engine = *ScriptObject::GetActiveInstance().engine;
|
||||||
Squirrel::DecreaseOps(engine->GetVM(), 100);
|
Squirrel::DecreaseOps(engine.GetVM(), 100);
|
||||||
}
|
}
|
||||||
if (callback != nullptr) {
|
if (callback != nullptr) {
|
||||||
/* Insert return value into to stack and throw a control code that
|
/* Insert return value into to stack and throw a control code that
|
||||||
|
|
|
@ -100,7 +100,7 @@ void ScriptInstance::Initialize(const std::string &main_script, const std::strin
|
||||||
|
|
||||||
void ScriptInstance::RegisterAPI()
|
void ScriptInstance::RegisterAPI()
|
||||||
{
|
{
|
||||||
squirrel_register_std(this->engine);
|
squirrel_register_std(*this->engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptInstance::LoadCompatibilityScript(std::string_view api_version, Subdirectory dir)
|
bool ScriptInstance::LoadCompatibilityScript(std::string_view api_version, Subdirectory dir)
|
||||||
|
@ -318,9 +318,10 @@ void ScriptInstance::CollectGarbage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScriptStorage *ScriptInstance::GetStorage()
|
ScriptStorage &ScriptInstance::GetStorage()
|
||||||
{
|
{
|
||||||
return this->storage;
|
assert(this->storage != nullptr);
|
||||||
|
return *this->storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptLogTypes::LogData &ScriptInstance::GetLogData()
|
ScriptLogTypes::LogData &ScriptInstance::GetLogData()
|
||||||
|
|
|
@ -91,7 +91,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Get the storage of this script.
|
* Get the storage of this script.
|
||||||
*/
|
*/
|
||||||
class ScriptStorage *GetStorage();
|
class ScriptStorage &GetStorage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the log pointer of this script.
|
* Get the log pointer of this script.
|
||||||
|
@ -146,7 +146,11 @@ public:
|
||||||
/**
|
/**
|
||||||
* Get the controller attached to the instance.
|
* Get the controller attached to the instance.
|
||||||
*/
|
*/
|
||||||
class ScriptController *GetController() { return controller; }
|
class ScriptController &GetController()
|
||||||
|
{
|
||||||
|
assert(this->controller != nullptr);
|
||||||
|
return *this->controller;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the "this script died" value
|
* Return the "this script died" value
|
||||||
|
|
|
@ -536,7 +536,7 @@ void Squirrel::Initialize()
|
||||||
sq_setforeignptr(this->vm, this);
|
sq_setforeignptr(this->vm, this);
|
||||||
|
|
||||||
sq_pushroottable(this->vm);
|
sq_pushroottable(this->vm);
|
||||||
squirrel_register_global_std(this);
|
squirrel_register_global_std(*this);
|
||||||
|
|
||||||
/* Set consts table as delegate of root table, so consts/enums defined via require() are accessible */
|
/* Set consts table as delegate of root table, so consts/enums defined via require() are accessible */
|
||||||
sq_pushconsttable(this->vm);
|
sq_pushconsttable(this->vm);
|
||||||
|
|
|
@ -82,20 +82,20 @@ SQInteger SquirrelStd::notifyallexceptions(HSQUIRRELVM vm)
|
||||||
return SQ_ERROR;
|
return SQ_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void squirrel_register_global_std(Squirrel *engine)
|
void squirrel_register_global_std(Squirrel &engine)
|
||||||
{
|
{
|
||||||
/* We don't use squirrel_helper here, as we want to register to the global
|
/* We don't use squirrel_helper here, as we want to register to the global
|
||||||
* scope and not to a class. */
|
* scope and not to a class. */
|
||||||
engine->AddMethod("require", &SquirrelStd::require, ".s");
|
engine.AddMethod("require", &SquirrelStd::require, ".s");
|
||||||
engine->AddMethod("notifyallexceptions", &SquirrelStd::notifyallexceptions, ".b");
|
engine.AddMethod("notifyallexceptions", &SquirrelStd::notifyallexceptions, ".b");
|
||||||
}
|
}
|
||||||
|
|
||||||
void squirrel_register_std(Squirrel *engine)
|
void squirrel_register_std(Squirrel &engine)
|
||||||
{
|
{
|
||||||
/* We don't use squirrel_helper here, as we want to register to the global
|
/* We don't use squirrel_helper here, as we want to register to the global
|
||||||
* scope and not to a class. */
|
* scope and not to a class. */
|
||||||
engine->AddMethod("min", &SquirrelStd::min, ".ii");
|
engine.AddMethod("min", &SquirrelStd::min, ".ii");
|
||||||
engine->AddMethod("max", &SquirrelStd::max, ".ii");
|
engine.AddMethod("max", &SquirrelStd::max, ".ii");
|
||||||
|
|
||||||
sqstd_register_mathlib(engine->GetVM());
|
sqstd_register_mathlib(engine.GetVM());
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* Register all standard functions we want to give to a script.
|
* Register all standard functions we want to give to a script.
|
||||||
*/
|
*/
|
||||||
void squirrel_register_std(Squirrel *engine);
|
void squirrel_register_std(Squirrel &engine);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all standard functions that are available on first startup.
|
* Register all standard functions that are available on first startup.
|
||||||
* @note this set is very limited, and is only meant to load other scripts and things like that.
|
* @note this set is very limited, and is only meant to load other scripts and things like that.
|
||||||
*/
|
*/
|
||||||
void squirrel_register_global_std(Squirrel *engine);
|
void squirrel_register_global_std(Squirrel &engine);
|
||||||
|
|
||||||
#endif /* SQUIRREL_STD_HPP */
|
#endif /* SQUIRREL_STD_HPP */
|
||||||
|
|
|
@ -330,32 +330,26 @@ TileIndex Ship::GetOrderStationLocation(StationID station)
|
||||||
|
|
||||||
void Ship::UpdateDeltaXY()
|
void Ship::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
static const int8_t _delta_xy_table[8][4] = {
|
static constexpr SpriteBounds ship_bounds[DIR_END] = {
|
||||||
/* y_extent, x_extent, y_offs, x_offs */
|
{{ -3, -3, 0}, { 6, 6, 6}, {}}, // N
|
||||||
{ 6, 6, -3, -3}, // N
|
{{-16, -3, 0}, {32, 6, 6}, {}}, // NE
|
||||||
{ 6, 32, -3, -16}, // NE
|
{{ -3, -3, 0}, { 6, 6, 6}, {}}, // E
|
||||||
{ 6, 6, -3, -3}, // E
|
{{ -3, -16, 0}, { 6, 32, 6}, {}}, // SE
|
||||||
{32, 6, -16, -3}, // SE
|
{{ -3, -3, 0}, { 6, 6, 6}, {}}, // S
|
||||||
{ 6, 6, -3, -3}, // S
|
{{-16, -3, 0}, {32, 6, 6}, {}}, // SW
|
||||||
{ 6, 32, -3, -16}, // SW
|
{{ -3, -3, 0}, { 6, 6, 6}, {}}, // W
|
||||||
{ 6, 6, -3, -3}, // W
|
{{ -3, -16, 0}, { 6, 32, 6}, {}}, // NW
|
||||||
{32, 6, -16, -3}, // NW
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const int8_t *bb = _delta_xy_table[this->rotation];
|
this->bounds = ship_bounds[this->rotation];
|
||||||
this->x_offs = bb[3];
|
|
||||||
this->y_offs = bb[2];
|
|
||||||
this->x_extent = bb[1];
|
|
||||||
this->y_extent = bb[0];
|
|
||||||
this->z_extent = 6;
|
|
||||||
|
|
||||||
if (this->direction != this->rotation) {
|
if (this->direction != this->rotation) {
|
||||||
/* If we are rotating, then it is possible the ship was moved to its next position. In that
|
/* If we are rotating, then it is possible the ship was moved to its next position. In that
|
||||||
* case, because we are still showing the old direction, the ship will appear to glitch sideways
|
* case, because we are still showing the old direction, the ship will appear to glitch sideways
|
||||||
* slightly. We can work around this by applying an additional offset to make the ship appear
|
* slightly. We can work around this by applying an additional offset to make the ship appear
|
||||||
* where it was before it moved. */
|
* where it was before it moved. */
|
||||||
this->x_offs -= this->x_pos - this->rotation_x_pos;
|
this->bounds.origin.x -= this->x_pos - this->rotation_x_pos;
|
||||||
this->y_offs -= this->y_pos - this->rotation_y_pos;
|
this->bounds.origin.y -= this->y_pos - this->rotation_y_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,16 +54,11 @@ void DrawCommonTileSeq(const TileInfo *ti, const DrawTileSprites *dts, Transpare
|
||||||
|
|
||||||
if (dtss.IsParentSprite()) {
|
if (dtss.IsParentSprite()) {
|
||||||
parent_sprite_encountered = true;
|
parent_sprite_encountered = true;
|
||||||
AddSortableSpriteToDraw(
|
AddSortableSpriteToDraw(image, pal, *ti, dtss, !HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(to)
|
||||||
image, pal,
|
|
||||||
ti->x + dtss.delta_x, ti->y + dtss.delta_y,
|
|
||||||
dtss.size_x, dtss.size_y,
|
|
||||||
dtss.size_z, ti->z + dtss.delta_z,
|
|
||||||
!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(to)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
int offs_x = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.delta_x) : dtss.delta_x;
|
int offs_x = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.origin.x) : dtss.origin.x;
|
||||||
int offs_y = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.delta_y) : dtss.delta_y;
|
int offs_y = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.origin.y) : dtss.origin.y;
|
||||||
bool transparent = !HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(to);
|
bool transparent = !HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(to);
|
||||||
if (parent_sprite_encountered) {
|
if (parent_sprite_encountered) {
|
||||||
AddChildSpriteScreen(image, pal, offs_x, offs_y, transparent);
|
AddChildSpriteScreen(image, pal, offs_x, offs_y, transparent);
|
||||||
|
@ -114,15 +109,15 @@ void DrawCommonTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32_t or
|
||||||
pal = SpriteLayoutPaletteTransform(image, pal, default_palette);
|
pal = SpriteLayoutPaletteTransform(image, pal, default_palette);
|
||||||
|
|
||||||
if (dtss.IsParentSprite()) {
|
if (dtss.IsParentSprite()) {
|
||||||
Point pt = RemapCoords(dtss.delta_x, dtss.delta_y, dtss.delta_z);
|
Point pt = RemapCoords(dtss.origin.x, dtss.origin.y, dtss.origin.z);
|
||||||
DrawSprite(image, pal, x + UnScaleGUI(pt.x), y + UnScaleGUI(pt.y));
|
DrawSprite(image, pal, x + UnScaleGUI(pt.x), y + UnScaleGUI(pt.y));
|
||||||
|
|
||||||
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
|
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
|
||||||
child_offset.x = UnScaleGUI(pt.x + spr->x_offs);
|
child_offset.x = UnScaleGUI(pt.x + spr->x_offs);
|
||||||
child_offset.y = UnScaleGUI(pt.y + spr->y_offs);
|
child_offset.y = UnScaleGUI(pt.y + spr->y_offs);
|
||||||
} else {
|
} else {
|
||||||
int offs_x = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.delta_x) : dtss.delta_x;
|
int offs_x = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.origin.x) : dtss.origin.x;
|
||||||
int offs_y = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.delta_y) : dtss.delta_y;
|
int offs_y = child_offset_is_unsigned ? static_cast<uint8_t>(dtss.origin.y) : dtss.origin.y;
|
||||||
DrawSprite(image, pal, x + child_offset.x + ScaleSpriteTrad(offs_x), y + child_offset.y + ScaleSpriteTrad(offs_y));
|
DrawSprite(image, pal, x + child_offset.x + ScaleSpriteTrad(offs_x), y + child_offset.y + ScaleSpriteTrad(offs_y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
src/sprite.h
32
src/sprite.h
|
@ -10,28 +10,33 @@
|
||||||
#ifndef SPRITE_H
|
#ifndef SPRITE_H
|
||||||
#define SPRITE_H
|
#define SPRITE_H
|
||||||
|
|
||||||
|
#include "core/geometry_type.hpp"
|
||||||
#include "transparency.h"
|
#include "transparency.h"
|
||||||
|
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
|
|
||||||
|
struct SpriteBounds {
|
||||||
|
PointXyz<int8_t> origin; ///< Position of northern corner within tile.
|
||||||
|
PointXyz<uint8_t> extent; ///< Size of bounding box.
|
||||||
|
PointXyz<int8_t> offset; ///< Relative position of sprite from bounding box.
|
||||||
|
};
|
||||||
|
|
||||||
/* The following describes bunch of sprites to be drawn together in a single 3D
|
/* The following describes bunch of sprites to be drawn together in a single 3D
|
||||||
* bounding box. Used especially for various multi-sprite buildings (like
|
* bounding box. Used especially for various multi-sprite buildings (like
|
||||||
* depots or stations): */
|
* depots or stations): */
|
||||||
|
|
||||||
/** A tile child sprite and palette to draw for stations etc, with 3D bounding box */
|
/** A tile child sprite and palette to draw for stations etc, with 3D bounding box */
|
||||||
struct DrawTileSeqStruct {
|
struct DrawTileSeqStruct : SpriteBounds {
|
||||||
int8_t delta_x = 0;
|
PalSpriteID image;
|
||||||
int8_t delta_y = 0;
|
|
||||||
int8_t delta_z = 0; ///< \c 0x80 identifies child sprites
|
constexpr DrawTileSeqStruct() = default;
|
||||||
uint8_t size_x = 0;
|
constexpr DrawTileSeqStruct(int8_t origin_x, int8_t origin_y, int8_t origin_z, uint8_t extent_x, uint8_t extent_y, uint8_t extent_z, PalSpriteID image) :
|
||||||
uint8_t size_y = 0;
|
SpriteBounds({origin_x, origin_y, origin_z}, {extent_x, extent_y, extent_z}, {}), image(image) {}
|
||||||
uint8_t size_z = 0;
|
|
||||||
PalSpriteID image{};
|
|
||||||
|
|
||||||
/** Check whether this is a parent sprite with a boundingbox. */
|
/** Check whether this is a parent sprite with a boundingbox. */
|
||||||
bool IsParentSprite() const
|
inline bool IsParentSprite() const
|
||||||
{
|
{
|
||||||
return (uint8_t)this->delta_z != 0x80;
|
return static_cast<uint8_t>(this->origin.z) != 0x80;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,14 +74,9 @@ struct DrawTileSpriteSpan : DrawTileSprites {
|
||||||
* This structure is the same for both Industries and Houses.
|
* This structure is the same for both Industries and Houses.
|
||||||
* Buildings here reference a general type of construction
|
* Buildings here reference a general type of construction
|
||||||
*/
|
*/
|
||||||
struct DrawBuildingsTileStruct {
|
struct DrawBuildingsTileStruct : SpriteBounds {
|
||||||
PalSpriteID ground;
|
PalSpriteID ground;
|
||||||
PalSpriteID building;
|
PalSpriteID building;
|
||||||
uint8_t subtile_x;
|
|
||||||
uint8_t subtile_y;
|
|
||||||
uint8_t width;
|
|
||||||
uint8_t height;
|
|
||||||
uint8_t dz;
|
|
||||||
uint8_t draw_proc; // this allows to specify a special drawing procedure.
|
uint8_t draw_proc; // this allows to specify a special drawing procedure.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3184,7 +3184,7 @@ static void DrawTile_Station(TileInfo *ti)
|
||||||
7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
|
7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
|
||||||
};
|
};
|
||||||
|
|
||||||
AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
|
AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, 7}, {}});
|
||||||
} else {
|
} else {
|
||||||
/* Draw simple foundations, built up from 8 possible foundation sprites. */
|
/* Draw simple foundations, built up from 8 possible foundation sprites. */
|
||||||
|
|
||||||
|
@ -3218,7 +3218,7 @@ static void DrawTile_Station(TileInfo *ti)
|
||||||
StartSpriteCombine();
|
StartSpriteCombine();
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
if (HasBit(parts, i)) {
|
if (HasBit(parts, i)) {
|
||||||
AddSortableSpriteToDraw(image + i, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
|
AddSortableSpriteToDraw(image + i, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, 7}, {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EndSpriteCombine();
|
EndSpriteCombine();
|
||||||
|
@ -3331,7 +3331,7 @@ draw_default_foundation:
|
||||||
auto result = GetRoadStopLayout(ti, stopspec, st, type, view, regs100);
|
auto result = GetRoadStopLayout(ti, stopspec, st, type, view, regs100);
|
||||||
if (result.has_value()) {
|
if (result.has_value()) {
|
||||||
if (stopspec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
|
if (stopspec->flags.Test(RoadStopSpecFlag::DrawModeRegister)) {
|
||||||
stop_draw_mode = static_cast<RoadStopDrawMode>(regs100[0]);
|
stop_draw_mode = static_cast<RoadStopDrawModes>(regs100[0]);
|
||||||
}
|
}
|
||||||
if (type == StationType::RoadWaypoint && stop_draw_mode.Test(RoadStopDrawMode::WaypGround)) {
|
if (type == StationType::RoadWaypoint && stop_draw_mode.Test(RoadStopDrawMode::WaypGround)) {
|
||||||
draw_ground = true;
|
draw_ground = true;
|
||||||
|
|
|
@ -313,14 +313,12 @@ enum WireSpriteOffset : uint8_t {
|
||||||
WSO_ENTRANCE_SE,
|
WSO_ENTRANCE_SE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SortableSpriteStruct {
|
struct SortableSpriteStruct : SpriteBounds {
|
||||||
uint8_t image_offset;
|
uint8_t image_offset;
|
||||||
int8_t x_offset;
|
|
||||||
int8_t y_offset;
|
constexpr SortableSpriteStruct(uint8_t image_offset, const SpriteBounds &bounds) : SpriteBounds(bounds), image_offset(image_offset) {}
|
||||||
int8_t x_size;
|
constexpr SortableSpriteStruct(uint8_t image_offset, int8_t x_offset, int8_t y_offset, uint8_t x_size, uint8_t y_size, uint8_t z_size, int8_t z_offset) :
|
||||||
int8_t y_size;
|
SpriteBounds({x_offset, y_offset, z_offset}, {x_size, y_size, z_size}, {}), image_offset(image_offset) {}
|
||||||
int8_t z_size;
|
|
||||||
int8_t z_offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Distance between wire and rail */
|
/** Distance between wire and rail */
|
||||||
|
@ -398,11 +396,17 @@ static const SortableSpriteStruct _rail_catenary_sprite_data_depot[] = {
|
||||||
{ WSO_ENTRANCE_NW, 7, 0, 1, 15, 1, ELRAIL_ELEVATION } //! Wire for NW depot exit
|
{ WSO_ENTRANCE_NW, 7, 0, 1, 15, 1, ELRAIL_ELEVATION } //! Wire for NW depot exit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In tunnelheads, the bounding box for wires covers nearly the full tile, and is lowered a bit.
|
||||||
|
* ELRAIL_TUNNEL_OFFSET is the difference between visual position and bounding box.
|
||||||
|
*/
|
||||||
|
static const int8_t ELRAIL_TUNNEL_OFFSET = ELRAIL_ELEVATION - BB_Z_SEPARATOR;
|
||||||
|
|
||||||
static const SortableSpriteStruct _rail_catenary_sprite_data_tunnel[] = {
|
static const SortableSpriteStruct _rail_catenary_sprite_data_tunnel[] = {
|
||||||
{ WSO_ENTRANCE_SW, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for NE tunnel (SW facing exit)
|
{ WSO_ENTRANCE_SW, {{0, 0, BB_Z_SEPARATOR}, {16, 15, 1}, {0, 7, ELRAIL_TUNNEL_OFFSET}} }, //! Wire for NE tunnel (SW facing exit)
|
||||||
{ WSO_ENTRANCE_NW, 7, 0, 1, 15, 1, ELRAIL_ELEVATION }, //! Wire for SE tunnel (NW facing exit)
|
{ WSO_ENTRANCE_NW, {{0, 0, BB_Z_SEPARATOR}, {15, 16, 1}, {7, 0, ELRAIL_TUNNEL_OFFSET}} }, //! Wire for SE tunnel (NW facing exit)
|
||||||
{ WSO_ENTRANCE_NE, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for SW tunnel (NE facing exit)
|
{ WSO_ENTRANCE_NE, {{0, 0, BB_Z_SEPARATOR}, {16, 15, 1}, {0, 7, ELRAIL_TUNNEL_OFFSET}} }, //! Wire for SW tunnel (NE facing exit)
|
||||||
{ WSO_ENTRANCE_SE, 7, 0, 1, 15, 1, ELRAIL_ELEVATION } //! Wire for NW tunnel (SE facing exit)
|
{ WSO_ENTRANCE_SE, {{0, 0, BB_Z_SEPARATOR}, {15, 16, 1}, {7, 0, ELRAIL_TUNNEL_OFFSET}} } //! Wire for NW tunnel (SE facing exit)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,15 +37,15 @@ struct DrawIndustryCoordinates {
|
||||||
* @param p1 palette ID of ground sprite
|
* @param p1 palette ID of ground sprite
|
||||||
* @param s2 sprite ID of building sprite
|
* @param s2 sprite ID of building sprite
|
||||||
* @param p2 palette ID of building sprite
|
* @param p2 palette ID of building sprite
|
||||||
* @param sx coordinate x of the sprite
|
* @param dx The x-position of the sprite within the tile.
|
||||||
* @param sy coordinate y of the sprite
|
* @param dy the y-position of the sprite within the tile.
|
||||||
* @param w width of the sprite
|
* @param sx the x-extent of the sprite.
|
||||||
* @param h height of the sprite
|
* @param sy the y-extent of the sprite.
|
||||||
* @param dz virtual height of the sprite
|
* @param sz the z-extent of the sprite.
|
||||||
* @param p this allows to specify a special drawing procedure.
|
* @param p this allows to specify a special drawing procedure.
|
||||||
* @see DrawBuildingsTileStruct
|
* @see DrawBuildingsTileStruct
|
||||||
*/
|
*/
|
||||||
#define M(s1, p1, s2, p2, sx, sy, w, h, dz, p) { { s1, p1 }, { s2, p2 }, sx, sy, w, h, dz, p }
|
#define M(s1, p1, s2, p2, dx, dy, sx, sy, sz, p) { {{dx, dy, 0}, {sx, sy, sz}, {}}, { s1, p1 }, { s2, p2 }, p}
|
||||||
|
|
||||||
/** Structure for industry tiles drawing */
|
/** Structure for industry tiles drawing */
|
||||||
static const DrawBuildingsTileStruct _industry_draw_tile_data[NEW_INDUSTRYTILEOFFSET * 4] = {
|
static const DrawBuildingsTileStruct _industry_draw_tile_data[NEW_INDUSTRYTILEOFFSET * 4] = {
|
||||||
|
|
|
@ -13,15 +13,15 @@
|
||||||
* @param p1 The first sprite's palette of the building, mostly the ground sprite
|
* @param p1 The first sprite's palette of the building, mostly the ground sprite
|
||||||
* @param s2 The second sprite of the building.
|
* @param s2 The second sprite of the building.
|
||||||
* @param p2 The second sprite's palette of the building.
|
* @param p2 The second sprite's palette of the building.
|
||||||
* @param sx The x-position of the sprite within the tile
|
* @param dx The x-position of the sprite within the tile.
|
||||||
* @param sy the y-position of the sprite within the tile
|
* @param dy the y-position of the sprite within the tile.
|
||||||
* @param w the width of the sprite
|
* @param sx the x-extent of the sprite.
|
||||||
* @param h the height of the sprite
|
* @param sy the y-extent of the sprite.
|
||||||
* @param dz the virtual height of the sprite
|
* @param sz the z-extent of the sprite.
|
||||||
* @param p set to 1 if a lift is present ()
|
* @param p set to 1 if a lift is present ()
|
||||||
* @see DrawBuildingsTileStruct
|
* @see DrawBuildingsTileStruct
|
||||||
*/
|
*/
|
||||||
#define M(s1, p1, s2, p2, sx, sy, w, h, dz, p) { { s1, p1 }, { s2, p2 }, sx, sy, w, h, dz, p}
|
#define M(s1, p1, s2, p2, dx, dy, sx, sy, sz, p) { {{dx, dy, 0}, {sx, sy, sz}, {}}, { s1, p1 }, { s2, p2 }, p}
|
||||||
|
|
||||||
/** structure of houses graphics*/
|
/** structure of houses graphics*/
|
||||||
static const DrawBuildingsTileStruct _town_draw_tile_data[] = {
|
static const DrawBuildingsTileStruct _town_draw_tile_data[] = {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef TILE_CMD_H
|
#ifndef TILE_CMD_H
|
||||||
#define TILE_CMD_H
|
#define TILE_CMD_H
|
||||||
|
|
||||||
|
#include "core/geometry_type.hpp"
|
||||||
#include "command_type.h"
|
#include "command_type.h"
|
||||||
#include "vehicle_type.h"
|
#include "vehicle_type.h"
|
||||||
#include "cargo_type.h"
|
#include "cargo_type.h"
|
||||||
|
@ -26,12 +27,9 @@ enum class VehicleEnterTileState : uint8_t {
|
||||||
using VehicleEnterTileStates = EnumBitSet<VehicleEnterTileState, uint8_t>;
|
using VehicleEnterTileStates = EnumBitSet<VehicleEnterTileState, uint8_t>;
|
||||||
|
|
||||||
/** Tile information, used while rendering the tile */
|
/** Tile information, used while rendering the tile */
|
||||||
struct TileInfo {
|
struct TileInfo : PointXyz<int> {
|
||||||
int x; ///< X position of the tile in unit coordinates
|
|
||||||
int y; ///< Y position of the tile in unit coordinates
|
|
||||||
Slope tileh; ///< Slope of the tile
|
Slope tileh; ///< Slope of the tile
|
||||||
TileIndex tile; ///< Tile index
|
TileIndex tile; ///< Tile index
|
||||||
int z; ///< Height
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Tile description for the 'land area information' tool */
|
/** Tile description for the 'land area information' tool */
|
||||||
|
|
|
@ -12,29 +12,29 @@
|
||||||
|
|
||||||
#include "core/strong_typedef_type.hpp"
|
#include "core/strong_typedef_type.hpp"
|
||||||
|
|
||||||
static const uint TILE_SIZE = 16; ///< Tile size in world coordinates.
|
static constexpr uint TILE_SIZE = 16; ///< Tile size in world coordinates.
|
||||||
static const uint TILE_UNIT_MASK = TILE_SIZE - 1; ///< For masking in/out the inner-tile world coordinate units.
|
static constexpr uint TILE_UNIT_MASK = TILE_SIZE - 1; ///< For masking in/out the inner-tile world coordinate units.
|
||||||
static const uint TILE_PIXELS = 32; ///< Pixel distance between tile columns/rows in #ZOOM_BASE.
|
static constexpr uint TILE_PIXELS = 32; ///< Pixel distance between tile columns/rows in #ZOOM_BASE.
|
||||||
static const uint TILE_HEIGHT = 8; ///< Height of a height level in world coordinate AND in pixels in #ZOOM_BASE.
|
static constexpr uint TILE_HEIGHT = 8; ///< Height of a height level in world coordinate AND in pixels in #ZOOM_BASE.
|
||||||
|
|
||||||
static const uint MAX_BUILDING_PIXELS = 200; ///< Maximum height of a building in pixels in #ZOOM_BASE. (Also applies to "bridge buildings" on the bridge floor.)
|
static constexpr uint MAX_BUILDING_PIXELS = 200; ///< Maximum height of a building in pixels in #ZOOM_BASE. (Also applies to "bridge buildings" on the bridge floor.)
|
||||||
static const int MAX_VEHICLE_PIXEL_X = 192; ///< Maximum width of a vehicle in pixels in #ZOOM_BASE.
|
static constexpr int MAX_VEHICLE_PIXEL_X = 192; ///< Maximum width of a vehicle in pixels in #ZOOM_BASE.
|
||||||
static const int MAX_VEHICLE_PIXEL_Y = 96; ///< Maximum height of a vehicle in pixels in #ZOOM_BASE.
|
static constexpr int MAX_VEHICLE_PIXEL_Y = 96; ///< Maximum height of a vehicle in pixels in #ZOOM_BASE.
|
||||||
|
|
||||||
static const uint MAX_TILE_HEIGHT = 255; ///< Maximum allowed tile height
|
static constexpr uint MAX_TILE_HEIGHT = 255; ///< Maximum allowed tile height
|
||||||
|
|
||||||
static const uint MIN_HEIGHTMAP_HEIGHT = 1; ///< Lowest possible peak value for heightmap creation
|
static constexpr uint MIN_HEIGHTMAP_HEIGHT = 1; ///< Lowest possible peak value for heightmap creation
|
||||||
static const uint MIN_CUSTOM_TERRAIN_TYPE = 1; ///< Lowest possible peak value for world generation
|
static constexpr uint MIN_CUSTOM_TERRAIN_TYPE = 1; ///< Lowest possible peak value for world generation
|
||||||
|
|
||||||
static const uint MIN_MAP_HEIGHT_LIMIT = 15; ///< Lower bound of maximum allowed heightlevel (in the construction settings)
|
static constexpr uint MIN_MAP_HEIGHT_LIMIT = 15; ///< Lower bound of maximum allowed heightlevel (in the construction settings)
|
||||||
static const uint MAX_MAP_HEIGHT_LIMIT = MAX_TILE_HEIGHT; ///< Upper bound of maximum allowed heightlevel (in the construction settings)
|
static constexpr uint MAX_MAP_HEIGHT_LIMIT = MAX_TILE_HEIGHT; ///< Upper bound of maximum allowed heightlevel (in the construction settings)
|
||||||
|
|
||||||
static const uint MIN_SNOWLINE_HEIGHT = 2; ///< Minimum snowline height
|
static constexpr uint MIN_SNOWLINE_HEIGHT = 2; ///< Minimum snowline height
|
||||||
static const uint DEF_SNOWLINE_HEIGHT = 10; ///< Default snowline height
|
static constexpr uint DEF_SNOWLINE_HEIGHT = 10; ///< Default snowline height
|
||||||
static const uint MAX_SNOWLINE_HEIGHT = (MAX_TILE_HEIGHT - 2); ///< Maximum allowed snowline height
|
static constexpr uint MAX_SNOWLINE_HEIGHT = (MAX_TILE_HEIGHT - 2); ///< Maximum allowed snowline height
|
||||||
|
|
||||||
static const uint DEF_SNOW_COVERAGE = 40; ///< Default snow coverage.
|
static constexpr uint DEF_SNOW_COVERAGE = 40; ///< Default snow coverage.
|
||||||
static const uint DEF_DESERT_COVERAGE = 50; ///< Default desert coverage.
|
static constexpr uint DEF_DESERT_COVERAGE = 50; ///< Default desert coverage.
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -427,6 +427,7 @@ struct TimetableWindow : Window {
|
||||||
void DrawTimetablePanel(const Rect &r) const
|
void DrawTimetablePanel(const Rect &r) const
|
||||||
{
|
{
|
||||||
const Vehicle *v = this->vehicle;
|
const Vehicle *v = this->vehicle;
|
||||||
|
if (v->GetNumOrders() == 0) return;
|
||||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
int i = this->vscroll->GetPosition();
|
int i = this->vscroll->GetPosition();
|
||||||
VehicleOrderID order_id = (i + 1) / 2;
|
VehicleOrderID order_id = (i + 1) / 2;
|
||||||
|
|
|
@ -284,15 +284,7 @@ static void DrawTile_Town(TileInfo *ti)
|
||||||
/* Add a house on top of the ground? */
|
/* Add a house on top of the ground? */
|
||||||
SpriteID image = dcts->building.sprite;
|
SpriteID image = dcts->building.sprite;
|
||||||
if (image != 0) {
|
if (image != 0) {
|
||||||
AddSortableSpriteToDraw(image, dcts->building.pal,
|
AddSortableSpriteToDraw(image, dcts->building.pal, *ti, *dcts, IsTransparencySet(TO_HOUSES));
|
||||||
ti->x + dcts->subtile_x,
|
|
||||||
ti->y + dcts->subtile_y,
|
|
||||||
dcts->width,
|
|
||||||
dcts->height,
|
|
||||||
dcts->dz,
|
|
||||||
ti->z,
|
|
||||||
IsTransparencySet(TO_HOUSES)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (IsTransparencySet(TO_HOUSES)) return;
|
if (IsTransparencySet(TO_HOUSES)) return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
|
||||||
|
|
||||||
/* Add a house on top of the ground? */
|
/* Add a house on top of the ground? */
|
||||||
if (dcts.building.sprite != 0) {
|
if (dcts.building.sprite != 0) {
|
||||||
Point pt = RemapCoords(dcts.subtile_x, dcts.subtile_y, 0);
|
Point pt = RemapCoords(dcts.origin.x, dcts.origin.y, dcts.origin.z);
|
||||||
DrawSprite(dcts.building.sprite, dcts.building.pal, x + UnScaleGUI(pt.x), y + UnScaleGUI(pt.y));
|
DrawSprite(dcts.building.sprite, dcts.building.pal, x + UnScaleGUI(pt.x), y + UnScaleGUI(pt.y));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1491,13 +1491,7 @@ CommandCost CmdSellRailWagon(DoCommandFlags flags, Vehicle *t, bool sell_chain,
|
||||||
void Train::UpdateDeltaXY()
|
void Train::UpdateDeltaXY()
|
||||||
{
|
{
|
||||||
/* Set common defaults. */
|
/* Set common defaults. */
|
||||||
this->x_offs = -1;
|
this->bounds = {{-1, -1, 0}, {3, 3, 6}, {}};
|
||||||
this->y_offs = -1;
|
|
||||||
this->x_extent = 3;
|
|
||||||
this->y_extent = 3;
|
|
||||||
this->z_extent = 6;
|
|
||||||
this->x_bb_offs = 0;
|
|
||||||
this->y_bb_offs = 0;
|
|
||||||
|
|
||||||
/* Set if flipped and engine is NOT flagged with custom flip handling. */
|
/* Set if flipped and engine is NOT flagged with custom flip handling. */
|
||||||
int flipped = this->flags.Test(VehicleRailFlag::Flipped) && !EngInfo(this->engine_type)->misc_flags.Test(EngineMiscFlag::RailFlips);
|
int flipped = this->flags.Test(VehicleRailFlag::Flipped) && !EngInfo(this->engine_type)->misc_flags.Test(EngineMiscFlag::RailFlips);
|
||||||
|
@ -1508,50 +1502,47 @@ void Train::UpdateDeltaXY()
|
||||||
if (flipped) dir = ReverseDir(dir);
|
if (flipped) dir = ReverseDir(dir);
|
||||||
|
|
||||||
if (!IsDiagonalDirection(dir)) {
|
if (!IsDiagonalDirection(dir)) {
|
||||||
static const int _sign_table[] =
|
static const Point _sign_table[] = {
|
||||||
{
|
|
||||||
/* x, y */
|
/* x, y */
|
||||||
-1, -1, // DIR_N
|
{-1, -1}, // DIR_N
|
||||||
-1, 1, // DIR_E
|
{-1, 1}, // DIR_E
|
||||||
1, 1, // DIR_S
|
{ 1, 1}, // DIR_S
|
||||||
1, -1, // DIR_W
|
{ 1, -1}, // DIR_W
|
||||||
};
|
};
|
||||||
|
|
||||||
int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length + flipped) / 2;
|
int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length + flipped) / 2;
|
||||||
|
|
||||||
/* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
|
/* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
|
||||||
this->x_offs -= half_shorten * _sign_table[dir];
|
this->bounds.offset.x -= half_shorten * _sign_table[DirToDiagDir(dir)].x;
|
||||||
this->y_offs -= half_shorten * _sign_table[dir + 1];
|
this->bounds.offset.y -= half_shorten * _sign_table[DirToDiagDir(dir)].y;
|
||||||
this->x_extent += this->x_bb_offs = half_shorten * _sign_table[dir];
|
|
||||||
this->y_extent += this->y_bb_offs = half_shorten * _sign_table[dir + 1];
|
|
||||||
} else {
|
} else {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
/* Shorten southern corner of the bounding box according the vehicle length
|
/* Shorten southern corner of the bounding box according the vehicle length
|
||||||
* and center the bounding box on the vehicle. */
|
* and center the bounding box on the vehicle. */
|
||||||
case DIR_NE:
|
case DIR_NE:
|
||||||
this->x_offs = 1 - (this->gcache.cached_veh_length + 1) / 2 + flip_offs;
|
this->bounds.origin.x = -(this->gcache.cached_veh_length + 1) / 2 + flip_offs;
|
||||||
this->x_extent = this->gcache.cached_veh_length - 1;
|
this->bounds.extent.x = this->gcache.cached_veh_length;
|
||||||
this->x_bb_offs = -1;
|
this->bounds.offset.x = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIR_NW:
|
case DIR_NW:
|
||||||
this->y_offs = 1 - (this->gcache.cached_veh_length + 1) / 2 + flip_offs;
|
this->bounds.origin.y = -(this->gcache.cached_veh_length + 1) / 2 + flip_offs;
|
||||||
this->y_extent = this->gcache.cached_veh_length - 1;
|
this->bounds.extent.y = this->gcache.cached_veh_length;
|
||||||
this->y_bb_offs = -1;
|
this->bounds.offset.y = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Move northern corner of the bounding box down according to vehicle length
|
/* Move northern corner of the bounding box down according to vehicle length
|
||||||
* and center the bounding box on the vehicle. */
|
* and center the bounding box on the vehicle. */
|
||||||
case DIR_SW:
|
case DIR_SW:
|
||||||
this->x_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH - flip_offs;
|
this->bounds.origin.x = -(this->gcache.cached_veh_length) / 2 - flip_offs;
|
||||||
this->x_extent = VEHICLE_LENGTH - 1;
|
this->bounds.extent.x = this->gcache.cached_veh_length;
|
||||||
this->x_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
this->bounds.offset.x = 1 - (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIR_SE:
|
case DIR_SE:
|
||||||
this->y_offs = 1 + (this->gcache.cached_veh_length + 1) / 2 - VEHICLE_LENGTH - flip_offs;
|
this->bounds.origin.y = -(this->gcache.cached_veh_length) / 2 - flip_offs;
|
||||||
this->y_extent = VEHICLE_LENGTH - 1;
|
this->bounds.extent.y = this->gcache.cached_veh_length;
|
||||||
this->y_bb_offs = VEHICLE_LENGTH - this->gcache.cached_veh_length - 1;
|
this->bounds.offset.y = 1 - (VEHICLE_LENGTH - this->gcache.cached_veh_length);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -635,7 +635,7 @@ CommandCost CmdPlantTree(DoCommandFlags flags, TileIndex tile, TileIndex start_t
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TreeListEnt : PalSpriteID {
|
struct TreeListEnt : PalSpriteID {
|
||||||
uint8_t x, y;
|
int8_t x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DrawTile_Trees(TileInfo *ti)
|
static void DrawTile_Trees(TileInfo *ti)
|
||||||
|
@ -699,7 +699,8 @@ static void DrawTile_Trees(TileInfo *ti)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSortableSpriteToDraw(te[mi].sprite, te[mi].pal, ti->x + te[mi].x, ti->y + te[mi].y, 16 - te[mi].x, 16 - te[mi].y, 0x30, z, IsTransparencySet(TO_TREES), -te[mi].x, -te[mi].y);
|
SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, 48}, {te[mi].x, te[mi].y, 0}};
|
||||||
|
AddSortableSpriteToDraw(te[mi].sprite, te[mi].pal, ti->x, ti->y, z, bounds, IsTransparencySet(TO_TREES));
|
||||||
|
|
||||||
/* replace the removed one with the last one */
|
/* replace the removed one with the last one */
|
||||||
te[mi] = te[trees - 1];
|
te[mi] = te[trees - 1];
|
||||||
|
|
|
@ -1017,10 +1017,10 @@ static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlags flags)
|
||||||
* @param h Bounding box size in Y direction
|
* @param h Bounding box size in Y direction
|
||||||
* @param subsprite Optional subsprite for drawing halfpillars
|
* @param subsprite Optional subsprite for drawing halfpillars
|
||||||
*/
|
*/
|
||||||
static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, int w, int h, const SubSprite *subsprite)
|
static inline void DrawPillar(const PalSpriteID *psid, int x, int y, int z, uint8_t w, uint8_t h, const SubSprite *subsprite)
|
||||||
{
|
{
|
||||||
static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START; ///< Start offset of pillar wrt. bridge (downwards)
|
static const int PILLAR_Z_OFFSET = TILE_HEIGHT - BRIDGE_Z_START; ///< Start offset of pillar wrt. bridge (downwards)
|
||||||
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, w, h, BB_HEIGHT_UNDER_BRIDGE - PILLAR_Z_OFFSET, z, IsTransparencySet(TO_BRIDGES), 0, 0, -PILLAR_Z_OFFSET, subsprite);
|
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, -PILLAR_Z_OFFSET}, {w, h, BB_HEIGHT_UNDER_BRIDGE}, {0, 0, PILLAR_Z_OFFSET}}, IsTransparencySet(TO_BRIDGES), subsprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1194,18 +1194,20 @@ static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
|
static constexpr SpriteBounds back_bounds[6] = {
|
||||||
static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
|
{{}, {0, TILE_SIZE, 40}, {}},
|
||||||
static const uint front_bb_offset_x[6] = { 15, 0, 0, 15, 0, 15 };
|
{{}, {TILE_SIZE, 0, 40}, {}},
|
||||||
static const uint front_bb_offset_y[6] = { 0, 15, 15, 0, 15, 0 };
|
{{}, {TILE_SIZE, 0, 40}, {}},
|
||||||
|
{{}, {0, TILE_SIZE, 40}, {}},
|
||||||
|
{{}, {TILE_SIZE, 0, 40}, {}},
|
||||||
|
{{}, {0, TILE_SIZE, 40}, {}},
|
||||||
|
};
|
||||||
|
|
||||||
/* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
|
/* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
|
||||||
* The bounding boxes here are the same as for bridge front/roof */
|
* The bounding boxes here are the same as for bridge front/roof */
|
||||||
for (uint i = 0; i < lengthof(seq_back); ++i) {
|
for (uint i = 0; i < lengthof(seq_back); ++i) {
|
||||||
if (seq_back[i] != 0) {
|
if (seq_back[i] != 0) {
|
||||||
AddSortableSpriteToDraw(seq_back[i], PAL_NONE,
|
AddSortableSpriteToDraw(seq_back[i], PAL_NONE, x, y, z, back_bounds[offset], trans_back[i]);
|
||||||
x, y, size_x[offset], size_y[offset], 0x28, z,
|
|
||||||
trans_back[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1213,12 +1215,18 @@ static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int off
|
||||||
EndSpriteCombine();
|
EndSpriteCombine();
|
||||||
StartSpriteCombine();
|
StartSpriteCombine();
|
||||||
|
|
||||||
|
static constexpr SpriteBounds front_bounds[6] = {
|
||||||
|
{{15, 0, 0}, {0, TILE_SIZE, 40}, {-15, 0, 0}},
|
||||||
|
{{0, 15, 0}, {TILE_SIZE, 0, 40}, {0, -15, 0}},
|
||||||
|
{{0, 15, 0}, {TILE_SIZE, 0, 40}, {0, -15, 0}},
|
||||||
|
{{15, 0, 0}, {0, TILE_SIZE, 40}, {-15, 0, 0}},
|
||||||
|
{{0, 15, 0}, {TILE_SIZE, 0, 40}, {0, -15, 0}},
|
||||||
|
{{15, 0, 0}, {0, TILE_SIZE, 40}, {-15, 0, 0}},
|
||||||
|
};
|
||||||
|
|
||||||
for (uint i = 0; i < lengthof(seq_front); ++i) {
|
for (uint i = 0; i < lengthof(seq_front); ++i) {
|
||||||
if (seq_front[i] != 0) {
|
if (seq_front[i] != 0) {
|
||||||
AddSortableSpriteToDraw(seq_front[i], PAL_NONE,
|
AddSortableSpriteToDraw(seq_front[i], PAL_NONE, x, y, z, front_bounds[offset], trans_front[i]);
|
||||||
x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
|
|
||||||
trans_front[i],
|
|
||||||
front_bb_offset_x[offset], front_bb_offset_y[offset]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1251,15 +1259,35 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const int _tunnel_BB[4][12] = {
|
/* Tunnel sprites are positioned at 15,15, but the bounding box covers most of the tile. */
|
||||||
/* tunnnel-roof | Z-separator | tram-catenary
|
static constexpr SpriteBounds roof_bounds[DIAGDIR_END] = {
|
||||||
* w h bb_x bb_y| x y w h |bb_x bb_y w h */
|
{{0, 1, BB_Z_SEPARATOR}, {TILE_SIZE, TILE_SIZE - 1, 1}, {TILE_SIZE - 1, TILE_SIZE - 2, -BB_Z_SEPARATOR}}, // NE
|
||||||
{ 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // NE
|
{{1, 0, BB_Z_SEPARATOR}, {TILE_SIZE - 1, TILE_SIZE, 1}, {TILE_SIZE - 2, TILE_SIZE - 1, -BB_Z_SEPARATOR}}, // SE
|
||||||
{ 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // SE
|
{{0, 1, BB_Z_SEPARATOR}, {TILE_SIZE, TILE_SIZE - 1, 1}, {TILE_SIZE - 1, TILE_SIZE - 2, -BB_Z_SEPARATOR}}, // SW
|
||||||
{ 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // SW
|
{{1, 0, BB_Z_SEPARATOR}, {TILE_SIZE - 1, TILE_SIZE, 1}, {TILE_SIZE - 2, TILE_SIZE - 1, -BB_Z_SEPARATOR}}, // NW
|
||||||
{ 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // NW
|
};
|
||||||
|
|
||||||
|
/* Catenary sprites are positioned at 0,0, with the same bounding box as above. */
|
||||||
|
static constexpr SpriteBounds catenary_bounds[DIAGDIR_END] = {
|
||||||
|
{{0, 1, BB_Z_SEPARATOR}, {TILE_SIZE, TILE_SIZE - 1, 1}, {0, -1, -BB_Z_SEPARATOR}}, // NE
|
||||||
|
{{1, 0, BB_Z_SEPARATOR}, {TILE_SIZE - 1, TILE_SIZE, 1}, {-1, 0, -BB_Z_SEPARATOR}}, // SE
|
||||||
|
{{0, 1, BB_Z_SEPARATOR}, {TILE_SIZE, TILE_SIZE - 1, 1}, {0, -1, -BB_Z_SEPARATOR}}, // SW
|
||||||
|
{{1, 0, BB_Z_SEPARATOR}, {TILE_SIZE - 1, TILE_SIZE, 1}, {-1, 0, -BB_Z_SEPARATOR}}, // NW
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr SpriteBounds rear_sep[DIAGDIR_END] = {
|
||||||
|
{{}, {TILE_SIZE, 1, TILE_HEIGHT}, {}}, // NE
|
||||||
|
{{}, {1, TILE_SIZE, TILE_HEIGHT}, {}}, // SE
|
||||||
|
{{}, {TILE_SIZE, 1, TILE_HEIGHT}, {}}, // SW
|
||||||
|
{{}, {1, TILE_SIZE, TILE_HEIGHT}, {}}, // NW
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr SpriteBounds front_sep[DIAGDIR_END] = {
|
||||||
|
{{0, TILE_SIZE - 1, 0}, {TILE_SIZE, 1, TILE_HEIGHT}, {}}, // NE
|
||||||
|
{{TILE_SIZE - 1, 0, 0}, {1, TILE_SIZE, TILE_HEIGHT}, {}}, // SE
|
||||||
|
{{0, TILE_SIZE - 1, 0}, {TILE_SIZE, 1, TILE_HEIGHT}, {}}, // SW
|
||||||
|
{{TILE_SIZE - 1, 0, 0}, {1, TILE_SIZE, TILE_HEIGHT}, {}}, // NW
|
||||||
};
|
};
|
||||||
const int *BB_data = _tunnel_BB[tunnelbridge_direction];
|
|
||||||
|
|
||||||
bool catenary = false;
|
bool catenary = false;
|
||||||
|
|
||||||
|
@ -1332,7 +1360,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
if (catenary_sprite_base != 0) {
|
if (catenary_sprite_base != 0) {
|
||||||
catenary = true;
|
catenary = true;
|
||||||
StartSpriteCombine();
|
StartSpriteCombine();
|
||||||
AddSortableSpriteToDraw(catenary_sprite_base + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
|
AddSortableSpriteToDraw(catenary_sprite_base + tunnelbridge_direction, PAL_NONE, *ti, catenary_bounds[tunnelbridge_direction], IsTransparencySet(TO_CATENARY));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
|
const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
|
||||||
|
@ -1364,15 +1392,15 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
|
|
||||||
if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
|
if (railtype_overlay != 0 && !catenary) StartSpriteCombine();
|
||||||
|
|
||||||
AddSortableSpriteToDraw(image + 1, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, BB_data[0], BB_data[1], TILE_HEIGHT, ti->z, false, BB_data[2], BB_data[3], BB_Z_SEPARATOR);
|
AddSortableSpriteToDraw(image + 1, PAL_NONE, *ti, roof_bounds[tunnelbridge_direction], false);
|
||||||
/* Draw railtype tunnel portal overlay if defined. */
|
/* Draw railtype tunnel portal overlay if defined. */
|
||||||
if (railtype_overlay != 0) AddSortableSpriteToDraw(railtype_overlay + tunnelbridge_direction, PAL_NONE, ti->x + TILE_SIZE - 1, ti->y + TILE_SIZE - 1, BB_data[0], BB_data[1], TILE_HEIGHT, ti->z, false, BB_data[2], BB_data[3], BB_Z_SEPARATOR);
|
if (railtype_overlay != 0) AddSortableSpriteToDraw(railtype_overlay + tunnelbridge_direction, PAL_NONE, *ti, roof_bounds[tunnelbridge_direction], false);
|
||||||
|
|
||||||
if (catenary || railtype_overlay != 0) EndSpriteCombine();
|
if (catenary || railtype_overlay != 0) EndSpriteCombine();
|
||||||
|
|
||||||
/* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
|
/* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
|
||||||
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x, ti->y, BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
|
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, *ti, rear_sep[tunnelbridge_direction]);
|
||||||
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, ti->x + BB_data[4], ti->y + BB_data[5], BB_data[6], BB_data[7], TILE_HEIGHT, ti->z);
|
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, *ti, front_sep[tunnelbridge_direction]);
|
||||||
|
|
||||||
DrawBridgeMiddle(ti);
|
DrawBridgeMiddle(ti);
|
||||||
} else { // IsBridge(ti->tile)
|
} else { // IsBridge(ti->tile)
|
||||||
|
@ -1423,7 +1451,7 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
* it doesn't disappear behind it
|
* it doesn't disappear behind it
|
||||||
*/
|
*/
|
||||||
/* Bridge heads are drawn solid no matter how invisibility/transparency is set */
|
/* Bridge heads are drawn solid no matter how invisibility/transparency is set */
|
||||||
AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
|
AddSortableSpriteToDraw(psid->sprite, psid->pal, *ti, {{}, {TILE_SIZE, TILE_SIZE, static_cast<uint8_t>(ti->tileh == SLOPE_FLAT ? 0 : TILE_HEIGHT)}, {}});
|
||||||
|
|
||||||
if (transport_type == TRANSPORT_ROAD) {
|
if (transport_type == TRANSPORT_ROAD) {
|
||||||
uint offset = tunnelbridge_direction;
|
uint offset = tunnelbridge_direction;
|
||||||
|
@ -1445,9 +1473,9 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
|
SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE);
|
||||||
if (surface != 0) {
|
if (surface != 0) {
|
||||||
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
||||||
AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, ti->x, ti->y, 16, 16, 0, ti->z + 8);
|
AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, *ti, {{0, 0, TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, 0}, {}});
|
||||||
} else {
|
} else {
|
||||||
AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, 16, 16, 8, ti->z);
|
AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT}, {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Don't fallback to non-overlay sprite -- the spec states that
|
/* Don't fallback to non-overlay sprite -- the spec states that
|
||||||
|
@ -1460,15 +1488,15 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
||||||
if (rti->UsesOverlay()) {
|
if (rti->UsesOverlay()) {
|
||||||
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
||||||
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
||||||
AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
|
AddSortableSpriteToDraw(overlay + RTO_X + DiagDirToAxis(tunnelbridge_direction), PALETTE_CRASH, *ti, {{0, 0, TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, 0}, {}});
|
||||||
} else {
|
} else {
|
||||||
AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
|
AddSortableSpriteToDraw(overlay + RTO_SLOPE_NE + tunnelbridge_direction, PALETTE_CRASH, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT}, {}});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
|
||||||
AddSortableSpriteToDraw(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
|
AddSortableSpriteToDraw(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, *ti, {{0, 0, TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, 0}, {}});
|
||||||
} else {
|
} else {
|
||||||
AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
|
AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT}, {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1578,7 +1606,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
||||||
int z = bridge_z - BRIDGE_Z_START;
|
int z = bridge_z - BRIDGE_Z_START;
|
||||||
|
|
||||||
/* Add a bounding box that separates the bridge from things below it. */
|
/* Add a bounding box that separates the bridge from things below it. */
|
||||||
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
|
AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR, {{}, {TILE_SIZE, TILE_SIZE, 1}, {}});
|
||||||
|
|
||||||
/* Draw Trambits as SpriteCombine */
|
/* Draw Trambits as SpriteCombine */
|
||||||
if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
|
if (transport_type == TRANSPORT_ROAD || transport_type == TRANSPORT_RAIL) StartSpriteCombine();
|
||||||
|
@ -1586,9 +1614,9 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
||||||
/* Draw floor and far part of bridge*/
|
/* Draw floor and far part of bridge*/
|
||||||
if (!IsInvisibilitySet(TO_BRIDGES)) {
|
if (!IsInvisibilitySet(TO_BRIDGES)) {
|
||||||
if (axis == AXIS_X) {
|
if (axis == AXIS_X) {
|
||||||
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
|
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
|
||||||
} else {
|
} else {
|
||||||
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
|
AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {0, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,16 +1630,16 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
||||||
if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
|
if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
|
||||||
SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
|
SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE);
|
||||||
if (surface != 0) {
|
if (surface != 0) {
|
||||||
AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
|
AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, bridge_z, {{}, {TILE_SIZE, TILE_SIZE, 0}, {}}, IsTransparencySet(TO_BRIDGES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
|
if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && !IsInvisibilitySet(TO_BRIDGES) && HasTunnelBridgeReservation(rampnorth)) {
|
||||||
if (rti->UsesOverlay()) {
|
if (rti->UsesOverlay()) {
|
||||||
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RTSG_OVERLAY);
|
||||||
AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
|
AddSortableSpriteToDraw(overlay + RTO_X + axis, PALETTE_CRASH, ti->x, ti->y, bridge_z, {{}, {TILE_SIZE, TILE_SIZE, 0}, {}}, IsTransparencySet(TO_BRIDGES));
|
||||||
} else {
|
} else {
|
||||||
AddSortableSpriteToDraw(axis == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, bridge_z, IsTransparencySet(TO_BRIDGES));
|
AddSortableSpriteToDraw(axis == AXIS_X ? rti->base_sprites.single_x : rti->base_sprites.single_y, PALETTE_CRASH, ti->x, ti->y, bridge_z, {{}, {TILE_SIZE, TILE_SIZE, 0}, {}}, IsTransparencySet(TO_BRIDGES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1626,10 +1654,10 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
||||||
if (!IsInvisibilitySet(TO_BRIDGES)) {
|
if (!IsInvisibilitySet(TO_BRIDGES)) {
|
||||||
if (axis == AXIS_X) {
|
if (axis == AXIS_X) {
|
||||||
y += 12;
|
y += 12;
|
||||||
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
|
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{0, 3, BRIDGE_Z_START}, {TILE_SIZE, 1, 40}, {0, -3, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
|
||||||
} else {
|
} else {
|
||||||
x += 12;
|
x += 12;
|
||||||
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
|
if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, z, {{3, 0, BRIDGE_Z_START}, {1, TILE_SIZE, 40}, {-3, 0, -BRIDGE_Z_START}}, IsTransparencySet(TO_BRIDGES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1109,8 +1109,7 @@ static void DoDrawVehicle(const Vehicle *v)
|
||||||
for (uint i = 0; i < v->sprite_cache.sprite_seq.count; ++i) {
|
for (uint i = 0; i < v->sprite_cache.sprite_seq.count; ++i) {
|
||||||
PaletteID pal2 = v->sprite_cache.sprite_seq.seq[i].pal;
|
PaletteID pal2 = v->sprite_cache.sprite_seq.seq[i].pal;
|
||||||
if (!pal2 || v->vehstatus.Test(VehState::Crashed)) pal2 = pal;
|
if (!pal2 || v->vehstatus.Test(VehState::Crashed)) pal2 = pal;
|
||||||
AddSortableSpriteToDraw(v->sprite_cache.sprite_seq.seq[i].sprite, pal2, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
|
AddSortableSpriteToDraw(v->sprite_cache.sprite_seq.seq[i].sprite, pal2, v->x_pos, v->y_pos, v->z_pos, v->bounds, shadowed);
|
||||||
v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
|
|
||||||
}
|
}
|
||||||
EndSpriteCombine();
|
EndSpriteCombine();
|
||||||
}
|
}
|
||||||
|
@ -1674,12 +1673,24 @@ void Vehicle::UpdateBoundingBoxCoordinates(bool update_cache) const
|
||||||
Rect new_coord;
|
Rect new_coord;
|
||||||
this->sprite_cache.sprite_seq.GetBounds(&new_coord);
|
this->sprite_cache.sprite_seq.GetBounds(&new_coord);
|
||||||
|
|
||||||
Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
|
/* z-bounds are not used. */
|
||||||
|
Point pt = RemapCoords(this->x_pos + this->bounds.origin.x + this->bounds.offset.x, this->y_pos + this->bounds.origin.y + this->bounds.offset.y, this->z_pos);
|
||||||
new_coord.left += pt.x;
|
new_coord.left += pt.x;
|
||||||
new_coord.top += pt.y;
|
new_coord.top += pt.y;
|
||||||
new_coord.right += pt.x + 2 * ZOOM_BASE;
|
new_coord.right += pt.x + 2 * ZOOM_BASE;
|
||||||
new_coord.bottom += pt.y + 2 * ZOOM_BASE;
|
new_coord.bottom += pt.y + 2 * ZOOM_BASE;
|
||||||
|
|
||||||
|
extern bool _draw_bounding_boxes;
|
||||||
|
if (_draw_bounding_boxes) {
|
||||||
|
int x = this->x_pos + this->bounds.origin.x;
|
||||||
|
int y = this->y_pos + this->bounds.origin.y;
|
||||||
|
int z = this->z_pos + this->bounds.origin.z;
|
||||||
|
new_coord.left = std::min(new_coord.left, RemapCoords(x + bounds.extent.x, y, z).x);
|
||||||
|
new_coord.right = std::max(new_coord.right, RemapCoords(x, y + bounds.extent.y, z).x + 1);
|
||||||
|
new_coord.top = std::min(new_coord.top, RemapCoords(x, y, z + bounds.extent.z).y);
|
||||||
|
new_coord.bottom = std::max(new_coord.bottom, RemapCoords(x + bounds.extent.x, y + bounds.extent.y, z).y + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (update_cache) {
|
if (update_cache) {
|
||||||
/*
|
/*
|
||||||
* If the old coordinates are invalid, set the cache to the new coordinates for correct
|
* If the old coordinates are invalid, set the cache to the new coordinates for correct
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef VEHICLE_BASE_H
|
#ifndef VEHICLE_BASE_H
|
||||||
#define VEHICLE_BASE_H
|
#define VEHICLE_BASE_H
|
||||||
|
|
||||||
|
#include "sprite.h"
|
||||||
#include "track_type.h"
|
#include "track_type.h"
|
||||||
#include "command_type.h"
|
#include "command_type.h"
|
||||||
#include "order_base.h"
|
#include "order_base.h"
|
||||||
|
@ -293,13 +294,7 @@ public:
|
||||||
* 0xff == reserved for another custom sprite
|
* 0xff == reserved for another custom sprite
|
||||||
*/
|
*/
|
||||||
uint8_t spritenum = 0;
|
uint8_t spritenum = 0;
|
||||||
uint8_t x_extent = 0; ///< x-extent of vehicle bounding box
|
SpriteBounds bounds{}; ///< Bounding box of vehicle.
|
||||||
uint8_t y_extent = 0; ///< y-extent of vehicle bounding box
|
|
||||||
uint8_t z_extent = 0; ///< z-extent of vehicle bounding box
|
|
||||||
int8_t x_bb_offs = 0; ///< x offset of vehicle bounding box
|
|
||||||
int8_t y_bb_offs = 0; ///< y offset of vehicle bounding box
|
|
||||||
int8_t x_offs = 0; ///< x offset for vehicle sprite
|
|
||||||
int8_t y_offs = 0; ///< y offset for vehicle sprite
|
|
||||||
EngineID engine_type = EngineID::Invalid(); ///< The type of engine used for this vehicle.
|
EngineID engine_type = EngineID::Invalid(); ///< The type of engine used for this vehicle.
|
||||||
|
|
||||||
TextEffectID fill_percent_te_id = INVALID_TE_ID; ///< a text-effect id to a loading indicator object
|
TextEffectID fill_percent_te_id = INVALID_TE_ID; ///< a text-effect id to a loading indicator object
|
||||||
|
|
|
@ -660,12 +660,17 @@ static void AddCombinedSprite(SpriteID image, PaletteID pal, int x, int y, int z
|
||||||
* @param bb_offset_z bounding box extent towards negative Z (world)
|
* @param bb_offset_z bounding box extent towards negative Z (world)
|
||||||
* @param sub Only draw a part of the sprite.
|
* @param sub Only draw a part of the sprite.
|
||||||
*/
|
*/
|
||||||
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
|
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
|
||||||
{
|
{
|
||||||
int32_t left, right, top, bottom;
|
int32_t left, right, top, bottom;
|
||||||
|
|
||||||
assert((image & SPRITE_MASK) < MAX_SPRITES);
|
assert((image & SPRITE_MASK) < MAX_SPRITES);
|
||||||
|
|
||||||
|
/* Move to bounding box. */
|
||||||
|
x += bounds.origin.x;
|
||||||
|
y += bounds.origin.y;
|
||||||
|
z += bounds.origin.z;
|
||||||
|
|
||||||
/* make the sprites transparent with the right palette */
|
/* make the sprites transparent with the right palette */
|
||||||
if (transparent) {
|
if (transparent) {
|
||||||
SetBit(image, PALETTE_MODIFIER_TRANSPARENT);
|
SetBit(image, PALETTE_MODIFIER_TRANSPARENT);
|
||||||
|
@ -673,21 +678,21 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vd.combine_sprites == SPRITE_COMBINE_ACTIVE) {
|
if (_vd.combine_sprites == SPRITE_COMBINE_ACTIVE) {
|
||||||
AddCombinedSprite(image, pal, x, y, z, sub);
|
AddCombinedSprite(image, pal, x + bounds.offset.x, y + bounds.offset.y, z + bounds.offset.z, sub);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vd.last_child = LAST_CHILD_NONE;
|
_vd.last_child = LAST_CHILD_NONE;
|
||||||
|
|
||||||
Point pt = RemapCoords(x, y, z);
|
Point pt = RemapCoords(x + bounds.offset.x, y + bounds.offset.y, z + bounds.offset.z);
|
||||||
int tmp_left, tmp_top, tmp_x = pt.x, tmp_y = pt.y;
|
int tmp_left, tmp_top, tmp_x = pt.x, tmp_y = pt.y;
|
||||||
|
|
||||||
/* Compute screen extents of sprite */
|
/* Compute screen extents of sprite */
|
||||||
if (image == SPR_EMPTY_BOUNDING_BOX) {
|
if (image == SPR_EMPTY_BOUNDING_BOX) {
|
||||||
left = tmp_left = RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x;
|
left = tmp_left = RemapCoords(x + bounds.extent.x, y, z).x;
|
||||||
right = RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1;
|
right = RemapCoords(x, y + bounds.extent.y, z).x + 1;
|
||||||
top = tmp_top = RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y;
|
top = tmp_top = RemapCoords(x, y, z + bounds.extent.z).y;
|
||||||
bottom = RemapCoords(x + w , y + h , z + bb_offset_z).y + 1;
|
bottom = RemapCoords(x + bounds.extent.x, y + bounds.extent.y, z).y + 1;
|
||||||
} else {
|
} else {
|
||||||
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
|
const Sprite *spr = GetSprite(image & SPRITE_MASK, SpriteType::Normal);
|
||||||
left = tmp_left = (pt.x += spr->x_offs);
|
left = tmp_left = (pt.x += spr->x_offs);
|
||||||
|
@ -698,10 +703,10 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
|
||||||
|
|
||||||
if (_draw_bounding_boxes && (image != SPR_EMPTY_BOUNDING_BOX)) {
|
if (_draw_bounding_boxes && (image != SPR_EMPTY_BOUNDING_BOX)) {
|
||||||
/* Compute maximal extents of sprite and its bounding box */
|
/* Compute maximal extents of sprite and its bounding box */
|
||||||
left = std::min(left , RemapCoords(x + w , y + bb_offset_y, z + bb_offset_z).x);
|
left = std::min(left , RemapCoords(x + bounds.extent.x, y, z).x);
|
||||||
right = std::max(right , RemapCoords(x + bb_offset_x, y + h , z + bb_offset_z).x + 1);
|
right = std::max(right , RemapCoords(x, y + bounds.extent.y, z).x + 1);
|
||||||
top = std::min(top , RemapCoords(x + bb_offset_x, y + bb_offset_y, z + dz ).y);
|
top = std::min(top , RemapCoords(x, y, z + bounds.extent.z).y);
|
||||||
bottom = std::max(bottom, RemapCoords(x + w , y + h , z + bb_offset_z).y + 1);
|
bottom = std::max(bottom, RemapCoords(x + bounds.extent.x, y + bounds.extent.y, z).y + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do not add the sprite to the viewport, if it is outside */
|
/* Do not add the sprite to the viewport, if it is outside */
|
||||||
|
@ -722,14 +727,14 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w,
|
||||||
ps.image = image;
|
ps.image = image;
|
||||||
ps.pal = pal;
|
ps.pal = pal;
|
||||||
ps.sub = sub;
|
ps.sub = sub;
|
||||||
ps.xmin = x + bb_offset_x;
|
ps.xmin = x;
|
||||||
ps.xmax = x + std::max(bb_offset_x, w) - 1;
|
ps.xmax = x + bounds.extent.x - 1;
|
||||||
|
|
||||||
ps.ymin = y + bb_offset_y;
|
ps.ymin = y;
|
||||||
ps.ymax = y + std::max(bb_offset_y, h) - 1;
|
ps.ymax = y + bounds.extent.y - 1;
|
||||||
|
|
||||||
ps.zmin = z + bb_offset_z;
|
ps.zmin = z;
|
||||||
ps.zmax = z + std::max(bb_offset_z, dz) - 1;
|
ps.zmax = z + bounds.extent.z - 1;
|
||||||
|
|
||||||
ps.first_child = LAST_CHILD_NONE;
|
ps.first_child = LAST_CHILD_NONE;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define VIEWPORT_FUNC_H
|
#define VIEWPORT_FUNC_H
|
||||||
|
|
||||||
#include "gfx_type.h"
|
#include "gfx_type.h"
|
||||||
|
#include "sprite.h"
|
||||||
#include "viewport_type.h"
|
#include "viewport_type.h"
|
||||||
#include "window_type.h"
|
#include "window_type.h"
|
||||||
#include "tile_map.h"
|
#include "tile_map.h"
|
||||||
|
@ -51,10 +52,14 @@ void OffsetGroundSprite(int x, int y);
|
||||||
|
|
||||||
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0);
|
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0);
|
||||||
void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32_t x, int32_t y, int z, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0);
|
void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32_t x, int32_t y, int z, const SubSprite *sub = nullptr, int extra_offs_x = 0, int extra_offs_y = 0);
|
||||||
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent = false, int bb_offset_x = 0, int bb_offset_y = 0, int bb_offset_z = 0, const SubSprite *sub = nullptr);
|
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent = false, const SubSprite *sub = nullptr);
|
||||||
void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool transparent = false, const SubSprite *sub = nullptr, bool scale = true, bool relative = true);
|
void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool transparent = false, const SubSprite *sub = nullptr, bool scale = true, bool relative = true);
|
||||||
std::string *ViewportAddString(const DrawPixelInfo *dpi, const ViewportSign *sign, ViewportStringFlags flags, Colours colour);
|
std::string *ViewportAddString(const DrawPixelInfo *dpi, const ViewportSign *sign, ViewportStringFlags flags, Colours colour);
|
||||||
|
|
||||||
|
inline void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, const PointXyz<int32_t> &world, const SpriteBounds &bounds, bool transparent = false, const SubSprite *sub = nullptr)
|
||||||
|
{
|
||||||
|
AddSortableSpriteToDraw(image, pal, world.x, world.y, world.z, bounds, transparent, sub);
|
||||||
|
}
|
||||||
|
|
||||||
void StartSpriteCombine();
|
void StartSpriteCombine();
|
||||||
void EndSpriteCombine();
|
void EndSpriteCombine();
|
||||||
|
|
|
@ -89,8 +89,8 @@ enum ZoomStateChange : uint8_t {
|
||||||
* z=6 reserved, currently unused.
|
* z=6 reserved, currently unused.
|
||||||
* z=7 Z separator between bridge/tunnel and the things under/above it.
|
* z=7 Z separator between bridge/tunnel and the things under/above it.
|
||||||
*/
|
*/
|
||||||
static const uint BB_HEIGHT_UNDER_BRIDGE = 6; ///< Everything that can be built under low bridges, must not exceed this Z height.
|
static constexpr int BB_HEIGHT_UNDER_BRIDGE = 6; ///< Everything that can be built under low bridges, must not exceed this Z height.
|
||||||
static const uint BB_Z_SEPARATOR = 7; ///< Separates the bridge/tunnel from the things under/above it.
|
static constexpr int BB_Z_SEPARATOR = 7; ///< Separates the bridge/tunnel from the things under/above it.
|
||||||
|
|
||||||
/** Viewport place method (type of highlighted area and placed objects) */
|
/** Viewport place method (type of highlighted area and placed objects) */
|
||||||
enum ViewportPlaceMethod : uint8_t {
|
enum ViewportPlaceMethod : uint8_t {
|
||||||
|
|
|
@ -806,11 +806,7 @@ static void DrawWaterTileStruct(const TileInfo *ti, std::span<const DrawTileSeqS
|
||||||
for (const DrawTileSeqStruct &dtss : seq) {
|
for (const DrawTileSeqStruct &dtss : seq) {
|
||||||
uint tile_offs = offset + dtss.image.sprite;
|
uint tile_offs = offset + dtss.image.sprite;
|
||||||
if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
|
if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
|
||||||
AddSortableSpriteToDraw(base + tile_offs, palette,
|
AddSortableSpriteToDraw(base + tile_offs, palette, *ti, dtss, IsTransparencySet(TO_BUILDINGS));
|
||||||
ti->x + dtss.delta_x, ti->y + dtss.delta_y,
|
|
||||||
dtss.size_x, dtss.size_y,
|
|
||||||
dtss.size_z, ti->z + dtss.delta_z,
|
|
||||||
IsTransparencySet(TO_BUILDINGS));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue