1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-21 02:59:53 +08:00

Merge pull request #33160 from peppy/carousel-animation-fixes

Fix multiple inconsistencies in beatmap carousel animations
This commit is contained in:
Bartłomiej Dach
2025-05-16 13:20:56 +02:00
committed by GitHub
Unverified
+44 -14
View File
@@ -623,7 +623,7 @@ namespace osu.Game.Graphics.Carousel
if (c.Item == null)
continue;
float normalisedDepth = (float)(Math.Abs(selectedYPos - c.DrawYPosition) / DrawHeight);
float normalisedDepth = (float)(Math.Abs(selectedYPos - c.Item.CarouselYPosition) / DrawHeight);
Scroll.Panels.ChangeChildDepth(panel, c.Item.DepthLayer + normalisedDepth);
if (c.DrawYPosition != c.Item.CarouselYPosition)
@@ -695,6 +695,12 @@ namespace osu.Game.Graphics.Carousel
{
var carouselPanel = (ICarouselPanel)panel;
if (carouselPanel.Item == null)
{
// Item is null when a panel is already fading away from existence; should be ignored for tracking purposes.
continue;
}
// The case where we're intending to display this panel, but it's already displayed.
// Note that we **must compare the model here** as the CarouselItems may be fresh instances due to a filter operation.
//
@@ -710,7 +716,7 @@ namespace osu.Game.Graphics.Carousel
}
// If the new display range doesn't contain the panel, it's no longer required for display.
expirePanelImmediately(panel);
expirePanel(panel);
}
// Add any new items which need to be displayed and haven't yet.
@@ -721,12 +727,36 @@ namespace osu.Game.Graphics.Carousel
if (drawable is not ICarouselPanel carouselPanel)
throw new InvalidOperationException($"Carousel panel drawables must implement {typeof(ICarouselPanel)}");
carouselPanel.DrawYPosition = item.CarouselYPosition;
carouselPanel.Item = item;
Scroll.Add(drawable);
}
if (toDisplay.Any())
{
// To make transitions of items appearing in the flow look good, do a pass and make sure newly added items spawn from
// just beneath the *current interpolated position* of the previous panel.
var orderedPanels = Scroll.Panels
.OfType<ICarouselPanel>()
.Where(p => p.Item != null)
.OrderBy(p => p.Item!.CarouselYPosition)
.ToList();
for (int i = 0; i < orderedPanels.Count; i++)
{
var panel = orderedPanels[i];
if (toDisplay.Contains(panel.Item!))
{
// Don't apply to the last because animating the tail of the list looks bad.
// It's usually off-screen anyway.
if (i > 0 && i < orderedPanels.Count - 1)
panel.DrawYPosition = orderedPanels[i - 1].DrawYPosition;
else
panel.DrawYPosition = panel.Item!.CarouselYPosition;
}
}
}
// Update the total height of all items (to make the scroll container scrollable through the full height even though
// most items are not displayed / loaded).
if (carouselItems.Count > 0)
@@ -738,13 +768,18 @@ namespace osu.Game.Graphics.Carousel
Scroll.SetLayoutHeight(0);
}
private static void expirePanelImmediately(Drawable panel)
private void expirePanel(Drawable panel)
{
panel.FinishTransforms();
panel.Expire();
var carouselPanel = (ICarouselPanel)panel;
// expired panels should have a depth behind all other panels to make the transition not look weird.
Scroll.Panels.ChangeChildDepth(panel, panel.Depth + 1024);
panel.FadeOut(150, Easing.OutQuint);
panel.MoveToX(panel.X + 100, 200, Easing.Out);
panel.Expire();
carouselPanel.Item = null;
carouselPanel.Selected.Value = false;
carouselPanel.KeyboardSelected.Value = false;
@@ -801,12 +836,7 @@ namespace osu.Game.Graphics.Carousel
base.OffsetScrollPosition(offset);
foreach (var panel in Panels)
{
var c = (ICarouselPanel)panel;
Debug.Assert(c.Item != null);
c.DrawYPosition += offset;
}
((ICarouselPanel)panel).DrawYPosition += offset;
}
public override void Clear(bool disposeChildren)