From 046db53857f5b7cd33e4f1aa3c8ce136ed6e2f01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 27 May 2025 18:17:22 +0900 Subject: [PATCH] Fix carousel not correctly handling traversal when current selection is filtered away Closes https://github.com/ppy/osu/issues/33215. --- osu.Game/Graphics/Carousel/Carousel.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Carousel/Carousel.cs b/osu.Game/Graphics/Carousel/Carousel.cs index 31c95f6930..a93748b514 100644 --- a/osu.Game/Graphics/Carousel/Carousel.cs +++ b/osu.Game/Graphics/Carousel/Carousel.cs @@ -518,19 +518,20 @@ namespace osu.Game.Graphics.Carousel // Position transfer won't happen unless we invalidate this. displayedRange = null; - // The case where no items are available for display yet. + Selection prevKeyboard = currentKeyboardSelection; + + // Importantly, we also reset the `Selection` to the most basic state. + // Removing the index and carousel item here is important to ensure we are aware of if a selection has been filtered away. + // If it hasn't been filtered, the full details will be re-populated just below in the loop. + currentKeyboardSelection = new Selection(currentKeyboardSelection.Model); + currentSelection = new Selection(currentSelection.Model); + if (carouselItems == null) - { - currentKeyboardSelection = new Selection(); - currentSelection = new Selection(); return; - } CarouselItem? lastVisible = null; int count = carouselItems.Count; - Selection prevKeyboard = currentKeyboardSelection; - // We are performing two important operations here: // - Update all Y positions. After a selection occurs, panels may have changed visibility state and therefore Y positions. // - Link selected models to CarouselItems. If a selection changed, this is where we find the relevant CarouselItems for further use. @@ -549,7 +550,7 @@ namespace osu.Game.Graphics.Carousel // If a keyboard selection is currently made, we want to keep the view stable around the selection. // That means that we should offset the immediate scroll position by any change in Y position for the selection. - if (prevKeyboard.YPosition != null && currentKeyboardSelection.YPosition != prevKeyboard.YPosition) + if (prevKeyboard.YPosition != null && currentKeyboardSelection.YPosition != null && currentKeyboardSelection.YPosition != prevKeyboard.YPosition) Scroll.OffsetScrollPosition((float)(currentKeyboardSelection.YPosition!.Value - prevKeyboard.YPosition.Value)); }