1
0
mirror of https://github.com/OpenTTD/OpenTTD synced 2026-01-04 11:02:34 +01:00

Codechange: Extract function to draw custom rail station foundations. (#14492)

This commit is contained in:
Peter Nelson
2025-08-06 23:46:53 +01:00
committed by GitHub
parent 73a69fd171
commit 1ccbd735d8

View File

@@ -3073,6 +3073,74 @@ bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrack
return true;
}
/**
* Draw custom station foundations for a NewGRF station if provided.
* @param statspec Custom NewGRF station.
* @param st Station being drawn.
* @param ti Tile being drawn.
* @param gfx Graphics layout for tile.
* @return true iff a custom foundation was drawn.
*/
static bool DrawCustomStationFoundations(const StationSpec *statspec, BaseStation *st, TileInfo *ti, StationGfx gfx)
{
if (statspec == nullptr || !statspec->flags.Test(StationSpecFlag::CustomFoundations)) return false;
/* Station has custom foundations.
* Check whether the foundation continues beyond the tile's upper sides. */
uint edge_info = 0;
auto [slope, z] = GetFoundationPixelSlope(ti->tile);
if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0);
if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1);
SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, gfx, edge_info);
if (image == 0) return false;
if (statspec->flags.Test(StationSpecFlag::ExtendedFoundations)) {
/* Station provides extended foundations. */
static constexpr uint8_t foundation_parts[] = {
UINT8_MAX, UINT8_MAX, UINT8_MAX, 0, // Invalid, Invalid, Invalid, SLOPE_SW
UINT8_MAX, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
UINT8_MAX, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
7, 8, 9, // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
};
assert(ti->tileh < std::size(foundation_parts));
if (foundation_parts[ti->tileh] == UINT8_MAX) return false;
AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}});
} else {
/* Draw simple foundations, built up from 8 possible foundation sprites.
* Each set bit represents one of the eight composite sprites to be drawn.
* 'Invalid' entries will not drawn but are included for completeness. */
static constexpr uint8_t composite_foundation_parts[] = {
0b0000'0000, 0b1101'0001, 0b1110'0100, 0b1110'0000, // Invalid, Invalid, Invalid, SLOPE_SW
0b1100'1010, 0b1100'1001, 0b1100'0100, 0b1100'0000, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
0b1101'0010, 0b1001'0001, 0b1110'0100, 0b1010'0000, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
0b0100'1010, 0b0000'1001, 0b0100'0100, // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
};
assert(ti->tileh < std::size(composite_foundation_parts));
uint8_t parts = composite_foundation_parts[ti->tileh];
/* If foundations continue beyond the tile's upper sides then mask out the last two pieces. */
if (HasBit(edge_info, 0)) ClrBit(parts, 6);
if (HasBit(edge_info, 1)) ClrBit(parts, 7);
/* We always have to draw at least one sprite, so if we have no parts to draw fall back to default foundation. */
if (parts == 0) return false;
StartSpriteCombine();
for (uint i : SetBitIterator(parts)) {
AddSortableSpriteToDraw(image + i, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}});
}
EndSpriteCombine();
}
OffsetGroundSprite(0, -static_cast<int>(TILE_HEIGHT));
ti->z += ApplyPixelFoundationToSlope(FOUNDATION_LEVELED, ti->tileh);
return true;
}
static void DrawTile_Station(TileInfo *ti)
{
const NewGRFSpriteLayout *layout = nullptr;
@@ -3164,70 +3232,7 @@ static void DrawTile_Station(TileInfo *ti)
/* don't show foundation for docks */
if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) {
if (statspec != nullptr && statspec->flags.Test(StationSpecFlag::CustomFoundations)) {
/* Station has custom foundations.
* Check whether the foundation continues beyond the tile's upper sides. */
uint edge_info = 0;
auto [slope, z] = GetFoundationPixelSlope(ti->tile);
if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0);
if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1);
SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, tile_layout, edge_info);
if (image == 0) goto draw_default_foundation;
if (statspec->flags.Test(StationSpecFlag::ExtendedFoundations)) {
/* Station provides extended foundations. */
static const uint8_t foundation_parts[] = {
0, 0, 0, 0, // Invalid, Invalid, Invalid, SLOPE_SW
0, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE
0, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS
7, 8, 9 // SLOPE_NE, SLOPE_ENW, SLOPE_SEN
};
AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, 7}, {}});
} else {
/* Draw simple foundations, built up from 8 possible foundation sprites. */
/* Each set bit represents one of the eight composite sprites to be drawn.
* 'Invalid' entries will not drawn but are included for completeness. */
static const uint8_t composite_foundation_parts[] = {
/* Invalid (00000000), Invalid (11010001), Invalid (11100100), SLOPE_SW (11100000) */
0x00, 0xD1, 0xE4, 0xE0,
/* Invalid (11001010), SLOPE_EW (11001001), SLOPE_SE (11000100), SLOPE_WSE (11000000) */
0xCA, 0xC9, 0xC4, 0xC0,
/* Invalid (11010010), SLOPE_NW (10010001), SLOPE_NS (11100100), SLOPE_NWS (10100000) */
0xD2, 0x91, 0xE4, 0xA0,
/* SLOPE_NE (01001010), SLOPE_ENW (00001001), SLOPE_SEN (01000100) */
0x4A, 0x09, 0x44
};
uint8_t parts = composite_foundation_parts[ti->tileh];
/* If foundations continue beyond the tile's upper sides then
* mask out the last two pieces. */
if (HasBit(edge_info, 0)) ClrBit(parts, 6);
if (HasBit(edge_info, 1)) ClrBit(parts, 7);
if (parts == 0) {
/* We always have to draw at least one sprite to make sure there is a boundingbox and a sprite with the
* correct offset for the childsprites.
* So, draw the (completely empty) sprite of the default foundations. */
goto draw_default_foundation;
}
StartSpriteCombine();
for (int i = 0; i < 8; i++) {
if (HasBit(parts, i)) {
AddSortableSpriteToDraw(image + i, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, 7}, {}});
}
}
EndSpriteCombine();
}
OffsetGroundSprite(0, -8);
ti->z += ApplyPixelFoundationToSlope(FOUNDATION_LEVELED, ti->tileh);
} else {
draw_default_foundation:
if (!DrawCustomStationFoundations(statspec, st, ti, tile_layout)) {
DrawFoundation(ti, FOUNDATION_LEVELED);
}
}