diff --git a/src/openrct2/paint/Supports.cpp b/src/openrct2/paint/Supports.cpp index df3b00ac0b..a168ceac71 100644 --- a/src/openrct2/paint/Supports.cpp +++ b/src/openrct2/paint/Supports.cpp @@ -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; diff --git a/src/openrct2/paint/Supports.h b/src/openrct2/paint/Supports.h index ac86384258..42e5f471bc 100644 --- a/src/openrct2/paint/Supports.h +++ b/src/openrct2/paint/Supports.h @@ -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); diff --git a/src/openrct2/paint/tile_element/Paint.Path.cpp b/src/openrct2/paint/tile_element/Paint.Path.cpp index 1730e47a38..27bab642e3 100644 --- a/src/openrct2/paint/tile_element/Paint.Path.cpp +++ b/src/openrct2/paint/tile_element/Paint.Path.cpp @@ -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(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(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(STR_RIDE_ENTRANCE_NAME); - ride->FormatNameTo(ft); - } - else - { - ft.Add(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 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); +}