1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-02-01 19:25:12 +01:00

Merge pull request #21305 from Gymnasiast/refactor/path-support-drawing

Refactor path support drawing
This commit is contained in:
Michael Steenbeek
2024-02-01 12:54:27 +01:00
committed by GitHub
3 changed files with 445 additions and 507 deletions

View File

@@ -1251,14 +1251,11 @@ bool MetalBSupportsPaintSetup(
*
* @return Whether supports were drawn
*/
bool PathASupportsPaintSetup(
PaintSession& session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
const FootpathPaintInfo& pathPaintInfo, bool* underground)
bool PathBoxSupportsPaintSetup(
PaintSession& session, WoodenSupportSubType supportType, bool isSloped, Direction slopeRotation, int32_t height,
ImageId imageTemplate, const FootpathPaintInfo& pathPaintInfo)
{
if (underground != nullptr)
{
*underground = false; // AND
}
auto supportOrientationOffset = (supportType == WoodenSupportSubType::NwSe) ? 24 : 0;
if (!(session.Flags & PaintSessionFlags::PassedSurface))
{
@@ -1278,8 +1275,6 @@ bool PathASupportsPaintSetup(
int32_t supportLength = height - baseHeight;
if (supportLength < 0)
{
if (underground != nullptr)
*underground = true; // STC
return false;
}
@@ -1299,12 +1294,10 @@ bool PathASupportsPaintSetup(
heightSteps -= 2;
if (heightSteps < 0)
{
if (underground != nullptr)
*underground = true; // STC
return false;
}
uint32_t imageId = (supportType * 24) + word_97B3C4[session.Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
uint32_t imageId = supportOrientationOffset + word_97B3C4[session.Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
+ pathPaintInfo.BridgeImageId;
PaintAddImageAsParent(
@@ -1322,12 +1315,10 @@ bool PathASupportsPaintSetup(
heightSteps -= 1;
if (heightSteps < 0)
{
if (underground != nullptr)
*underground = true; // STC
return false;
}
uint32_t ebx = (supportType * 24) + word_97B3C4[session.Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
uint32_t ebx = supportOrientationOffset + word_97B3C4[session.Support.slope & TILE_ELEMENT_SURFACE_SLOPE_MASK]
+ pathPaintInfo.BridgeImageId;
PaintAddImageAsParent(
@@ -1341,7 +1332,7 @@ bool PathASupportsPaintSetup(
{
if (baseHeight & 0x10 || heightSteps == 1 || baseHeight + WATER_HEIGHT_STEP == session.WaterHeight)
{
uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 23;
uint32_t imageId = supportOrientationOffset + pathPaintInfo.BridgeImageId + 23;
PaintAddImageAsParent(
session, imageTemplate.WithIndex(imageId), { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 1) ? 7 : 12) });
@@ -1351,7 +1342,7 @@ bool PathASupportsPaintSetup(
}
else
{
uint32_t imageId = (supportType * 24) + pathPaintInfo.BridgeImageId + 22;
uint32_t imageId = supportOrientationOffset + pathPaintInfo.BridgeImageId + 22;
PaintAddImageAsParent(
session, imageTemplate.WithIndex(imageId), { 0, 0, baseHeight }, { 32, 32, ((heightSteps == 2) ? 23 : 28) });
@@ -1361,13 +1352,11 @@ bool PathASupportsPaintSetup(
}
}
if (special != 0)
if (isSloped)
{
uint16_t specialIndex = (special - 1) & 0xFFFF;
ImageIndex imageIndex = pathPaintInfo.BridgeImageId + 55 + slopeRotation;
ImageIndex imageIndex = pathPaintInfo.BridgeImageId + 55 + specialIndex;
const UnkSupportsDescriptor& supportsDesc = Byte98D8D4[specialIndex];
const UnkSupportsDescriptor& supportsDesc = Byte98D8D4[slopeRotation];
auto boundBox = supportsDesc.bounding_box;
boundBox.offset.z += baseHeight;
@@ -1388,9 +1377,6 @@ bool PathASupportsPaintSetup(
}
}
if (underground != nullptr)
*underground = false; // AND
return hasSupports;
}
@@ -1406,10 +1392,12 @@ bool PathASupportsPaintSetup(
*
* @return Whether supports were drawn
*/
bool PathBSupportsPaintSetup(
PaintSession& session, int32_t segment, int32_t special, int32_t height, ImageId imageTemplate,
bool PathPoleSupportsPaintSetup(
PaintSession& session, MetalSupportPlace supportPlace, bool isSloped, int32_t height, ImageId imageTemplate,
const FootpathPaintInfo& pathPaintInfo)
{
auto segment = EnumValue(supportPlace);
SupportHeight* supportSegments = session.SupportSegments;
if (!(session.Flags & PaintSessionFlags::PassedSurface))
@@ -1523,13 +1511,13 @@ bool PathBSupportsPaintSetup(
supportSegments[segment].height = 0xFFFF;
supportSegments[segment].slope = 0x20;
if (special != 0)
if (isSloped)
{
int16_t si = special + baseHeight;
int16_t si = baseHeight + COORDS_Z_STEP;
while (true)
{
int16_t z = baseHeight + 16;
int16_t z = baseHeight + (2 * COORDS_Z_STEP);
if (z > si)
{
z = si;

View File

@@ -145,11 +145,11 @@ bool MetalASupportsPaintSetup(
bool MetalBSupportsPaintSetup(
PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, int32_t special, int32_t height,
ImageId imageTemplate);
bool PathASupportsPaintSetup(
PaintSession& session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
const FootpathPaintInfo& pathPaintInfo, bool* underground);
bool PathBSupportsPaintSetup(
PaintSession& session, int32_t supportType, int32_t special, int32_t height, ImageId imageTemplate,
bool PathBoxSupportsPaintSetup(
PaintSession& session, WoodenSupportSubType supportType, bool isSloped, Direction slopeRotation, int32_t height,
ImageId imageTemplate, const FootpathPaintInfo& pathPaintInfo);
bool PathPoleSupportsPaintSetup(
PaintSession& session, MetalSupportPlace supportPlace, bool isSloped, int32_t height, ImageId imageTemplate,
const FootpathPaintInfo& pathPaintInfo);
void DrawSupportsSideBySide(
PaintSession& session, Direction direction, uint16_t height, ImageId colour, MetalSupportType type, int32_t special = 0);

View File

@@ -82,8 +82,23 @@ static constexpr BoundBoxXY stru_98D804[] = {
{ { 0, 0 }, { 32, 32 } },
};
static constexpr uint8_t Byte98D8A4[] = {
0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0
static constexpr WoodenSupportSubType PathSupportOrientation[] = {
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NeSw,
WoodenSupportSubType::NwSe,
WoodenSupportSubType::NeSw,
};
// clang-format on
@@ -94,258 +109,269 @@ void PathPaintPoleSupport(
PaintSession& session, const PathElement& pathElement, int16_t height, const FootpathPaintInfo& pathPaintInfo,
bool hasSupports, ImageId imageTemplate, ImageId sceneryImageTemplate);
/**
* rct2: 0x006A4101
* @param tile_element (esi)
*/
static void PathPaintFencesAndQueueBanners(
PaintSession& session, const PathElement& pathElement, uint16_t height, uint32_t connectedEdges, bool hasSupports,
const FootpathPaintInfo& pathPaintInfo, ImageId imageTemplate)
static void PathPaintQueueBanner(
PaintSession& session, const PathElement& pathElement, uint16_t height, const FootpathPaintInfo& pathPaintInfo,
ImageId imageTemplate)
{
PROFILED_FUNCTION();
auto imageId = imageTemplate.WithIndex(pathPaintInfo.RailingsImageId);
if (pathElement.IsQueue())
uint8_t direction = pathElement.GetQueueBannerDirection();
// Draw ride sign
session.InteractionType = ViewportInteractionItem::Ride;
if (pathElement.IsSloped())
{
if (pathElement.IsSloped())
if (pathElement.GetSlopeDirection() == direction)
height += COORDS_Z_STEP * 2;
}
direction += session.CurrentRotation;
direction &= 3;
CoordsXYZ boundBoxOffsets = CoordsXYZ(BannerBoundBoxes[direction][0], height + 2);
imageId = imageId.WithIndexOffset(28 + (direction << 1));
// Draw pole in the back
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { boundBoxOffsets, { 1, 1, 21 } });
// Draw pole in the front and banner
boundBoxOffsets.x = BannerBoundBoxes[direction][1].x;
boundBoxOffsets.y = BannerBoundBoxes[direction][1].y;
imageId = imageId.WithIndexOffset(1);
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { boundBoxOffsets, { 1, 1, 21 } });
direction--;
// If text shown
auto ride = GetRide(pathElement.GetRideIndex());
if (direction < 2 && ride != nullptr && !imageTemplate.IsRemap())
{
uint16_t scrollingMode = pathPaintInfo.ScrollingMode;
scrollingMode += direction;
auto ft = Formatter();
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
{
switch ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
{
case 0:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(22), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(22), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 1:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(21), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(21), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
case 2:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(23), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(23), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 3:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(20), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(20), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
}
ft.Add<StringId>(STR_RIDE_ENTRANCE_NAME);
ride->FormatNameTo(ft);
}
else
{
const auto pathEdges = connectedEdges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK;
switch (pathEdges)
{
case 0b0001:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
break;
case 0b0010:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
break;
case 0b0011:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 28, 0, height },
{ { 28, 4, height + 2 }, { 1, 28, 7 } }); // bound_box_offset_y seems to be a bug
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
break;
case 0b0100:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
break;
case 0b0101:
ft.Add<StringId>(STR_RIDE_ENTRANCE_CLOSED);
}
if (gConfigGeneral.UpperCaseBanners)
{
FormatStringToUpper(
gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
}
else
{
FormatStringLegacy(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
}
uint16_t stringWidth = GfxGetStringWidth(gCommonStringFormatBuffer, FontStyle::Tiny);
uint16_t scroll = stringWidth > 0 ? (GetGameState().CurrentTicks / 2) % stringWidth : 0;
PaintAddImageAsChild(
session, ScrollingTextSetup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode, COLOUR_BLACK),
{ 0, 0, height + 7 }, { boundBoxOffsets, { 1, 1, 21 } });
}
session.InteractionType = ViewportInteractionItem::Footpath;
if (imageTemplate.IsRemap())
{
session.InteractionType = ViewportInteractionItem::None;
}
}
static void PathPaintSlopedFences(
PaintSession& session, const PathElement& pathElement, uint16_t height, ImageId imageId, bool isQueue)
{
auto queueOffset = isQueue ? 14 : 0;
switch ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
{
case 0:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(8 + queueOffset), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(8 + queueOffset), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 1:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(7 + queueOffset), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(7 + queueOffset), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
case 2:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(9 + queueOffset), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(9 + queueOffset), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 3:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(6 + queueOffset), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(6 + queueOffset), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
}
}
static void PathPaintFencesAndQueueBannersQueue(
PaintSession& session, const PathElement& pathElement, uint16_t height, uint32_t connectedEdges, bool hasSupports,
const FootpathPaintInfo& pathPaintInfo, ImageId imageTemplate)
{
auto imageId = imageTemplate.WithIndex(pathPaintInfo.RailingsImageId);
if (pathElement.IsSloped())
{
PathPaintSlopedFences(session, pathElement, height, imageId, true);
}
else
{
const auto pathEdges = connectedEdges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK;
switch (pathEdges)
{
case 0b0001:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
break;
case 0b0010:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
break;
case 0b0011:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 28, 0, height },
{ { 28, 4, height + 2 }, { 1, 28, 7 } }); // bound_box_offset_y seems to be a bug
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
break;
case 0b0100:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
break;
case 0b0101:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 7 } });
break;
case 0b0110:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
break;
case 0b0111:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 7 } });
break;
case 0b0110:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(18), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 4, height }, { { 0, 4, height + 2 }, { 28, 1, 7 } });
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
break;
case 0b0111:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1000:
}
break;
case 0b1000:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
break;
case 0b1001:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
break;
case 0b1010:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 7 } });
break;
case 0b1011:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
break;
case 0b1001:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(17), { 0, 28, height }, { { 0, 28, height + 2 }, { 28, 1, 7 } });
session, imageId.WithIndexOffset(14), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
break;
case 0b1010:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1100:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 28, height },
{ { 4, 28, height + 2 }, { 28, 1, 7 } }); // bound_box_offset_x seems to be a bug
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
break;
case 0b1101:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1110:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 7 } });
break;
case 0b1011:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1100:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(16), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 28, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(19), { 0, 28, height },
{ { 4, 28, height + 2 }, { 28, 1, 7 } }); // bound_box_offset_x seems to be a bug
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
break;
case 0b1101:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(15), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1110:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(14), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
}
break;
case 0b1111:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
}
}
}
break;
case 0b1111:
if (pathElement.HasJunctionRailings())
{
PaintAddImageAsParent(
session, imageId.WithIndexOffset(24), { 0, 0, height }, { { 0, 0, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(25), { 0, 0, height }, { { 0, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(26), { 0, 0, height }, { { 28, 28, height + 2 }, { 4, 4, 7 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(27), { 0, 0, height }, { { 28, 0, height + 2 }, { 4, 4, 7 } });
}
}
if (!pathElement.HasQueueBanner() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_NO_QUEUE_BANNER))
{
return;
}
uint8_t direction = pathElement.GetQueueBannerDirection();
// Draw ride sign
session.InteractionType = ViewportInteractionItem::Ride;
if (pathElement.IsSloped())
{
if (pathElement.GetSlopeDirection() == direction)
height += COORDS_Z_STEP * 2;
}
direction += session.CurrentRotation;
direction &= 3;
CoordsXYZ boundBoxOffsets = CoordsXYZ(BannerBoundBoxes[direction][0], height + 2);
imageId = imageId.WithIndexOffset(28 + (direction << 1));
// Draw pole in the back
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { boundBoxOffsets, { 1, 1, 21 } });
// Draw pole in the front and banner
boundBoxOffsets.x = BannerBoundBoxes[direction][1].x;
boundBoxOffsets.y = BannerBoundBoxes[direction][1].y;
imageId = imageId.WithIndexOffset(1);
PaintAddImageAsParent(session, imageId, { 0, 0, height }, { boundBoxOffsets, { 1, 1, 21 } });
direction--;
// If text shown
auto ride = GetRide(pathElement.GetRideIndex());
if (direction < 2 && ride != nullptr && !imageTemplate.IsRemap())
{
uint16_t scrollingMode = pathPaintInfo.ScrollingMode;
scrollingMode += direction;
auto ft = Formatter();
if (ride->status == RideStatus::Open && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN))
{
ft.Add<StringId>(STR_RIDE_ENTRANCE_NAME);
ride->FormatNameTo(ft);
}
else
{
ft.Add<StringId>(STR_RIDE_ENTRANCE_CLOSED);
}
if (gConfigGeneral.UpperCaseBanners)
{
FormatStringToUpper(
gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
}
else
{
FormatStringLegacy(
gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_BANNER_TEXT_FORMAT, ft.Data());
}
uint16_t stringWidth = GfxGetStringWidth(gCommonStringFormatBuffer, FontStyle::Tiny);
uint16_t scroll = stringWidth > 0 ? (GetGameState().CurrentTicks / 2) % stringWidth : 0;
PaintAddImageAsChild(
session, ScrollingTextSetup(session, STR_BANNER_TEXT_FORMAT, ft, scroll, scrollingMode, COLOUR_BLACK),
{ 0, 0, height + 7 }, { boundBoxOffsets, { 1, 1, 21 } });
}
session.InteractionType = ViewportInteractionItem::Footpath;
if (imageTemplate.IsRemap())
{
session.InteractionType = ViewportInteractionItem::None;
}
return;
}
if (pathElement.HasQueueBanner() && !(pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_NO_QUEUE_BANNER))
{
PathPaintQueueBanner(session, pathElement, height, pathPaintInfo, imageTemplate);
}
}
static void PathPaintFencesAndQueueBannersNonQueue(
PaintSession& session, const PathElement& pathElement, uint16_t height, uint32_t connectedEdges, bool hasSupports,
const FootpathPaintInfo& pathPaintInfo, ImageId imageTemplate)
{
auto imageId = imageTemplate.WithIndex(pathPaintInfo.RailingsImageId);
uint32_t drawnCorners = 0;
// If the path is not drawn over the supports, then no corner sprites will be drawn (making double-width paths
// look like connected series of intersections).
@@ -357,33 +383,7 @@ static void PathPaintFencesAndQueueBanners(
auto slopeRailingsSupported = !(pathPaintInfo.SurfaceFlags & FOOTPATH_ENTRY_FLAG_NO_SLOPE_RAILINGS);
if ((hasSupports || slopeRailingsSupported) && pathElement.IsSloped())
{
switch ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
{
case 0:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(8), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(8), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 1:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(7), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(7), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
case 2:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(9), { 0, 4, height }, { { 0, 4, height + 2 }, { 32, 1, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(9), { 0, 28, height }, { { 0, 28, height + 2 }, { 32, 1, 23 } });
break;
case 3:
PaintAddImageAsParent(
session, imageId.WithIndexOffset(6), { 4, 0, height }, { { 4, 0, height + 2 }, { 1, 32, 23 } });
PaintAddImageAsParent(
session, imageId.WithIndexOffset(6), { 28, 0, height }, { { 28, 0, height + 2 }, { 1, 32, 23 } });
break;
}
PathPaintSlopedFences(session, pathElement, height, imageId, false);
}
else
{
@@ -564,6 +564,28 @@ static void PathPaintFencesAndQueueBanners(
}
}
/**
* rct2: 0x006A4101
* @param tile_element (esi)
*/
static void PathPaintFencesAndQueueBanners(
PaintSession& session, const PathElement& pathElement, uint16_t height, uint32_t connectedEdges, bool hasSupports,
const FootpathPaintInfo& pathPaintInfo, ImageId imageTemplate)
{
PROFILED_FUNCTION();
if (pathElement.IsQueue())
{
PathPaintFencesAndQueueBannersQueue(
session, pathElement, height, connectedEdges, hasSupports, pathPaintInfo, imageTemplate);
}
else
{
PathPaintFencesAndQueueBannersNonQueue(
session, pathElement, height, connectedEdges, hasSupports, pathPaintInfo, imageTemplate);
}
}
/**
* rct2: 0x006A3F61
* @param pathElement (esp[0])
@@ -819,12 +841,9 @@ void PaintPath(PaintSession& session, uint16_t height, const PathElement& tileEl
PaintLampLightEffects(session, tileElement, height);
}
void PathPaintBoxSupport(
PaintSession& session, const PathElement& pathElement, int32_t height, const FootpathPaintInfo& pathPaintInfo,
bool hasSupports, ImageId imageTemplate, ImageId sceneryImageTemplate)
static std::pair<uint8_t, uint8_t> PathPaintGetRotatedEdgesAndCorners(
const PaintSession& session, const PathElement& pathElement)
{
PROFILED_FUNCTION();
// Rol edges around rotation
uint8_t edges = ((pathElement.GetEdges() << session.CurrentRotation) & 0xF)
| (((pathElement.GetEdges()) << session.CurrentRotation) >> 4);
@@ -832,11 +851,13 @@ void PathPaintBoxSupport(
uint8_t corners = (((pathElement.GetCorners()) << session.CurrentRotation) & 0xF)
| (((pathElement.GetCorners()) << session.CurrentRotation) >> 4);
CoordsXY boundBoxOffset = stru_98D804[edges].offset;
CoordsXY boundBoxSize = stru_98D804[edges].length;
uint16_t edi = edges | (corners << 4);
return std::make_pair(edges, corners);
}
static ImageIndex PathPaintGetBaseImage(
const PaintSession& session, const PathElement& pathElement, const FootpathPaintInfo& pathPaintInfo,
uint16_t rotatedEdgesAndCorners)
{
ImageIndex surfaceBaseImageIndex = pathPaintInfo.SurfaceImageId;
if (pathElement.IsSloped())
{
@@ -846,155 +867,22 @@ void PathPaintBoxSupport(
}
else
{
surfaceBaseImageIndex += Byte98D6E0[edi];
surfaceBaseImageIndex += Byte98D6E0[rotatedEdgesAndCorners];
}
const bool hasPassedSurface = (session.Flags & PaintSessionFlags::PassedSurface) != 0;
if (!hasPassedSurface)
{
boundBoxOffset.x = 3;
boundBoxOffset.y = 3;
boundBoxSize.x = 26;
boundBoxSize.y = 26;
}
// By default, add 1 to the z bounding box to always clip above the surface
uint8_t boundingBoxZOffset = 1;
// If we are on the same tile as a straight track, add the offset 2 so we
// can clip above gravel part of the track sprite
if (session.TrackElementOnSameHeight != nullptr)
{
if (session.TrackElementOnSameHeight->AsTrack()->GetTrackType() == TrackElemType::Flat)
{
boundingBoxZOffset = 2;
}
}
if (!hasSupports || !hasPassedSurface)
{
PaintAddImageAsParent(
session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 } });
}
else
{
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
auto directionOffset
= ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
bridgeBaseImageIndex = pathPaintInfo.BridgeImageId + 51 + directionOffset;
}
else
{
bridgeBaseImageIndex = Byte98D8A4[edges] + pathPaintInfo.BridgeImageId + 49;
}
PaintAddImageAsParent(
session, imageTemplate.WithIndex(bridgeBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 } });
if (pathElement.IsQueue() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{
PaintAddImageAsChild(
session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 } });
}
}
Sub6A3F61(session, pathElement, edi, height, pathPaintInfo, imageTemplate, sceneryImageTemplate, hasSupports);
uint16_t ax = 0;
if (pathElement.IsSloped())
{
ax = ((pathElement.GetSlopeDirection() + session.CurrentRotation) & 0x3) + 1;
}
auto supportType = Byte98D8A4[edges] == 0 ? 0 : 1;
PathASupportsPaintSetup(session, supportType, ax, height, imageTemplate, pathPaintInfo, nullptr);
height += 32;
if (pathElement.IsSloped())
{
height += 16;
}
PaintUtilSetGeneralSupportHeight(session, height, 0x20);
if (pathElement.IsQueue() || (pathElement.GetEdgesAndCorners() != 0xFF && hasSupports))
{
PaintUtilSetSegmentSupportHeight(session, SEGMENTS_ALL, 0xFFFF, 0);
return;
}
if (pathElement.GetEdgesAndCorners() == 0xFF)
{
PaintUtilSetSegmentSupportHeight(session, SEGMENT_C8 | SEGMENT_CC | SEGMENT_D0 | SEGMENT_D4, 0xFFFF, 0);
return;
}
PaintUtilSetSegmentSupportHeight(session, SEGMENT_C4, 0xFFFF, 0);
if (edges & 1)
{
PaintUtilSetSegmentSupportHeight(session, SEGMENT_CC, 0xFFFF, 0);
}
if (edges & 2)
{
PaintUtilSetSegmentSupportHeight(session, SEGMENT_D4, 0xFFFF, 0);
}
if (edges & 4)
{
PaintUtilSetSegmentSupportHeight(session, SEGMENT_D0, 0xFFFF, 0);
}
if (edges & 8)
{
PaintUtilSetSegmentSupportHeight(session, SEGMENT_C8, 0xFFFF, 0);
}
return surfaceBaseImageIndex;
}
void PathPaintPoleSupport(
PaintSession& session, const PathElement& pathElement, int16_t height, const FootpathPaintInfo& pathPaintInfo,
bool hasSupports, ImageId imageTemplate, ImageId sceneryImageTemplate)
static BoundBoxXYZ PathPaintGetBoundbox(const PaintSession& session, int32_t height, uint8_t edges)
{
PROFILED_FUNCTION();
// Rol edges around rotation
uint8_t edges = ((pathElement.GetEdges() << session.CurrentRotation) & 0xF)
| (((pathElement.GetEdges()) << session.CurrentRotation) >> 4);
CoordsXY boundBoxOffset = stru_98D804[edges].offset;
CoordsXY boundBoxSize = stru_98D804[edges].length;
uint8_t corners = (((pathElement.GetCorners()) << session.CurrentRotation) & 0xF)
| (((pathElement.GetCorners()) << session.CurrentRotation) >> 4);
uint16_t edi = edges | (corners << 4);
ImageIndex surfaceBaseImageIndex = pathPaintInfo.SurfaceImageId;
if (pathElement.IsSloped())
{
auto directionOffset
= ((pathElement.GetSlopeDirection() + session.CurrentRotation) & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK);
surfaceBaseImageIndex += 16 + directionOffset;
}
else
{
surfaceBaseImageIndex += Byte98D6E0[edi];
}
// Below Surface
const bool hasPassedSurface = (session.Flags & PaintSessionFlags::PassedSurface) != 0;
if (!hasPassedSurface)
{
boundBoxOffset.x = 3;
boundBoxOffset.y = 3;
boundBoxSize.x = 26;
boundBoxSize.y = 26;
boundBoxOffset = { 3, 3 };
boundBoxSize = { 26, 26 };
}
// By default, add 1 to the z bounding box to always clip above the surface
@@ -1002,77 +890,18 @@ void PathPaintPoleSupport(
// If we are on the same tile as a straight track, add the offset 2 so we
// can clip above gravel part of the track sprite
if (session.TrackElementOnSameHeight != nullptr)
if (session.TrackElementOnSameHeight != nullptr
&& session.TrackElementOnSameHeight->AsTrack()->GetTrackType() == TrackElemType::Flat)
{
if (session.TrackElementOnSameHeight->AsTrack()->GetTrackType() == TrackElemType::Flat)
{
boundingBoxZOffset = 2;
}
boundingBoxZOffset = 2;
}
if (!hasSupports || !hasPassedSurface)
{
PaintAddImageAsParent(
session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset.x, boundBoxOffset.y, height + boundingBoxZOffset }, { boundBoxSize.x, boundBoxSize.y, 0 } });
}
else
{
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
bridgeBaseImageIndex = ((pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ pathPaintInfo.BridgeImageId + 16;
}
else
{
bridgeBaseImageIndex = edges + pathPaintInfo.BridgeImageId;
}
PaintAddImageAsParent(
session, imageTemplate.WithIndex(bridgeBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 } });
if (pathElement.IsQueue() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{
PaintAddImageAsChild(
session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height },
{ { boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 } });
}
}
Sub6A3F61(
session, pathElement, edi, height, pathPaintInfo, imageTemplate, sceneryImageTemplate,
hasSupports); // TODO: arguments
uint16_t ax = 0;
if (pathElement.IsSloped())
{
ax = 8;
}
uint8_t supports[] = {
6,
8,
7,
5,
};
for (int8_t i = 3; i > -1; --i)
{
if (!(edges & (1 << i)))
{
// Only colour the supports if not already remapped (e.g. ghost remap)
auto supportColour = pathPaintInfo.SupportColour;
if (supportColour != COLOUR_NULL && !imageTemplate.IsRemap())
{
imageTemplate = ImageId().WithPrimary(supportColour);
}
PathBSupportsPaintSetup(session, supports[i], ax, height, imageTemplate, pathPaintInfo);
}
}
return BoundBoxXYZ({ boundBoxOffset, height + boundingBoxZOffset }, { boundBoxSize, 0 });
}
static void PathPaintSegmentSupportHeight(
PaintSession& session, const PathElement& pathElement, int32_t height, uint8_t edges, bool hasSupports)
{
height += 32;
if (pathElement.IsSloped())
{
@@ -1115,3 +944,124 @@ void PathPaintPoleSupport(
PaintUtilSetSegmentSupportHeight(session, SEGMENT_C8, 0xFFFF, 0);
}
}
void PathPaintBoxSupport(
PaintSession& session, const PathElement& pathElement, int32_t height, const FootpathPaintInfo& pathPaintInfo,
bool hasSupports, ImageId imageTemplate, ImageId sceneryImageTemplate)
{
PROFILED_FUNCTION();
auto [edges, corners] = PathPaintGetRotatedEdgesAndCorners(session, pathElement);
uint16_t edi = edges | (corners << 4);
auto surfaceBaseImageIndex = PathPaintGetBaseImage(session, pathElement, pathPaintInfo, edi);
auto boundbox = PathPaintGetBoundbox(session, height, edges);
const bool hasPassedSurface = (session.Flags & PaintSessionFlags::PassedSurface) != 0;
if (!hasSupports || !hasPassedSurface)
{
PaintAddImageAsParent(session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height }, boundbox);
}
else
{
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
auto directionOffset = (pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
bridgeBaseImageIndex = pathPaintInfo.BridgeImageId + 51 + directionOffset;
}
else
{
bridgeBaseImageIndex = EnumValue(PathSupportOrientation[edges]) + pathPaintInfo.BridgeImageId + 49;
}
PaintAddImageAsParent(session, imageTemplate.WithIndex(bridgeBaseImageIndex), { 0, 0, height }, boundbox);
if (pathElement.IsQueue() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{
PaintAddImageAsChild(session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height }, boundbox);
}
}
Sub6A3F61(session, pathElement, edi, height, pathPaintInfo, imageTemplate, sceneryImageTemplate, hasSupports);
Direction slopeDirection{};
if (pathElement.IsSloped())
{
slopeDirection = ((pathElement.GetSlopeDirection() + session.CurrentRotation) & 0x3);
}
PathBoxSupportsPaintSetup(
session, PathSupportOrientation[edges], pathElement.IsSloped(), slopeDirection, height, imageTemplate, pathPaintInfo);
PathPaintSegmentSupportHeight(session, pathElement, height, edges, hasSupports);
}
void PathPaintPoleSupport(
PaintSession& session, const PathElement& pathElement, int16_t height, const FootpathPaintInfo& pathPaintInfo,
bool hasSupports, ImageId imageTemplate, ImageId sceneryImageTemplate)
{
PROFILED_FUNCTION();
auto [edges, corners] = PathPaintGetRotatedEdgesAndCorners(session, pathElement);
uint16_t edi = edges | (corners << 4);
auto surfaceBaseImageIndex = PathPaintGetBaseImage(session, pathElement, pathPaintInfo, edi);
auto boundbox = PathPaintGetBoundbox(session, height, edges);
// Below Surface
const bool hasPassedSurface = (session.Flags & PaintSessionFlags::PassedSurface) != 0;
if (!hasSupports || !hasPassedSurface)
{
PaintAddImageAsParent(session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height }, boundbox);
}
else
{
ImageIndex bridgeBaseImageIndex;
if (pathElement.IsSloped())
{
bridgeBaseImageIndex = ((pathElement.GetSlopeDirection() + session.CurrentRotation)
& FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)
+ pathPaintInfo.BridgeImageId + 16;
}
else
{
bridgeBaseImageIndex = edges + pathPaintInfo.BridgeImageId;
}
PaintAddImageAsParent(session, imageTemplate.WithIndex(bridgeBaseImageIndex), { 0, 0, height }, boundbox);
if (pathElement.IsQueue() || (pathPaintInfo.RailingFlags & RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS))
{
PaintAddImageAsChild(session, imageTemplate.WithIndex(surfaceBaseImageIndex), { 0, 0, height }, boundbox);
}
}
Sub6A3F61(
session, pathElement, edi, height, pathPaintInfo, imageTemplate, sceneryImageTemplate,
hasSupports); // TODO: arguments
MetalSupportPlace supports[] = {
MetalSupportPlace::TopRightSide,
MetalSupportPlace::BottomRightSide,
MetalSupportPlace::BottomLeftSide,
MetalSupportPlace::TopLeftSide,
};
for (int8_t i = 3; i > -1; --i)
{
if (!(edges & (1 << i)))
{
// Only colour the supports if not already remapped (e.g. ghost remap)
auto supportColour = pathPaintInfo.SupportColour;
if (supportColour != COLOUR_NULL && !imageTemplate.IsRemap())
{
imageTemplate = ImageId().WithPrimary(supportColour);
}
PathPoleSupportsPaintSetup(session, supports[i], pathElement.IsSloped(), height, imageTemplate, pathPaintInfo);
}
}
PathPaintSegmentSupportHeight(session, pathElement, height, edges, hasSupports);
}