* 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. */
| 3205 | * @return true iff a custom foundation was drawn. |
| 3206 | */ |
| 3207 | static bool DrawCustomStationFoundations(const StationSpec *statspec, BaseStation *st, TileInfo *ti, StationGfx gfx) |
| 3208 | { |
| 3209 | if (statspec == nullptr || !statspec->flags.Test(StationSpecFlag::CustomFoundations)) return false; |
| 3210 | |
| 3211 | /* Station has custom foundations. |
| 3212 | * Check whether the foundation continues beyond the tile's upper sides. */ |
| 3213 | uint edge_info = 0; |
| 3214 | auto [slope, z] = GetFoundationPixelSlope(ti->tile); |
| 3215 | if (!HasFoundationNW(ti->tile, slope, z)) SetBit(edge_info, 0); |
| 3216 | if (!HasFoundationNE(ti->tile, slope, z)) SetBit(edge_info, 1); |
| 3217 | |
| 3218 | SpriteID image = GetCustomStationFoundationRelocation(statspec, st, ti->tile, gfx, edge_info); |
| 3219 | if (image == 0) return false; |
| 3220 | |
| 3221 | if (statspec->flags.Test(StationSpecFlag::ExtendedFoundations)) { |
| 3222 | /* Station provides extended foundations. */ |
| 3223 | static constexpr uint8_t foundation_parts[] = { |
| 3224 | UINT8_MAX, UINT8_MAX, UINT8_MAX, 0, // Invalid, Invalid, Invalid, SLOPE_SW |
| 3225 | UINT8_MAX, 1, 2, 3, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE |
| 3226 | UINT8_MAX, 4, 5, 6, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS |
| 3227 | 7, 8, 9, // SLOPE_NE, SLOPE_ENW, SLOPE_SEN |
| 3228 | }; |
| 3229 | assert(ti->tileh < std::size(foundation_parts)); |
| 3230 | if (foundation_parts[ti->tileh] == UINT8_MAX) return false; |
| 3231 | |
| 3232 | AddSortableSpriteToDraw(image + foundation_parts[ti->tileh], PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}}); |
| 3233 | } else { |
| 3234 | /* Draw simple foundations, built up from 8 possible foundation sprites. |
| 3235 | * Each set bit represents one of the eight composite sprites to be drawn. |
| 3236 | * 'Invalid' entries will not drawn but are included for completeness. */ |
| 3237 | static constexpr uint8_t composite_foundation_parts[] = { |
| 3238 | 0b0000'0000, 0b1101'0001, 0b1110'0100, 0b1110'0000, // Invalid, Invalid, Invalid, SLOPE_SW |
| 3239 | 0b1100'1010, 0b1100'1001, 0b1100'0100, 0b1100'0000, // Invalid, SLOPE_EW, SLOPE_SE, SLOPE_WSE |
| 3240 | 0b1101'0010, 0b1001'0001, 0b1110'0100, 0b1010'0000, // Invalid, SLOPE_NW, SLOPE_NS, SLOPE_NWS |
| 3241 | 0b0100'1010, 0b0000'1001, 0b0100'0100, // SLOPE_NE, SLOPE_ENW, SLOPE_SEN |
| 3242 | }; |
| 3243 | assert(ti->tileh < std::size(composite_foundation_parts)); |
| 3244 | |
| 3245 | uint8_t parts = composite_foundation_parts[ti->tileh]; |
| 3246 | |
| 3247 | /* If foundations continue beyond the tile's upper sides then mask out the last two pieces. */ |
| 3248 | if (HasBit(edge_info, 0)) ClrBit(parts, 6); |
| 3249 | if (HasBit(edge_info, 1)) ClrBit(parts, 7); |
| 3250 | |
| 3251 | /* We always have to draw at least one sprite, so if we have no parts to draw fall back to default foundation. */ |
| 3252 | if (parts == 0) return false; |
| 3253 | |
| 3254 | StartSpriteCombine(); |
| 3255 | for (uint i : SetBitIterator(parts)) { |
| 3256 | AddSortableSpriteToDraw(image + i, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT - 1}, {}}); |
| 3257 | } |
| 3258 | EndSpriteCombine(); |
| 3259 | } |
| 3260 | |
| 3261 | OffsetGroundSprite(0, -static_cast<int>(TILE_HEIGHT)); |
| 3262 | ti->z += ApplyPixelFoundationToSlope(FOUNDATION_LEVELED, ti->tileh); |
| 3263 | |
| 3264 | return true; |
no test coverage detected